{"id":132,"date":"2014-02-04T17:39:31","date_gmt":"2014-02-04T17:39:31","guid":{"rendered":"http:\/\/visualgdb.com\/w\/?p=132"},"modified":"2016-03-31T12:24:04","modified_gmt":"2016-03-31T19:24:04","slug":"arm-stm32-timers","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/stm32\/timers\/","title":{"rendered":"Controlling STM32 Hardware Timers with Interrupts"},"content":{"rendered":"<p>This tutorial shows how control the hardware timers of an STM32 microcontroller. We will show it based on the STM32F4-Discovery board, however controlling the timers of other STM32 devices is very similar.<\/p>\n<p><strong>Warning: this tutorial describes the legacy StdPeriph interface. To learn about controlling the timers using the new HAL interface, follow <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/stm32\/timers\/hal\/\">this tutorial<\/a> instead.<\/strong><\/p>\n<p>Before you begin with this tutorial please create a basic project for your STM32 device (e.g. by following <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/stm32\/timers\/..\/\"> this tutorial for STM32F1 series devices<\/a> or this <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/stm32\/timers\/..\/f4_discovery\">tutorial for the STM32F4-Discovery board<\/a>).<\/p>\n<ol>\n<li>A hardware timer is essentially an independent counter that counts from zero to its maximum value at a given speed and generates various events. It runs in the background independently from your C\/C++ program and its value typically follows the sequence depicted below:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/01-timer.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/01-timer.png\" alt=\"01-timer\" width=\"700\" height=\"249\" \/><\/a><\/li>\n<li>Let&#8217;s start with a simple program that will configure the timer to run in the background with a period of 500, turn the LED on once the value reaches 400 and back off once it gets to 500. The timer will automatically reset itself to zero once it reaches a value of 500:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/02-timer500.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/02-timer500.png\" alt=\"02-timer500\" width=\"700\" height=\"252\" \/><\/a><\/li>\n<li>We will initialize the timer to run with a prescaler of 40000, and a period of 500. Note that before we can do anything with the timer we need to enable it by calling <strong>RCC_APB1PeriphClockCmd()<\/strong>:\n<pre>RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);\r\n\r\nTIM_TimeBaseInitTypeDef timerInitStructure; \r\ntimerInitStructure.TIM_Prescaler = 40000;\r\ntimerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;\r\ntimerInitStructure.TIM_Period = 500;\r\ntimerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;\r\ntimerInitStructure.TIM_RepetitionCounter = 0;\r\nTIM_TimeBaseInit(TIM2, &amp;timerInitStructure);\r\nTIM_Cmd(TIM2, ENABLE);<\/pre>\n<\/li>\n<li>In the main() function we will simply check the timer value and control the LED based on it. The entire program for the STM32F4-Discovery board is listed below:\n<pre class=\"\">#include &lt;stm32f4xx_gpio.h&gt;\r\n#include &lt;stm32f4xx_tim.h&gt;\r\n#include &lt;stm32f4xx_rcc.h&gt;\r\n#include &lt;misc.h&gt;\r\n\r\nvoid InitializeLEDs()\r\n{\r\n    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);\r\n\r\n    GPIO_InitTypeDef gpioStructure;\r\n    gpioStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;\r\n    gpioStructure.GPIO_Mode = GPIO_Mode_OUT;\r\n    gpioStructure.GPIO_Speed = GPIO_Speed_50MHz;\r\n    GPIO_Init(GPIOD, &amp;gpioStructure);\r\n\r\n    GPIO_WriteBit(GPIOD, GPIO_Pin_12 | GPIO_Pin_13, Bit_RESET);\r\n}\r\n\r\nvoid InitializeTimer()\r\n{\r\n    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);\r\n\r\n    TIM_TimeBaseInitTypeDef timerInitStructure; \r\n    timerInitStructure.TIM_Prescaler = 40000;\r\n    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;\r\n    timerInitStructure.TIM_Period = 500;\r\n    timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;\r\n    timerInitStructure.TIM_RepetitionCounter = 0;\r\n    TIM_TimeBaseInit(TIM2, &amp;timerInitStructure);\r\n    TIM_Cmd(TIM2, ENABLE);\r\n}\r\n\r\nint main()\r\n{\r\n    InitializeLEDs();\r\n    InitializeTimer();\r\n\r\n    for (;;)\r\n    {\r\n        int timerValue = TIM_GetCounter(TIM2);\r\n        if (timerValue == 400)\r\n            GPIO_WriteBit(GPIOD, GPIO_Pin_12, Bit_SET);\r\n        else if (timerValue == 500)\r\n            GPIO_WriteBit(GPIOD, GPIO_Pin_12, Bit_RESET);\r\n    }\r\n}<\/pre>\n<\/li>\n<li>Run the program and notice how LED blinks in short cycles. If you set a breakpoint after the line reading <strong>timerValue<\/strong>, you will see that each time it is hit the <strong>timerValue<\/strong> will be between 0 and 500. This corresponds to the period of 5000 we have specified in <strong>TIM_Period<\/strong>:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/03-breakpoint.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/03-breakpoint.png\" alt=\"03-breakpoint\" width=\"698\" height=\"611\" \/><\/a><\/li>\n<li>The STM32 timers can automatically generate &#8216;update&#8217; events once they reach the period value. Add the following code after the <strong>TIM_Cmd(TIM2, ENABLE)<\/strong> line:\n<pre>TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);<\/pre>\n<\/li>\n<li>This will enable the &#8216;update&#8217; interrupt for the timer. Note that as we did not configure interrupt controller, the interrupt won&#8217;t affect our code execution and we&#8217;ll have to check for it manually. Replace the contents of <strong> main() <\/strong>with the following code:\n<pre class=\"\">InitializeLEDs();\r\nInitializeTimer();\r\nfor (;;)\r\n{\r\n    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)\r\n    {\r\n        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);\r\n        GPIO_ToggleBits(GPIOD, GPIO_Pin_12);\r\n    }\r\n}<\/pre>\n<p>Run the program and notice how the LED blinking pattern has changed. Now instead of polling the timer value constantly and switching the LED on and off on certain threshold values we simply wait for the <strong>TIM_IT_Update <\/strong> interrupt and toggle the LED once it arrives.<\/li>\n<li>The real power of hardware timers is however in the way they can send interrupts to the CPU eliminating the need to check the status manually. Add the following function to your code and call it from <strong>main()<\/strong> after <strong>InitializeTimer()<\/strong>:\n<pre>void EnableTimerInterrupt()\r\n{\r\n    NVIC_InitTypeDef nvicStructure;\r\n    nvicStructure.NVIC_IRQChannel = TIM2_IRQn;\r\n    nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;\r\n    nvicStructure.NVIC_IRQChannelSubPriority = 1;\r\n    nvicStructure.NVIC_IRQChannelCmd = ENABLE;\r\n    NVIC_Init(&amp;nvicStructure);\r\n}<\/pre>\n<\/li>\n<li>Finally remove all contents of the <strong>for(;;)<\/strong> loop in <strong>main()<\/strong> and move it into the <strong> TIM2_IRQHandler()<\/strong> function:\n<pre class=\"\">extern \"C\" void TIM2_IRQHandler()\r\n{\r\n    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)\r\n    {\r\n        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);\r\n        GPIO_ToggleBits(GPIOD, GPIO_Pin_12);\r\n    }\r\n}<\/pre>\n<p>Note that you only need <strong>extern &#8220;C&#8221; <\/strong>if you are building a C++ program.<\/li>\n<li>Run your new program and observe how the LED blinks. Put a breakpoint inside TIM2_IRQHandler() and observe the register values:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/04-interrupt.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/04-interrupt.png\" alt=\"04-interrupt\" width=\"698\" height=\"614\" \/><\/a><\/li>\n<li>Note that the link register (lr) that normally contains the return address of a function contains the value of <strong> 0xfffffff9<\/strong>. This is a special value denoted as <strong>EXC_RETURN <\/strong>in ARM Cortex CPU documentation. It means that the current function was called by the CPU automatically as a result of handling an exception.<\/li>\n<li>Replace the contents of the <strong>for(;;) <\/strong>loop in <strong>main()<\/strong> with the following:\n<pre class=\"\">for (int i = 0; i &lt; 1000000; i++)\r\n    asm(\"nop\");\r\nGPIO_ToggleBits(GPIOD, GPIO_Pin_13);<\/pre>\n<\/li>\n<li>Run your program. You will see how the two LEDs blink with different frequencies independently. The loop inside main() that controls the orange LED does not need to do any extra checks to control the green LED. The timer automatically pauses it and transfers control to <strong>TIM2_IRQHandler() <\/strong>each time an update event occurs.<\/li>\n<li>Note that the name of the <strong>TIM2_IRQHandler()<\/strong> function is crucial to the entire process of handling interrupts. The STM32 startup file contains the following code:\n<pre class=\"\">void TIM2_IRQHandler() __attribute__ ((weak, alias (\"Default_Handler\")));\r\n\r\nvoid *g_pfnVectors[0x62] __attribute__ ((section (\".isr_vector\"))) = \r\n{\r\n    &amp;_estack,\r\n    &amp;Reset_Handler,\r\n    &amp;NMI_Handler,\r\n    ... ,\r\n    &amp;TIM2_IRQHandler,\r\n    ... ,\r\n}\r\n\r\nvoid__attribute__((naked, noreturn)) Default_Handler()\r\n{\r\n    for (;;) ;\r\n}\r\n\r\n<\/pre>\n<p>The <strong>g_pfnVectors<\/strong> table contains addresses of interrupt handlers such as <strong>TIM2_IRQHandler()<\/strong>. Furthermore, unless you explicitly provide a method for a given interrupt handler, such as <strong>TIM2_IRQHandler()<\/strong>, GCC will automatically substitute it with <strong> DefaultHandler()<\/strong> that will halt your program.<\/li>\n<\/ol>\n<p>You can download the full source code of this sample here: <a href=\"http:\/\/sysprogs.com\/files\/visualgdb\/tutorials\/TimerDemo.cpp\">TimerDemo.cpp<\/a><\/p>\n<p>To learn about controlling the STM32 timers\u00a0 using the HAL API, follow <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/stm32\/timers\/hal\/\">this tutorial<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how control the hardware timers of an STM32 microcontroller. We will show it based on the STM32F4-Discovery<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16],"tags":[53,61,68],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/132"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=132"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/132\/revisions"}],"predecessor-version":[{"id":1765,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/132\/revisions\/1765"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=132"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=132"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=132"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}