{"id":1756,"date":"2016-03-31T12:22:11","date_gmt":"2016-03-31T19:22:11","guid":{"rendered":"http:\/\/visualgdb.com\/w\/?p=1756"},"modified":"2016-03-31T12:22:11","modified_gmt":"2016-03-31T19:22:11","slug":"controlling-stm32-hardware-timers-using-hal","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/stm32\/timers\/hal\/","title":{"rendered":"Controlling STM32 Hardware Timers using HAL"},"content":{"rendered":"<p>This tutorial shows how to use the STM32 hardware timers via the STM32 HAL API. If you want to use them with the legacy StdPeriph library, follow <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/stm32\/timers\/\">this tutorial<\/a> instead.<\/p>\n<p>Before you begin, ensure that you can build and debug embedded projects for your STM32 board by following one of our basic <a href=\"http:\/\/visualgdb.com\/w\/tutorials\/tag\/stm32\/\">STM32 tutorials<\/a>.<\/p>\n<ol>\n<li>Before we can start configuring the timer, we&#8217;ll give a brief overview how the timers work. Hardware timers keep counting up or down depending on the module until the timer period is reached. Then the timer is reset:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/01-timer.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/01-timer.png\" alt=\"\" width=\"700\" height=\"249\" \/><\/a><\/li>\n<li>We will use the timer to keep our LED on 80% of the time by setting a period of 500, turning it on when the counter reaches 400 and turning it off when it reaches 500:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/02-timer500.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/timers\/02-timer500.png\" alt=\"\" width=\"700\" height=\"252\" \/><\/a><\/li>\n<li>Create a basic HAL-based LEDBlink project for your board if you have not done that already. Then we will begin with configuring the timer. This is done by calling __TIMx_CLK_ENABLE(),\u00a0 filling the fields of the <strong>Init<\/strong> member in the <strong>TIM_HandleTypeDef<\/strong> structure and calling HAL_TIM_Base_Init() and HAL_TIM_Base_Start():\n<pre class=\"\">\u00a0\u00a0\u00a0 __TIM2_CLK_ENABLE();\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.Prescaler = 40000;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.Period = 500;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.RepetitionCounter = 0;\r\n\u00a0\u00a0\u00a0 HAL_TIM_Base_Init(&amp;s_TimerInstance);\r\n\u00a0\u00a0\u00a0 HAL_TIM_Base_Start(&amp;s_TimerInstance);<\/pre>\n<\/li>\n<li>From the main() function we can get the current timer value using the __HAL_TIM_GET_COUNTER() macro and update the LED accordingly. The main source file will look the following way:\n<pre class=\"\">#include &lt;stm32f4xx_hal.h&gt;\r\n\r\n#ifdef __cplusplus\r\nextern \"C\"\r\n#endif\r\nvoid SysTick_Handler(void)\r\n{\r\n\u00a0\u00a0 \u00a0HAL_IncTick();\r\n\u00a0\u00a0 \u00a0HAL_SYSTICK_IRQHandler();\r\n}\r\n\r\nstatic TIM_HandleTypeDef s_TimerInstance = { \r\n\u00a0\u00a0\u00a0 .Instance = TIM2\r\n};\r\n\r\nvoid InitializeTimer()\r\n{\r\n\u00a0\u00a0\u00a0 __TIM2_CLK_ENABLE();\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.Prescaler = 40000;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.Period = 500;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;\r\n\u00a0\u00a0\u00a0 s_TimerInstance.Init.RepetitionCounter = 0;\r\n\u00a0\u00a0\u00a0 HAL_TIM_Base_Init(&amp;s_TimerInstance);\r\n\u00a0\u00a0\u00a0 HAL_TIM_Base_Start(&amp;s_TimerInstance);\r\n}\r\n\r\nvoid InitializeLED()\r\n{\r\n\u00a0\u00a0\u00a0 __GPIOD_CLK_ENABLE();\r\n\u00a0\u00a0\u00a0 GPIO_InitTypeDef GPIO_InitStructure;\r\n\r\n\u00a0\u00a0\u00a0 GPIO_InitStructure.Pin = GPIO_PIN_12;\r\n\r\n\u00a0\u00a0\u00a0 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;\r\n\u00a0\u00a0\u00a0 GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;\r\n\u00a0\u00a0\u00a0 GPIO_InitStructure.Pull = GPIO_NOPULL;\r\n\u00a0\u00a0\u00a0 HAL_GPIO_Init(GPIOD, &amp;GPIO_InitStructure);\r\n}\r\n\r\nint main(void)\r\n{\r\n\u00a0\u00a0 \u00a0HAL_Init();\r\n\u00a0\u00a0\u00a0 InitializeLED();\r\n\u00a0\u00a0\u00a0 InitializeTimer();\r\n\r\n\u00a0\u00a0\u00a0 for (;;)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int timerValue = __HAL_TIM_GET_COUNTER(&amp;s_TimerInstance);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (timerValue == 400)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (timerValue == 500)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);\r\n\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<\/li>\n<li>Run the program and notice how the LED starts blinking. You can use the Preprocess Selected Lines command to see that the __HAL_TIM_GET_COUNTER() simply reads the CNT register of the timer:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/timer.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1757\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/timer.png\" alt=\"timer\" width=\"902\" height=\"659\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/timer.png 902w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/timer-300x219.png 300w\" sizes=\"(max-width: 902px) 100vw, 902px\" \/><\/a><\/li>\n<li>If you change timerValue to be a static variable, you can use the Live Variables to plot how the value is changing over time following the TIM2-&gt;CNT value:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/live.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1758\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/live.png\" alt=\"live\" width=\"902\" height=\"659\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/live.png 902w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/live-300x219.png 300w\" sizes=\"(max-width: 902px) 100vw, 902px\" \/><\/a><\/li>\n<li>You can also configure the timer to automatically generate the &#8216;update&#8217; events once the value reaches the period value. This can be done by replacing a call to HAL_TIM_Base_Start() with HAL_TIM_Base_Start_IT():\n<pre class=\"\">\u00a0\u00a0\u00a0 HAL_TIM_Base_Start_IT(&amp;s_TimerInstance);<\/pre>\n<\/li>\n<li>From the main() function you can check the status of the &#8216;Update&#8217; interrupt and toggle the LED state when the update happens:\n<pre class=\"\">\u00a0\u00a0\u00a0 for (;;)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (__HAL_TIM_GET_FLAG(&amp;s_TimerInstance, TIM_FLAG_UPDATE) != RESET)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 __HAL_TIM_CLEAR_IT(&amp;s_TimerInstance, TIM_IT_UPDATE);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>If you run the program now, you will see how the LED changes its state every 500 timer cycles.<\/li>\n<li>The good thing about the timer interrupts is that you actually don&#8217;t need to check their status manually. As long as you enable the interrupt by calling HAL_NVIC_EnableIRQ(), the timer will automatically trigger an interrupt handler function when the event occurs. You can look up the interrupt function name in the startup_stm32xxxx.c file:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/handler.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1759\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/handler.png\" alt=\"handler\" width=\"902\" height=\"659\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/handler.png 902w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/handler-300x219.png 300w\" sizes=\"(max-width: 902px) 100vw, 902px\" \/><\/a><\/li>\n<li>The easiest way to write the interrupt handler is to simply call HAL_TIM_IRQHandler() from it. The handler provided by HAL will automatically check which event caused the interrupt and invoke one of the specialized handlers like HAL_TIM_PeriodElapsedCallback(). Add the following code to your main file to try that out:\n<pre class=\"\">extern \"C\" void TIM2_IRQHandler()\r\n{\r\n\u00a0\u00a0\u00a0 HAL_TIM_IRQHandler(&amp;s_TimerInstance);\r\n}\r\n\r\nvoid HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)\r\n{\r\n\u00a0\u00a0\u00a0 HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);\r\n}\r\n\r\nint main(void)\r\n{\r\n\u00a0\u00a0 \u00a0HAL_Init();\r\n\u00a0\u00a0\u00a0 InitializeLED();\r\n\u00a0\u00a0\u00a0 InitializeTimer();\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);\r\n\u00a0\u00a0\u00a0 HAL_NVIC_EnableIRQ(TIM2_IRQn);\r\n\r\n\u00a0\u00a0\u00a0 for (;;)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<p>Note that the main() function does not need to do anything with the timer anymore and can simply handle the rest of your application&#8217;s logic.<\/li>\n<li>You can visualize what happens when the interrupt is triggered by adding an indicator variable and toggling it from the callback function (a value of 250 is chosen to scale good with the timer counter range):\n<pre class=\"\">int g_Indicator;\r\n\r\nvoid HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)\r\n{\r\n\u00a0\u00a0\u00a0 HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);\r\n\u00a0\u00a0\u00a0 g_Indicator = g_Indicator ? 0 : 250;\r\n}<\/pre>\n<\/li>\n<li>Simply add both timer counter and the g_Indicator to live variables and observe how the indicator variable is changed each time the timer gets reset:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/ind.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1760\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/ind.png\" alt=\"ind\" width=\"902\" height=\"659\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/ind.png 902w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/ind-300x219.png 300w\" sizes=\"(max-width: 902px) 100vw, 902px\" \/><\/a><\/li>\n<li>If you set a breakpoint at the HAL_TIM_PeriodElapsedCallback() function, you can see how it&#8217;s called by the HAL_TIM_IRQHandler() as a result of the timer 2 interrupt handler being invoked:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/stack.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1761\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/stack.png\" alt=\"stack\" width=\"902\" height=\"659\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/stack.png 902w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/stack-300x219.png 300w\" sizes=\"(max-width: 902px) 100vw, 902px\" \/><\/a><\/li>\n<li>You can use the Code Map to quickly explore what other event handlers the HAL_TIM_IRQHandler() method invokes:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/cb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1762\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/cb.png\" alt=\"cb\" width=\"902\" height=\"659\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/cb.png 902w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2016\/03\/cb-300x219.png 300w\" sizes=\"(max-width: 902px) 100vw, 902px\" \/><\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use the STM32 hardware timers via the STM32 HAL API. If you want to use<\/p>\n","protected":false},"author":1,"featured_media":1763,"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\/1756"}],"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=1756"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/1756\/revisions"}],"predecessor-version":[{"id":1764,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/1756\/revisions\/1764"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media\/1763"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=1756"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=1756"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=1756"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}