Tutorial 3 Timer/Counter with AVR Controller Exercise 1 - Getting started with AVR Timer In this task, we will get used to use Timer for blinking LEDs. For example, we will generate a square wave with the frequency of 1000 Hz. You need to choose the Timer that is appropriate, in normal counting mode and we will not use Interrupts. A. Calculation First of all, we need to perform a bit of calculation in advance to set the right Timer count for the timer. Use the following formula for that purpose: ππππππ‘ πππππ πΆππ’ππ‘ = ( 1 1 / ) − 1 2 π₯ ππππππ‘ πππππ’ππππ¦ πππππ πΆππππ πΉππππ’ππππ¦ For example, I am using the board with the external clock of 16Mhz, so I can get the timer count as ππππππ‘ πππππ πΆππ’ππ‘ = ( 1 1 16,000,000 / ) − 1= − 1 = π, πππ 2 π₯ 1000 16,000,000 2,000 Atmega328p has couple timers: o o TC0 – 8-bit timer (value counts from 0 to 28 − 1 = 255) TC1 – 16-bit timer (value counts from 0 to 216 − 1 = 65,535) With the timer count of 7,999, we cannot use the 8-bit timer but 16-bit timer instead. B. Programming and Testing 1. Create a new project as done in the Tutorial 1 – name it Tut31_Arduino 2. For this part we don’t need to connect any LEDs to the board but instead we can use the built-in LED of the board. This LED is connected to the Pin 13 of the header – and the Pin PB5 of the Atmega328p EEET2505 Ref: https://circuito.cdn.prismic.io/circuito/8e3a980f0f964cc539b4cbbba2654bb660db6f52_arduinouno-pinout-diagram.png 3. Type in the following code #include <avr/io.h> int main(void) { DDRB |= (1 << 5); // Set LED connected PORT B, Pin 5 as output TCCR1B |= (1 << CS10 ); // Set up timer1 (16 bit) while (1) { // Check timer value in if statement , true when count matches 0.5ms (half cycle) if ( TCNT1 >= 7999) { PORTB ^= (1 << 5); // Toggle the LED TCNT1 = 0; // Reset timer value } } } 4. Build and download the code onto the Arduino Uno, you should see the LED seems to turn ON all the time. This LED blinks quick than you can observe hence we need some instruments to observe the frequency. EEET2505 C. Measuring on Virtual Bench Note – this step we cannot do for this Semester 2021B yet. I still leave them here so you can review when you have chance. 1. Setup NI Virtual Bench a. Connect cables (power + USB) b. From My Computer -> Virtual Bench Drive 5. EEET2505 Connect the Logic Analyser to the pin where PB5 is connected, the pin labelled 13 in the header a. Use the Schematic to support the connection. b. Take two wires from the Logic Analyser – for example D0 and GND. Then plug to the pin 13 (PORTB5) and GND) c. The setup is as follows 6. Turn on Digital channel – Choose the pin that you want to observe (in my case is Digital 0) If the result is not shown yet, you can click on Auto setup and then adjust the scale. Then Adjust the scale by using your middle mouse by scrolling up and down until you receive a full waveform EEET2505 7. Read the measured frequency a. Turn on measurement b. Press the values that you wish to measure, for example Period, Duty cycle and Frequency c. Read the result So, we have successfully generated a 1000hz signal with Timer 1 of the AVR. This confirm the results from the code that was written earlier. Note – if you are using the Oscilloscope, you can apply the process given in the supporting video on Canvas to perform the measurement as done with the Virtual Bench above. EEET2505 D. Analysis For Timer to work, it is important for us to work with the two registers. In this part you will find yourself need to learn how to read and use the information from Datasheet of the Microcontroller since we will rely on it a lot. 1. The choice of Timer in this part. The 16-bit Timer 1 is chosen here. The microcontroller has other Timers that you can choose. YOU SHOULD ALSO GET FAMILIAR WITH THE Chapter about Timer 1 IN THE DATASHEET THAT DESCRIBE THIS TIMER 2. First, we need to configure the Timer. Few things to highlight here first. In this section we will use the Timer in its Normal Mode and with no prescaling at all a. You are required to read through the Modes of Operation part. For example, Page 161 of the Datasheet b. With that we need to set the register accordingly. Next you need to check out the Register Description at 20.14. For timer you need to configure 2 Register: TCCR1A (Timer/Counter1 Control Register A) and TTCR1B (Timer/Counter1 Control Register B). With the configuration above you need to check out the Table of configuration i. For Normal mode – we don’t need to set WGM10 and WGM11 (belong to TTCR1A) and WGM12 and WGM13 (belong to TTCR1B) ii. For Normal mode, we don’t have to set others bits belong to Compare Output Mode in the TTCR1A With i and ii -> we don’t have to set TTCR1A and they can have their default value after reset as 0x00 EEET2505 iii. For the non-pre-scaling, according to the table we need to set the CS10 as 1 in the TTCR1A With the above you then can set the TTCR1B TCCR1B |= (1 << CS10 ); // Set up timer1 (16 bit) 3. Next, once we have done the configuration for the normal mode, we need to set the top counter value via the counter value register TCNT1 (16-bit register combined from TCNT1H and TCNT1L) a. With the calculation earlier we can set the cap is at 7999 and use the conditional condition in C to check this. b. When the condition is met then the LED is toggle to indicate the timer is hit. c. Finally, we need to reset the timer value. if ( TCNT1 >= 7999) { PORTB ^= (1 << 5); // Toggle the LED TCNT1 = 0; // Reset timer value } EEET2505 Exercise 2 - Prescaled Timers (Hardware Approach) In the above task, we have used 16-bit timer TC1, which can hold a value in the range of 0 - 65535. In case we need to create a larger delay time, we can use the timer's prescaler – the internal circuit to divide the clock signals (by a power of two). To learn this, we will generate a square wave with the frequency of 1Hz (period = 1s) in this task – 0.5ms for ON and 0.5ms for OFF A. Calculation The formula to calculate the Timer count now includes the Prescale value ππππππ‘ πππππ πΆππ’ππ‘ = ( 1 ππππ ππππ / ) − 1 2 π₯ ππππππ‘ πππππ’ππππ¦ πππππ πΆππππ πΉππππ’ππππ¦ With the target frequency of 1Hz, we can get the Timer Count value with different prescaler values as below Prescaler Value 1 Target Timer Count Observation 16,000,000 − 2π₯1π₯1 The timer value is above the range of a 16-bit counter (0 – 63,535) 1 = 7,999,999 8 999,999 64 124,999 256 31,249 This can be used since it is within the range of 16-bit timer 1024 7811.5 Can be used but rounding can cause the slight difference in the time delay From the table, it can be seen the Timer Count value affect our decision to choose the prescaler value. From the table we can attempt to use the prescaler of 256 and use Timer Count of 31,249, which is in the range of the 16-bit counter. We will try these two in the code. In order to configure the Prescaler we need to configure the register Timer Counter TCCR1B. Three bits we need to pay attention is CS10 to CS12 (as seen in the datasheet) EEET2505 B. Programming and Testing 1. Edit the code above to reflect the change #include <avr/io.h> int main(void) { DDRB |= (1 << 5); // Set LED as output //TCCR1B |= (1 << CS10 ); // Set up timer 1 (16 bit) TCCR1B |= (1 << CS12 ); // Set up timer with the prescaler of 256 while (1) { // Check timer value in if statement , true when count matches 0.5s (half cycle) //if ( TCNT1 >= 7999) if ( TCNT1 >= 31249) // New Timer Count for Prescaled Timer. { PORTB ^= (1 << 5); // Toggle the LED TCNT1 = 0; // Reset timer value } } } 2. Build and download the code 3. Observe the LED 4. Measure the actual frequency using NI Virtual Bench As seen, we have successfully generated a clock of 1 Hz Note – for this long delay (to the Virtual Bench), you need to wait for the OSC to finish triggering and you might not observe that many cycles of signal on the instruments. EEET2505 C. Analysis 1. The code in this section is pretty similar to the above except two places a. Where you need to set the set the TTCR1B to accommodate the Prescaler discussed earlier. TCCR1B |= (1 << CS12 ); // Set up timer with the prescaler of 256 b. Secondly, the Timer value is set according to the calculation above if ( TCNT1 >= 31249) EEET2505 // New Timer Count for Prescaled Timer.