|
Post by arvind on Oct 30, 2005 5:18:39 GMT 10
Am beginner to programming in avr's. I have basically written a program using timer1 of avr to blink an led. It stays on for 1 second and off for the same time..according to the program. But during my simulation and also when i test it on atmega8 it seems to be taking longer than 1 second..almost 20seconds. Is something wrong with my code?? Here is the code: #include<inttypes.h> #include<avr/io.h> #include<avr/interrupt.h> #include<avr/signal.h>
uint16_t tcount=0;
SIGNAL (SIG_OUTPUT_COMPARE1A) { PORTD^=0xFF; OCR1A=OCR1A+15625; }
int main(void) { DDRD=0xFF; PORTD=0x00; TCCR1A=0x00; TCCR1B=0x05; //OCR1A=15625; TIMSK=0x10; sei(); while(1); }
|
|
|
Post by Dingo on Oct 30, 2005 18:42:44 GMT 10
Firstly what clock source are you using?
|
|
|
Post by Robotman on Nov 2, 2005 12:19:47 GMT 10
Here's a few things I've noticed about the code:
1. The TCNT1 register is not initialized to a known value (i.e. zero) - and remember to access this 16-bit register *high byte first*. I will make an educated guess that the C code presented here is writing low-byte first 2. The OCR1A register is not initialized to a known value - this is also a 16-bit register and must be written to *high byte first*. Same comments as in (1) 3. Based upon the value of 15625 that I see in the code, and the fact that you are using clkIO/1024 (via TCCR1B), I figure you are clocking the Atmega8 at 16 MHz. I assume therefore you are using the -16PC version of the chip.
I hope this helps you, arvind
|
|
|
Post by Robotman on Nov 2, 2005 12:31:14 GMT 10
P.S.
Just to clear up the matter of reading/writing the 16-bit timer:
Read using low-byte first. Write using high-byte first.
It would be best to use inline assembler instructions to do the "backwards" high-byte-first writing.
Page 77 of the ATmega8 manual describes the complete operation in detail.
|
|
|
Post by Robotman on Nov 2, 2005 13:03:55 GMT 10
P.P.S.
But then, you don't have to use inline assembler.
Something like the following would work alright:
typedef unsigned char *pByte; pByte OCR1A = 0x4A; *(OCR1A + 1) = hi_byte; *OCR1A = lo_byte;
Then to read, simply use:
typedef unsigned short *pWord; word = *(pWord)OCR1A;
Personally, I prefer to do all of my I/O in assembler, and then call these functions from higher-level code (usually in C). Bit-banging is so much easier (and easier to optimize) using assembler. This also holds true for interrupt handling - higher level functions can then be called after doing all the low-level bit twiddling and register stuffing housekeeping that is usually required.
|
|
|
Post by htj on Jan 14, 2011 14:21:27 GMT 10
|
|