{"id":4147,"date":"2023-08-17T19:25:20","date_gmt":"2023-08-17T17:25:20","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4147"},"modified":"2025-12-27T15:31:23","modified_gmt":"2025-12-27T14:31:23","slug":"delay-using-the-systick-timer-on-stm32-stm32-using-registers-3","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/delay-using-the-systick-timer-on-stm32-stm32-using-registers-3\/","title":{"rendered":"Delay using the SysTick Timer on STM32 | STM32 Using Registers #3"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Delay Using the SysTick Timer on STM32<\/h1>\n\n\n\n<p>Blinking an LED from the previous article had one <strong>big drawback<\/strong>. In reality, we <strong>didn\u2019t fully control the time<\/strong> between changing states on the GPIO pin. Such a silly <em>for <\/em>loop doesn\u2019t have a defined execution time. Of course, you could check what instructions it contains and count clock cycles, but that\u2019s not how it\u2019s done\u2026 Measuring time in microcontrollers is handled by <strong>Timers<\/strong>, and today we\u2019ll learn how to use one of them.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/sklep.msalamon.pl\/produkt\/stm32-nucleo-c031c6-nucleo-32-z-stm32c031c6t6-arm-cortex-m0?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=stm32narejestrach&amp;utm_content=banner\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"341\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/07\/stm32C031C6_BANER-1024x341.jpg\" alt=\"\" class=\"wp-image-2351\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/07\/stm32C031C6_BANER-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/07\/stm32C031C6_BANER-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/07\/stm32C031C6_BANER-768x256.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/07\/stm32C031C6_BANER.jpg 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">STM32 on Registers Series on YouTube<\/h2>\n\n\n\n<p>These posts are created in parallel with the&nbsp;<strong>series on my YouTube<\/strong>&nbsp;on the same topic. If you prefer the video version, I invite you there. These articles are a shortened version of what I show on YouTube.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Delay na STM32 z u\u017cyciem SysTick Timera | STM32 na Rejestrach #3\" width=\"750\" height=\"422\" src=\"https:\/\/www.youtube.com\/embed\/SFQL7gYbeC4?list=PLMr8JGWm4y7_l6qIVBSePaSQ0vuLWMfGp\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=ShCWoicHkKM&amp;list=PLMr8JGWm4y7_l6qIVBSePaSQ0vuLWMfGp\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Link to the YouTube Playlist<\/strong><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Time Base in Embedded Systems<\/h2>\n\n\n\n<p>You will probably always need to measure a fixed time interval. It even has its own name \u2013 <strong>time base<\/strong>. Depending on your needs, it will be 1, 10, 100 milliseconds. That\u2019s the only task such a time-base timer needs to perform.<\/p>\n\n\n\n<p>STM32 has <strong>tons of advanced timers<\/strong>, and it would be a waste to use them just to measure a fixed time interval. Fortunately, we have the <strong>SysTick system clock timer<\/strong>. Interestingly, <strong>it is part of the core<\/strong> (which also has consequences), so it is identical in every microcontroller with an ARM Cortex-M.<\/p>\n\n\n\n<p>It is relatively <strong>simple<\/strong>. It only counts down from a set value. When it reaches zero, it reloads the set value and counts down again. <strong>Each time it passes through zero, it generates a so-called interrupt.<\/strong><\/p>\n\n\n\n<p>We will cover interrupts only after some time, so here we\u2019ll go briefly through its configuration. The main goal here is <strong>using SysTick as a time delay<\/strong>.<\/p>\n\n\n\n<p>Inevitably, we\u2019ll also touch a bit on clock configuration in STM32. I also want to leave this topic for later to cover it fully, so we\u2019ll go through the absolute minimum needed for this lesson.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SysTick as a Core Element<\/h2>\n\n\n\n<p>Since we already know that <strong>SysTick is part of the core<\/strong>, where should we look for information about it? Exactly\u2026 <strong>in the core documentation<\/strong>. Not the microcontroller\u2019s! We don\u2019t have it at hand right now. Fortunately, we won\u2019t need it. But if you want to take a look, here it is: <a href=\"https:\/\/documentation-service.arm.com\/static\/60411750ee937942ba301773\" target=\"_blank\" rel=\"noopener\">Cortex-M0+ Technical Reference Manual<\/a><\/p>\n\n\n\n<p>ARM did all the work for us. They wrote a function that properly sets up SysTick based on what we pass to it.<\/p>\n\n\n\n<p>It\u2019s called <em><strong>uint32_t SysTick_Config(uint32_t ticks)<\/strong><\/em> and is <strong>part of the CMSIS libraries<\/strong>. Specifically, it is located in the file c<em>ore_cmX.h<\/em>, where X is the Cortex-M core number. In our case, we\u2019re dealing with a <strong>Cortex-M0+<\/strong>.<\/p>\n\n\n\n<p>Besides setting the number of ticks, this function checks whether we\u2019re trying to write more than 24 bits, sets the interrupt to the lowest available priority and enables it, and also enables the counting itself.<\/p>\n\n\n\n<p>This function <strong>takes as its argument the number of clock ticks<\/strong> to count. Two problems appear to be solved:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Which clock?<\/li>\n\n\n\n<li>How many ticks for the selected time base?<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">What Frequency Reaches the SysTick Timer in STM32C0C6T6?<\/h3>\n\n\n\n<p>Each timer counts a clock signal. So it must be clocked by something. In our microcontroller, SysTick can be clocked by two values: <strong>HCLK<\/strong>, i.e. (in short) the core frequency, <strong>or HCLK\/8<\/strong>. We can quickly check this, for example, in the <strong>clock view in CubeMX<\/strong>. That will be the fastest way.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-Clocks.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"500\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-Clocks-1024x500.jpg\" alt=\"Zegary STM32C032C6T6\" class=\"wp-image-2410\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-Clocks-1024x500.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-Clocks-300x146.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-Clocks-768x375.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-Clocks.jpg 1436w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><\/figure>\n<\/div>\n\n\n\n<p>By default, <strong>STM32 microcontrollers start from the internal oscillator.<\/strong> Since we\u2019re still running on the default clock <strong>HSI48<\/strong>, then SysTick is fed with a 48 MHz signal. <strong>But is it really?<\/strong> It\u2019s better to rely on the documentation. CubeMX, even though it\u2019s set to the default value, note that it indicates HSE here, i.e. the external clock. We never enabled it, so it turns out that <strong>CubeMX has a different idea of the default value<\/strong> than what\u2019s in the Reference Manual. There may be more differences here!<\/p>\n\n\n\n<p>What we care about are the clock dividers. There are several of them in STM32. Since we\u2019re working on HSI, we are interested in the dividers for it. In the RCC registers we have, for example, <strong>HSIDIV<\/strong> and <strong>HSIKERDIV<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIDIV.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"870\" height=\"266\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIDIV.jpg\" alt=\"\" class=\"wp-image-2414\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIDIV.jpg 870w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIDIV-300x92.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIDIV-768x235.jpg 768w\" sizes=\"auto, (max-width: 870px) 100vw, 870px\" \/><\/a><\/figure>\n\n\n\n<p>HSIDIV is used to generate <strong>HSISYS<\/strong>. This signal is right at the beginning of the clock tree and initially divides the clock. <strong>It is set to 4 by default!!!<\/strong> So we\u2019re not dealing with 48 MHz, but <strong>12 MHz<\/strong>. That\u2019s a huge difference. We have two options:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Leave it and work at 12 MHz<\/li>\n\n\n\n<li>Insist and change the divider to a value of 1<\/li>\n<\/ol>\n\n\n\n<p>Let\u2019s first see what happens next.<\/p>\n\n\n\n<p>HSIKER is the second divider that may interest us, because it is set to 3. Let\u2019s see where it goes. The easiest way will be in CubeMX.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIKER.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"797\" height=\"276\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIKER.jpg\" alt=\"\" class=\"wp-image-2417\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIKER.jpg 797w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIKER-300x104.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-HSIKER-768x266.jpg 768w\" sizes=\"auto, (max-width: 797px) 100vw, 797px\" \/><\/a><\/figure>\n\n\n\n<p>Fortunately, we do not use the HSIKER signal, so it is harmless for us. However, for the future we must remember that it is set to a <strong>value other than 1.<\/strong><\/p>\n\n\n\n<p>Next we have the <strong>RCC_CFGR<\/strong> register, which also contains dividers. These, in turn, create the <strong>SYSCLK<\/strong> and <strong>HCLK<\/strong> signals for us. Notice that by default everything in this register is zero, so all these prescalers will be set to 1.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-RCC_CFGR.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"972\" height=\"387\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-RCC_CFGR.jpg\" alt=\"\" class=\"wp-image-2419\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-RCC_CFGR.jpg 972w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-RCC_CFGR-300x119.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-RCC_CFGR-768x306.jpg 768w\" sizes=\"auto, (max-width: 972px) 100vw, 972px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-PPRE.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"858\" height=\"498\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-PPRE.jpg\" alt=\"\" class=\"wp-image-2420\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-PPRE.jpg 858w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-PPRE-300x174.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2023\/08\/STM32C0-PPRE-768x446.jpg 768w\" sizes=\"auto, (max-width: 858px) 100vw, 858px\" \/><\/a><\/figure>\n\n\n\n<p>Let\u2019s go back to the decision. What to do? 12 or 48 MHz? <strong>We don\u2019t have full knowledge about clocks yet, so I recommend leaving it at 12 MHz.<\/strong> When changing to 48 MHz, you will need to take care of something else besides just the clock.<\/p>\n\n\n\n<p>In general, on the Internet you can find many opinions that clocks in STM32 are something very complicated and\u2026 they are. Here we don\u2019t have much of it, but <strong>large chips can really make your head spin.<\/strong><\/p>\n\n\n\n<p>I always recommend checking <strong>what is set by default in the Reference Manual.<\/strong> Plus, <strong>the CubeMX visualization<\/strong> to speed up the analysis.<\/p>\n\n\n\n<p><strong>Decision: We stay with HCLK at 12 MHz. At the same time, SysTick will also be clocked at 12 MHz.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Many Ticks for the Selected Time Base?<\/h3>\n\n\n\n<p>In our programs, we will most often assume 1 ms as the time base. How many ticks must be counted for one millisecond to pass? And will that number fit in a 24-bit value? We need to calculate it.<\/p>\n\n\n\n<p>1 second = 12000000<\/p>\n\n\n\n<p>0.001 s = X<\/p>\n\n\n\n<p>X = 12000000 * 0.001 = 12000000 \/ 1000 = <strong>12000<\/strong> <strong>ticks<\/strong> at 12 MHz<\/p>\n\n\n\n<p>You can arrive at it a slightly different way \u2013 simpler. <strong>Divide the clock frequency by how many \u201ctime bases\u201d fit in a second.<\/strong> In our case, how many single milliseconds are in a second, i.e. 1000.<\/p>\n\n\n\n<p>12000000 \/ 1000 = 12000 ticks<\/p>\n\n\n\n<p>You can enter the calculated value or <strong>enter the division expression<\/strong>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\t\/\/ Configure SysTick Timer\n\t\/\/ 1s = 12 000 000\n\t\/\/ 0,001 = X\n\tSysTick_Config(12000000 \/ 1000);<\/pre>\n\n\n\n<p>Will this fit in a 24-bit counter? 2^24 is 16&nbsp;777&nbsp;216. It fits easily.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SysTick Timer Interrupt<\/h2>\n\n\n\n<p>Since we have SysTick configured, we need to <strong>handle its interrupt<\/strong>. Let me cover interrupts another time, and here I\u2019ll shorten it a bit. Microcontroller programming is a field where it would be best if you learned everything at once. That can\u2019t be done, so sometimes you need a shortcut in order to clarify it later.<\/p>\n\n\n\n<p>When SysTick counts down the set value, it notifies a special block responsible for interrupts \u2013 the NVIC. <strong>NVIC interrupts the main program and allows us to react to what happened \u2013 i.e. the interrupt handler.<\/strong><\/p>\n\n\n\n<p>In this interrupt handler, we will count how many individual milliseconds have elapsed since the program started.<\/p>\n\n\n\n<p>We will use a variable of type <em>uint32_t Ticks<\/em> for this. Since it will be used both in the interrupt and in the same compilation unit, it must be marked as <em>volatile<\/em>. You can do it directly, or you can use the __IO definition, which is located in the CMSIS headers.<\/p>\n\n\n\n<p><strong>NVIC jumps to the interrupt function<\/strong>, which is provided in the so-called <strong>interrupt vector<\/strong>. I\u2019ll show you where this is in the interrupts lesson.<\/p>\n\n\n\n<p>For SysTick, this handler is called <strong><em>SysTick_Handler<\/em><\/strong>. In this function, the only thing we do is increment, i.e. increase by one, our Tick variable. <strong>And this way SysTick will count the passing time for us.<\/strong><\/p>\n\n\n\n<p>Remember that the <strong>interrupt is already set up and enabled<\/strong> by the earlier use of the <em>SysTick_Config<\/em> function.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">__IO uint32_t Tick;\n\nvoid SysTick_Handler(void)\n{\n\tTick++; \/\/ Increase system timer\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Delay on SysTick<\/h2>\n\n\n\n<p>We have time counting; now we need to write a <strong>delay function.<\/strong><\/p>\n\n\n\n<p><strong>Warning! This will be a so-called blocking function.<\/strong> It is incredibly simple, but unfortunately <strong>it comes at a cost<\/strong>.<\/p>\n\n\n\n<p>While waiting for the delay, the microcontroller will do nothing else (besides interrupts). <strong>Our program will be blocked, stuck in this one place. Hence the name \u2013 blocking.<\/strong><\/p>\n\n\n\n<p>For now I have to show it to you like this, but in the next lessons I will show you <strong>one of the ways to avoid blocking the code.<\/strong> I discuss this in more detail in my STM32 for Beginners course (the course content is conducted in Polish): <a href=\"https:\/\/kursstm32.pl\" target=\"_blank\" rel=\"noopener\">https:\/\/kursstm32.pl<\/a><\/p>\n\n\n\n<p>Since we are counting milliseconds, we will delay by milliseconds. In this function we need to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Store the current time when entering the function. The current time is in the <em>Tick<\/em> variable.<\/li>\n\n\n\n<li>Wait the amount of time specified in the argument by checking whether the <em>Tick<\/em> variable has increased by the specified value<\/li>\n\n\n\n<li>If the specified time has passed \u2013 release the microcontroller. That\u2019s it \ud83d\udc4c<\/li>\n<\/ol>\n\n\n\n<p>It will look like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void Delay(uint32_t Delay_ms)\n{\n\tuint32_t StartTime = Tick;\n\n\twhile(Tick &lt; (StartTime + Delay_ms))\n\t{\n\t\t\/\/ Just wait\n\t}\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">How the Delay Works<\/h2>\n\n\n\n<p>Now in the program\u2019s main loop you can use our new delay. In the Delay argument, you enter the number of milliseconds to wait.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">while(1)\n{\n\t\/\/ Set LED on PA5\n\tLD4_ON;\n\tDelay(150);\n\n\t\/\/ Reset LED on PA5\n\tLD4_OFF;\n\tDelay(150);\n}<\/pre>\n\n\n\n<p>This way our LD4 LED on <a href=\"https:\/\/sklep.msalamon.pl\/produkt\/stm32-nucleo-c031c6-nucleo-32-z-stm32c031c6t6-arm-cortex-m0\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=stm32narejestrach&amp;utm_content=Text\" target=\"_blank\" data-type=\"link\" data-id=\"https:\/\/sklep.msalamon.pl\/produkt\/stm32-nucleo-c031c6-nucleo-32-z-stm32c031c6t6-arm-cortex-m0\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=stm32narejestrach&amp;utm_content=Text\" rel=\"noreferrer noopener\">NUCLEO-C031C6<\/a> blinks exactly as we tell it to. Voila!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>Using SysTick is quite simple. All thanks to the ready-made function in the CMSIS libraries. You only need to take care of the interrupt handler, which as you can see can be very simple.<\/p>\n\n\n\n<p>In the next post we will deal with GPIO input. We will read the state of a button. The freshly written delay function will come in handy there.<\/p>\n\n\n\n<p>Let me know in the comments if you liked this post! Maybe you have a suggestion of what to show as part of the STM32 on Registers series? Share this article with your friends.<\/p>\n\n\n\n<p>I also invite you to my store, where you can buy interesting electronics for programming, such as&nbsp;<a href=\"https:\/\/sklep.msalamon.pl\/produkt\/stm32-nucleo-c031c6-nucleo-32-z-stm32c031c6t6-arm-cortex-m0\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=stm32narejestrach&amp;utm_content=Text\" target=\"_blank\" rel=\"noreferrer noopener\">NUCLEO-C031C6<\/a>, which we use in this series:&nbsp;<a href=\"https:\/\/sklep.msalamon.pl\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/sklep.msalamon.pl<\/a><\/p>\n\n\n\n<p>You can find the project from this article at:&nbsp;<a href=\"https:\/\/github.com\/lamik\/stm32narejestrach_3\" target=\"_blank\" data-type=\"link\" data-id=\"https:\/\/github.com\/lamik\/stm32narejestrach_3\" rel=\"noreferrer noopener\">https:\/\/github.com\/lamik\/stm32narejestrach_3<\/a><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;4147&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;0&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 - (0 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Delay using the SysTick Timer on STM32 | STM32 Using Registers #3&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Delay Using the SysTick Timer on STM32 Blinking an LED from the previous article had one big drawback. In reality, we didn\u2019t fully control the time between changing states on the GPIO pin. Such a silly for loop doesn\u2019t have a defined execution time. Of course, you could check what [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3839,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[178,176,174],"class_list":["post-4147","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-kursstm32","tag-programming","tag-stm32"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4147","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/comments?post=4147"}],"version-history":[{"count":3,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4147\/revisions"}],"predecessor-version":[{"id":4150,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4147\/revisions\/4150"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/3839"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4147"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}