In: Computer Science
Q2 (Timer – interval or tick setting)
Modify either the example program Timer0_Ex.c or Timer0_Ex_10ms.c (both available on Sulis under \Example Programs) to toggle the bits of PORTD at exactly 40ms intervals – no approximations allowed – but this time using Timer2 in place of Timer0. You may assume that the ATMega328P is clocked at 16MHz, but you may need to modify the clock division ratio and the number of timer interrupts used for the required delay (timecount0). The structure of the program will be the same. Refer to the ATMega328P datasheet for descriptions of the ATMega328P Timer2 registers.
here is the code to be modified
/* * Timer0_Ex.c * * Created: 09/10/2013 23:37:12 * Author: n/a */ #include #include unsigned int timecount0; int main(void) { //Set PortD to all outputs because LEDs are connected to this PORT DDRD = 0xff; // 0xff = 0b11111111; all ones PORTD = 0; // Initialise to all off timecount0 = 0; // Initialise the overflow count. Note its scope TCCR0B = (5<= 40) // 40 * 12.5ms = 500ms { PORTD = ~PORTD; // Toggle all the bits timecount0 = 0; // Restart the overflow counter } }
---------------------------------------------------------------------------------------------------------------------------------------------------
here is the other programme?
/* * Timer0_Ex.c * * Created: 09/10/2013 23:37:12 * Author: n/a */ #include <avr/io.h> #include <avr/interrupt.h> #define DLY_2_ms 141 /* We use 141 because we want Timer0 to count 125 counts, and 256-141 = 125 */ #define COUNT_FOR_10ms 5 unsigned int timecount0; int main(void) { /* Set PortD to all outputs because LEDs are connected to this PORT */ DDRD = 0xff; /* 0xff = 0b11111111; all ones */ PORTD = 0; /* Initialise to all off */ timecount0 = 0; /* Initialise the overflow count. Note its scope */ TCCR0B = (4<<CS00); /* Set T0 Source = Clock (16MHz)/256 and put Timer in Normal mode */ TCCR0A = 0; /* Not strictly necessary as these are the reset states but it's good */ /* practice to show what you're doing */ TCNT0 = DLY_2_ms; /* Recall: 256-61 = 195 & 195*64us = 12.48ms, approx 12.5ms */ TIMSK0 = (1<<TOIE0); /* Enable Timer 0 interrupt */ sei(); /* Global interrupt enable (I=1) */ while(1) ; /* Do nothing loop */ } ISR(TIMER0_OVF_vect) { TCNT0 = DLY_2_ms; /* TCNT0 needs to be set to the start point each time */ ++timecount0; /* count the number of times the interrupt has been reached */ if (timecount0 >= COUNT_FOR_10ms) /* 5 * 2ms = 10ms */ { PORTD = ~PORTD; /* Toggle all the bits */ timecount0 = 0; /* Restart the overflow counter */ } }
Please upvote , comment for any query . Thanks.
Note : check attached image for output and program . AVR C program compiled and tested in Programmers notepad.
Remark : LED will blink so fast you can not see turn on and off operation properly .
Program plan :
Program :
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
volatile int count=0; //count variable to increase in ISR
int main(void)
{
DDRD|=(1<<DDD5);
cli(); // disable global interrupts
// initialize Timer2
// turn on CTC mode:
TCCR2A = (1 << WGM21);
// Set CS10, CS11 and CS12 bits for 1024 prescaler:
/*
16000000/1024=15625 for 1second
15625/1000=15.625 for 1ms
15.625*40 = 625 for 40 ms
OCR2A can have maximum 255
OCR2A =125 when interrupt occurs 5 times it will be
625 and 40 ms
*/
TCCR2B = (1 << CS22) | (1 << CS21) | (1 <<
CS20);
TIMSK2 |= (1 << OCIE2A);
OCR2A = 125; // This should give about a 10ms interrupt
sei(); // enable global interrupts.
}
ISR(TIMER2_COMPA_vect)
{
count++; //increment count by 1
if(count>=5) //when 5th interrupt occured
{
PORTD^=(1<<PD5); //toggle PORTD pin 5
count=0; //set count =0
}
}
Program :