Recently i have been thinking about many things such as(nested timer interrupts and countdown made using timer1). Although i have been partially successful in creating a countdown timer but i have no idea on how to use the nested interrupts. If have checked the site for quite some time but not got anything of my use.
#include <avr/io.h> #include <stdio.h> #include <string.h> #include <stdbool.h> #include <avr/interrupt.h> #include "I2C_Master_H_file.h" #include "LCD16x2_4Bit.h" #define Device_Write_address 0xD0 /* Define RTC DS1307 slave write address */ #define Device_Read_address 0xD1 /* Make LSB bit high of slave address for read */ #define BUTTON1 PD0 // button switch connected to port B pin 1 #define BUTTON2 PD1 #define BUTTON3 PD2 #define LED1 PD3 // Drain #define LED2 PD7 // Pump #define DEBOUNCE_TIME 25 // time to wait while "de-bouncing" button #define LOCK_INPUT_TIME 300 // time to wait after a button press void init_ports_mcu() { DDRD &= ~(1<<PD0); //on/off manual button PORTD |= (1<<PD0); DDRD &= ~(1<<PD1); //sensor 1 button PORTD |= (1<<PD1); DDRD &= ~(1<<PD2); //sensor 2 button PORTD |= (1<<PD2); DDRD |= (1<<PD7); //pump PORTD &= ~(1<<PD7); DDRD |= (1<<PD3);//drain PORTD &= ~(1<<PD3); } unsigned char button_state_1() //button one { /* the button is pressed when BUTTON1 bit is clear */ if (!(PIND & (1<<BUTTON1))) { _delay_ms(DEBOUNCE_TIME); if (!(PIND & (1<<BUTTON1))) return 1; } return 0; } unsigned char button_state_2()//button two { /* the button is pressed when BUTTON1 bit is clear */ if (!(PIND & (1<<BUTTON2))) { _delay_ms(DEBOUNCE_TIME); if (!(PIND & (1<<BUTTON2))) return 1; } return 0; } unsigned char button_state_3()//button three { /* the button is pressed when BUTTON1 bit is clear */ if (!(PIND & (1<<BUTTON3))) { _delay_ms(DEBOUNCE_TIME); if (!(PIND & (1<<BUTTON3))) return 1; } return 0; } int second,minute,hour,day,date,month,year; #define degree_sysmbol 0xdf volatile uint8_t m=0; volatile uint8_t s=0; volatile uint8_t timer_running=0; void RTC_Read_Clock(char read_clock_address) { I2C_Start(Device_Write_address);/* Start I2C communication with RTC */ I2C_Write(read_clock_address); /* Write address to read */ I2C_Repeated_Start(Device_Read_address);/* Repeated start with device read address */ second = I2C_Read_Ack(); /* Read second */ minute = I2C_Read_Ack(); /* Read minute */ hour = I2C_Read_Nack(); /* Read hour with Nack */ I2C_Stop(); /* Stop i2C communication */ } void RTC_Read_Calendar(char read_calendar_address) { I2C_Start(Device_Write_address); I2C_Write(read_calendar_address); I2C_Repeated_Start(Device_Read_address); day = I2C_Read_Ack(); /* Read day */ date = I2C_Read_Ack(); /* Read date */ month = I2C_Read_Ack(); /* Read month */ year = I2C_Read_Nack(); /* Read the year with Nack */ I2C_Stop(); /* Stop i2C communication */ } void ADC_Init(){ DDRA = 0x00; /* Make ADC port as input */ ADCSRA = 0x87; /* Enable ADC, with freq/128 */ ADMUX = 0x40; /* Vref: Avcc, ADC channel: 0 */ } int ADC_Read(char channel) { ADMUX = 0x40 | (channel & 0x07); /* set input channel to read */ ADCSRA |= (1<<ADSC); /* Start ADC conversion */ while (!(ADCSRA & (1<<ADIF))); /* Wait until end of conversion by polling ADC interrupt flag */ ADCSRA |= (1<<ADIF); /* Clear interrupt flag */ _delay_ms(1); /* Wait a little bit */ return ADCW; /* Return ADC word */ } int main(void) { char Temperature[10]; float celsius; char buffer[40]; unsigned char n_led = 1; // LED number is on now init_ports_mcu(); I2C_Init(); /* Initialize I2C */ lcdinit(); /* Initialize LCD16x2 */ ADC_Init(); TCCR1B=(1<<WGM12)|(1<<CS12)|(1<<CS10); //CTC Mode prescaller 1024 OCR1A=976; TIMSK|=(1<<OCIE1A); lcd_print_xy(0, 0, "WELCOME"); _delay_ms(100); lcd_clear(); _delay_ms(500); while(1) { RTC_Read_Clock(0); /* Read clock with second add. i.e location is 0 */ sprintf(buffer, "%02x:%02x:%02x ", hour, minute, second); lcd_print_xy(0,0,buffer); RTC_Read_Calendar(3); /* Read calendar with day address i.e location is 3 */ sprintf(buffer, "%02x/NOV/%02x ", date, year); lcd_print_xy(0,11,buffer); lcd_print_xy(1, 0,"TEMPERATURE"); celsius = (ADC_Read(0)*4.88); celsius = (celsius/10.00); sprintf(Temperature,"%d%cC ", (int)celsius, degree_sysmbol); lcd_print_xy(1,12,Temperature); memset(Temperature,0,10); lcd_print_xy(2, 0, "LEVEL : 0 00:00"); lcd_print_xy(3, 0, "PUMP OFF DRAIN OFF"); //Here i have operated the switches with delay but they prevents the avr //from multitasking and hence countdown doesnt shows if (button_state_1()) // Manual ON/OFF { switch(n_led){ case 1: lcd_print_xy(2, 8, "0");//for the indication of 0th level lcd_print_xy(3, 0, "PUMP ON DRAIN OFF"); PORTD ^= (1<<LED1); // toggling the current state of the pin LED1. LED1 is turn off. break; n_led=0; // reset LED number break; } _delay_ms(LOCK_INPUT_TIME); } if (button_state_2()) //Washing button //will turn on both the outputs for 30secs and then turn them off { switch(n_led){ case 1: lcd_print_xy(2, 8, "1"); //for indication of 1st level lcd_print_xy(3, 0, "PUMP ON DRAIN ON "); PORTD |= (1<<LED1); // toggling the current state of the pin LED1. LED1 is turn off. PORTD |= (1<<LED2); _delay_ms(30000); //Time changer PORTD &= ~(1<<LED1); PORTD &= ~(1<<LED2); break; n_led=0; // reset LED number break; } _delay_ms(LOCK_INPUT_TIME); } if (button_state_3()) // Sensor input//will turn the LED1 for 4 mins and when there is 1 min left on the countdown then LED2 should lightup { switch(n_led){ case 1: lcd_print_xy(2, 8, "2");//for indication of second level lcd_print_xy(3, 0, "PUMP ON DRAIN OFF"); PORTD |= (1<<LED1); _delay_ms(4000); lcd_print_xy(3, 0, "PUMP ON DRAIN ON "); PORTD |= (1<<LED2); _delay_ms(2000); PORTD &= ~(1<<LED1); //after all this both of them should turn off PORTD &= ~(1<<LED2); break; //second press missing break; } _delay_ms(LOCK_INPUT_TIME); } } return (0); } ISR(TIMER1_COMPA_vect) // for the countdown timer { if(!timer_running) return; if(s==0) { if(m==0) { //off timer_running=0; } else { m--; s=59; } } else { s--; } }
Here i have four things running simultaneously an rtc date and time system , temperature readings , if any on the button is pressed then outputs should light up accordingly and when the outputs are turned on a countdown should also run stating the time left for the output to turn off.
Please help i have been struck on it for many hours.
Don't worry for the rtc date and time and temperature readings they work good.
Buttons also work but they hangs the avr and hence countdown and rtc time stops.
I am a little bit confused on where to place the countdown.