In this tutorial, I will make tutorial for making millis() function that will return number of millisecond since AVR microcontrollers began executing program. This function is like millis() function on Arduino. I will use ATmega16 and CodeVisionAVR for this tutorial. First, you have to make a variable that will hold the value of millisecond. I declared this variable as volatile because the value of this variable will be changed inside ISR.
// Store value of millisecond since uC started volatile unsigned long millis_value;
Next, Setup timer 0 (or another timer if you wish) to generate interrupt every 1 ms. I am using timer 0 on CTC mode to count up from 0 to the value of OCR0 register. The prescaler that I use is 64 with 16 MHz CPU clock. To calculate the OCR0 register for 1ms compare match, we can use this formula OCRx = ((T x Fcpu) / N) - 1. Where T is the desired compare match value in second (1ms = 0.001s), Fcpu in Hz is 16,000,000 and N is prescaler (64). The OCR0 value will be 0xF9. To generate code for this settings we will use CodeWizardAVR. This is the settings for timer 0:
Copy this lines of code from CodeWidardAVR preview to main function. This codes is used for initializing timer 0 and timer 0 interrupt.
void main(void) { /* Set timer 0 on CTC mode that will compare match every 1ms */ // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250.000 kHz // Mode: CTC top=OCR0 // OC0 output: Disconnected TCCR0 = 0x0B; TCNT0 = 0x00; OCR0 = 0xF9; /* Enable compare match interrupt for timer 0 */ // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK = 0x02; /* Enable global interrupt */ #asm("sei") while (1); }
After that, add this ISR code from CodeWizardAVR preview. This code will increment millis_value every 1ms.
// Timer 0 output compare interrupt service routine interrupt [TIM0_COMP] void timer0_comp_isr(void) { // Increment millisecond every 1ms millis_value++; }
To get the millis_value we can make a function like this:
// This function is used to get millis_value unsigned long millis() { unsigned long m; // Disable interrupts while we read millis_value or we might get an // inconsistent value (e.g. in the middle of a write to millis_value) #asm("cli") m = millis_value; #asm("sei") return m; }
We need to disable interrupt while read millis_value to avoid inconsistent value (in case when in the middle of a write to millis_value).
Fantastic blog you got here,I enjoyed reading some of your posts.
ReplyDeleteOET Coaching for Dentists in Adelaide
OET Coaching for Nurses in Adelaide
OET Coaching for Nurses in Melbourne
OET Coaching for Nurses in Melbourne
ADC Coaching for Dentist in Adelaide
AMC Coaching for Doctors in Adelaide
Thank you so much for reading my blog.
DeletePerfect!!! What I can say in this article is very important to be written as it may help everybody to get awareness. Good job done.
ReplyDeleteOET for Nurses in Adelaide | oet in Adelaide
Excellent tutorial I wish you can make more tutorial like this I will port this example to mikroc
ReplyDeleteHi
ReplyDeletewhy OCR0 = 0xF9; and not OCR0 = 0xFA; ??
0+250 = FA
working 100%... thanxs bro
ReplyDelete