In this section, we provide several representative examples of using the timer system for various applications. We will provide examples of using the timer system to generate a prescribed delay, to generate a PWM signal, and to capture an input event.
7.10.1 PRECISION DELAY IN C
In this example, we program the ATmega328 to provide a delay of some number of 6.55 ms interrupts.
The Timer 0 overflow is configured to occur every 6.55 ms. The overflow flag is used as a “clock tick” to generate a precision delay. To create the delay the microcontroller is placed in a while loop waiting for the prescribed number of Timer 0 overflows to occur.
//Function prototypes
void delay(unsigned int number_of_6_55ms_interrupts);
void init_timer0_ovf_interrupt(void);
void timer0_interrupt_isr(void);
//interrupt handler definition
#pragma interrupt_handler timer0_interrupt_isr:17 //door profile data
//*************************************************************************
//int_timer0_ovf_interrupt(): The Timer0 overflow interrupt is being //employed as a time base for a master timer for this project.
//The ceramic resonator operating at 10 MHz is divided by 256.
//The 8-bit Timer0 register (TCNT0) overflows every 256 counts //or every 6.55 ms.
//*************************************************************************
void init_timer0_ovf_interrupt(void) {
TCCR0B = 0x04; //divide timer0 timebase by 256, overfl. occurs every 6.55ms
TIMSK0 = 0x01; //enable timer0 overflow interrupt asm("SEI"); //enable global interrupt
}
//*************************************************************************
//*************************************************************************
//timer0_interrupt_isr:
//Note: Timer overflow 0 is cleared by hardware when executing the //corresponding interrupt handling vector.
//*************************************************************************
void timer0_interrupt_isr(void) {
input_delay++; //input delay processing }
//*************************************************************************
//*************************************************************************
//delay(unsigned int num_of_6_55ms_interrupts): this generic delay function //provides the specified delay as the number of 6.55 ms "clock ticks" from //the Timer0 interrupt.
//Note: this function is only valid when using a 10 MHz crystal or ceramic // resonator
//*************************************************************************
void delay(unsigned int number_of_6_55ms_interrupts) {
TCNT0 = 0x00; //reset timer0
input_delay = 0;
while(input_delay <= number_of_6_55ms_interrupts) {
; } }
//*************************************************************************
7.10.2 PULSE WIDTH MODULATION IN C
The function provided below is used to configure output compare channel B to generate a pulse width modulated signal. An analog voltage provided to ADC Channel 3 is used to set the desired duty cycle from 50 to 100 percent. Note how the PWM ramps up from 0 to the desired speed.
//Function Prototypes
void PWM(unsigned int PWM_incr) {
unsigned int Open_Speed_int;
float Open_Speed_float;
int gate_position_int;
PWM_duty_cycle = 0;
InitADC(); //Initialize ADC
//Read "Open Speed" volt Open_Speed_int = ReadADC(0x03); //setting PA3
//Open Speed Setting unsigned int //Convert to max duty cycle //setting
//0 VDC = 50% = 127, //5 VDC = 100% =255 Open_Speed_float = ((float)(Open_Speed_int)/(float)(0x0400));
//Convert volt to PWM constant //127-255
Open_Speed_int = (unsigned int)((Open_Speed_float * 127) + 128.0);
//Configure PWM clock
TCCR1A = 0xA1; //freq = resonator/510 = 10MHz/510 //freq = 19.607 kHz
TCCR1B = 0x01; //no clock source division
PWM_duty_cycle = 0; //Initiate PWM duty cycle //variables
OCR1BH = 0x00;
OCR1BL = (unsigned char)(PWM_duty_cycle);//Set PWM duty cycle CH B to 0%
//Ramp up to Open Speed in 1.6s OCR1BL = (unsigned char)(PWM_duty_cycle);//Set PWM duty cycle CH B while (PWM_duty_cycle < Open_Speed_int)
{
if(PWM_duty_cycle < Open_Speed_int) //Increment duty cycle PWM_duty_cycle=PWM_duty_cycle + PWM_open_incr;
//Set PWM duty cycle CH B OCR1BL = (unsigned char)(PWM_duty_cycle);
}
//Gate continues to open at specified upper speed (PA3) :
: :
//*************************************************************************
7.10.3 INPUT CAPTURE MODE IN C
This example was developed by Julie Sandberg, BSEE and Kari Fuller, BSEE at the University of Wyoming as part of their senior design project. In this example, the input capture channel is being used to monitor the heart rate (typically 50-120 beats per minute) of a patient. The microcontroller is set to operate at an internal clock frequency of 1 MHz. Timer/Counter channel 1 is used in this example.
//*************************************************************************
//initialize_ICP_interrupt: Initialize Timer/Counter 1 for input capture //*************************************************************************
void initialize_ICP_interrupt(void) {
TIMSK=0x20; //Allows input capture interrupts
SFIOR=0x04; //Internal pull-ups disabled
TCCR1A=0x00; //No output comp or waveform //generation mode
TCCR1B=0x45; //Capture on rising edge,
//clock prescalar=1024
TCNT1H=0x00; //Initially clear timer/counter 1 TCNT1L=0x00;
asm("SEI"); //Enable global interrupts }
//*************************************************************************
void Input_Capture_ISR(void) {
if(first_edge==0) {
ICR1L=0x00; //Clear ICR1 and TCNT1 on first edge ICR1H=0x00;
TCNT1L=0x00;
TCNT1H=0x00;
first_edge=1;
} else
{
ICR1L=TCNT1L; //Capture time from TCNT1 ICR1H=TCNT1H;
TCNT1L=0x00;
TCNT1H=0x00;
first_edge=0;
}
heart_rate(); //Calculate the heart rate
TIFR=0x20; //Clear the input capture flag
asm("RETI"); //Resets the I flag to allow //global interrupts
}
//*************************************************************************
void heart_rate(void) {
if(first_edge==0) {
time_pulses_low = ICR1L; //Read 8 low bits first time_pulses_high = ((unsigned int)(ICR1H << 8));
time_pulses = time_pulses_low | time_pulses_high;
if(time_pulses!=0) //1 counter increment = 1.024 ms
{ //Divide by 977 to get seconds/pulse
HR=60/(time_pulses/977); //(secs/min)/(secs/beat) =bpm }
else { HR=0;
} } else
{ HR=0;
} }
//*************************************************************************