This post is relevent to my previous post of ADC-timer delay problem.
I later realised that the problem is due to LCD.
My configuration:
ATMega8 with Internal 8Mhz osc
Timer 2 async with 32.768 Khz external crystal
16x2LCD and ADC connected.
In the code, i have marked "PROBLEMATIC area".
If i comment the code, i get 1400ms exact delay. (I have corrected the error too in ISR)
But if i write the Problematic area code, then i get 670ms delay instead of 1400ms. I have placed a endless loop in ISR, which Clears PORTC,5 to indicate the delay.
This is my code:
#include#include #include #include "lcd/lcd.h" #include "calibration.h" #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif //long glb_ms_counter; long glb_max_ms; long error_corrector; void Init_Timer2_CTC(void); void CheckCurrentLimit(void); void Read_and_Print_Current(void); ISR (TIMER2_COMP_vect, ISR_BLOCK) { //will be called every 1ms static long glb_ms_counter; glb_ms_counter ++; error_corrector++; if(error_corrector==125) { error_corrector=0; glb_ms_counter=glb_ms_counter+3; } if(glb_ms_counter==glb_max_ms) { sbi(DDRC,5); cbi(PORTC,5); while(1){} } } void Init_Timer2_CTC(void) { sbi(ASSR,AS2); // External Crystal of 32.768KHz will be used TCNT2=0x00; OCR2=0x20; //OCR2=21; TCCR2=0x09; // CTC + 0 presclar TIMSK|=0x80; // CTC interrupt SREG |= 0x80; //global interrupt while (ASSR & ((1 << TCN2UB) | (1 << TCR2UB) | (1 << OCR2UB))); } int main(void) { _delay_ms(1000); sbi(DDRC,5); sbi(PORTC,5); sbi(DDRC,4); sbi(PORTC,4); OSCCAL_Calibrate(); //glb_ms_counter=0; glb_max_ms=1400; error_corrector=0; lcdInit(); ADMUX = _BV(ADLAR) | _BV(REFS1) | _BV(REFS0) | _BV(MUX1) | _BV(MUX0); //avrfreaks ADCSRA=0X86; ADCSRA |= _BV(ADSC); while (ADCSRA & (1 << ADSC)); Init_Timer2_CTC(); sbi(DDRC,4); cbi(PORTC,4); while(1){ Read_and_Print_Current(); CheckCurrentLimit(); _delay_us(200); } return 0; } void Read_and_Print_Current(void) { double input_current; char val1,val2,val3; double a; ADCSRA |= _BV(ADSC); while (ADCSRA & (1 << ADSC)); a=ADCH; input_current=(a*2.55)/255; val1=(int)(input_current * 1) + 48; val2=(int)(input_current * 10) % 10 + 48; val3=(int)(input_current * 100) %10 + 48; //********************* //Problematic area starts here lcdGotoXY(0,0); lcdDataWrite(val1); lcdPrintData(".",1); lcdDataWrite(val2); lcdDataWrite(val3); lcdPrintData(" ",1); lcdPrintData("Amp",3); lcdPrintData(" ",8); //Problematic area ends here //********************** _delay_us(500); } void CheckCurrentLimit(void) { double current; double input_current; double backup_ISet; double backup_T; double Idif; ADCSRA |= _BV(ADSC); while (ADCSRA & (1 << ADSC)); current=ADCH; input_current=(current*2.55)/255; } ////////////////LCD/////////////////////// void lcdGotoXY(u08 x, u08 y) { register u08 DDRAMAddr; // remap lines into proper order switch(y) { case 0: DDRAMAddr = LCD_LINE0_DDRAMADDR+x; break; case 1: DDRAMAddr = LCD_LINE1_DDRAMADDR+x; break; case 2: DDRAMAddr = LCD_LINE2_DDRAMADDR+x; break; case 3: DDRAMAddr = LCD_LINE3_DDRAMADDR+x; break; default: DDRAMAddr = LCD_LINE0_DDRAMADDR+x; } // set data address lcdControlWrite(1<<LCD_DDRAM | DDRAMAddr); } void lcdDataWrite(u08 data) { // write a data byte to the display #ifdef LCD_PORT_INTERFACE lcdBusyWait(); // wait until LCD not busy sbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "data" cbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "write" #ifdef LCD_DATA_4BIT // 4 bit write sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit) outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) ); // output data, high 4 bits LCD_DELAY; // wait LCD_DELAY; // wait cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line LCD_DELAY; // wait LCD_DELAY; // wait sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) ); // output data, low 4 bits LCD_DELAY; // wait LCD_DELAY; // wait cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #else // 8 bit write sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line outb(LCD_DATA_DDR, 0xFF); // set data I/O lines to output (8bit) outb(LCD_DATA_POUT, data); // output data, 8bits LCD_DELAY; // wait LCD_DELAY; // wait cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line #endif // leave data lines in input mode so they can be most easily used for other purposes #ifdef LCD_DATA_4BIT outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit) outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit) #else outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit) outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit) #endif #else // memory bus write //sbi(MCUCR, SRW); // enable RAM waitstate lcdBusyWait(); // wait until LCD not busy *((volatile unsigned char *) (LCD_DATA_ADDR)) = data; //cbi(MCUCR, SRW); // disable RAM waitstate #endif } void lcdPrintData(char* data, u08 nBytes) { register u08 i; // check to make sure we have a good pointer if (!data) return; // print data for(i=0; i Quote: