{"id":450,"date":"2023-10-02T09:50:00","date_gmt":"2023-10-02T04:20:00","guid":{"rendered":"https:\/\/blog.mshafeeq.com\/?p=450"},"modified":"2024-07-05T09:57:38","modified_gmt":"2024-07-05T04:27:38","slug":"stm32f103c6t6a-bare-metal-programming-capture-mode","status":"publish","type":"post","link":"https:\/\/blog.mshafeeq.com\/index.php\/2023\/10\/02\/stm32f103c6t6a-bare-metal-programming-capture-mode\/","title":{"rendered":"STM32F103C6T6A Bare Metal Programming &#8211; Capture mode"},"content":{"rendered":"\n<p>The CC module can capture the value of the counter at the moment a specified event occurs on an input pin. This is useful for measuring input signal frequencies, pulse widths, and timing intervals. If you haven&#8217;t gone throught my previous post &#8220;STM32F103C6T6A Bare Metal Programming &#8211; Compare mode&#8221;, I strongly recommend you to go through that before continuing this.<\/p>\n\n\n\n<p>This is almost opposite of the comapre mode, here whenever an event happen in the physical pin TIMx_CHn, the data from the counter register will be copied into the CCR register. The capture module is used to measure the time between two events in the input.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Exercise<a href=\"https:\/\/github.com\/mshafeeqkn\/STM32F1XX_Sample_Project\/blob\/timer_1_compare\/README.md#exercise-1\"><\/a><\/h4>\n\n\n\n<p>Write a program to print the counter value through the UART when a button is pressed. Since we haven&#8217;t covered the UART now, so you can take the souce code to access UART from my GitHub repository. I have given the link at the end of the post.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Registers used<a href=\"https:\/\/github.com\/mshafeeqkn\/STM32F1XX_Sample_Project\/blob\/timer_1_compare\/README.md#registers-used-1\"><\/a><\/h4>\n\n\n\n<ul>\n<li><mark style=\"background-color:rgba(0, 0, 0, 0);color:#aaaaaa\" class=\"has-inline-color\"><strong>APB2 peripheral clock enable register (RCC_APB2ENR) &#8211;<\/strong>\u00a0Enable the clock source for timer and GPIOA<\/mark><\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0);color:#aaaaaa\" class=\"has-inline-color\"><strong>Port A configuration register high (GPIOA_CRH) &#8211;<\/strong>\u00a0Configure the input pin<\/mark><\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0);color:#aaaaaa\" class=\"has-inline-color\"><strong>Port A output data register (GPIOA_ODR) &#8211;<\/strong>\u00a0Configure the input pin<\/mark><\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0);color:#aaaaaa\" class=\"has-inline-color\"><strong>TIM1 Prescaler register (TIM1_PSC) &#8211;<\/strong>\u00a0Configure the timer<\/mark><\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0);color:#aaaaaa\" class=\"has-inline-color\"><strong>TIM1 auto-reload register (TIM_ARR) &#8211;<\/strong>\u00a0Configure the timer<\/mark><\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0);color:#aaaaaa\" class=\"has-inline-color\"><strong>TIM1 control register 1 (TIM1_CR1) &#8211;<\/strong>\u00a0Enable the timer<\/mark><\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0);color:#aaaaaa\" class=\"has-inline-color\"><strong>TIM1 status register (TIM1_SR) &#8211;<\/strong>\u00a0Capture flag<\/mark><\/li>\n\n\n\n<li><strong>TIM1 capture\/compare mode register 1 (TIM1_CCMR1) &#8211;<\/strong>\u00a0Select the trigger<\/li>\n\n\n\n<li><strong>TIM1 capture\/compare enable register (TIMx_CCER) &#8211;<\/strong>\u00a0Enable the capture mode<\/li>\n\n\n\n<li><strong>TIM1 Capture\/Compare register (TIM1_CCR1) &#8211;<\/strong>\u00a0Take the counter value after capture.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Solution<a href=\"https:\/\/github.com\/mshafeeqkn\/STM32F1XX_Sample_Project\/blob\/timer_1_compare\/README.md#solution-1\"><\/a><\/h4>\n\n\n\n<p>As I mentioned in the compare module post, I am using the TIM1_CH1(PA8) as the input. From the table 22 of reference manual RM0008, the pin should be configured as input floating. But interestingly input pull-up and pull-down also working fine in capture mode. So I am using the pull down mode so that I can connect the pin and 3.3v supply via a push button switch to give logical high input.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Configure GPIOA8 pin as input\nRCC-&gt;APB2ENR |= RCC_APB2ENR_IOPAEN;               \/\/ Enable clock for Port A\nGPIOA-&gt;CRH &amp;= ~(GPIO_CRH_CNF8 | GPIO_CRH_MODE8);  \/\/ Set PA8 as input\nGPIOA-&gt;CRH |= GPIO_CRH_CNF8_1;                    \/\/ Set PA8 as pull-up\/pull-down\nGPIOA-&gt;ODR &amp;= ~(GPIO_ODR_ODR8);                   \/\/ Set PA8 as pull down;\n<\/code><\/pre>\n\n\n\n<p>Enable the timer with random prescalar and auto reload register value<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Enable TIMER1\nRCC-&gt;APB2ENR |= RCC_APB2ENR_TIM1EN;               \/\/ Enable clock for TIM1\nTIM1-&gt;PSC = 0x3FFF;                               \/\/ set prescalar\nTIM1-&gt;ARR = 0xFFFF;                               \/\/ set maximum count\nTIM1-&gt;CR1 |=  TIM_CR1_CEN;                        \/\/ Start the timer.\n<\/code><\/pre>\n\n\n\n<p>Now we have to select the trigger which is used to capture the value. We have so many trigger options that can be chosen. You can check the description of bits 7:4 IC1F: Input capture 1 filter, I am selecting the internal clock for sampling and wait atleast 8 cycles to ensure the state is high or low. So the value of IC1F would be 0011<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Select filter trigger\nTIM1-&gt;CCMR1 &amp;= ~(TIM_CCMR1_IC1F);                 \/\/ Sampling at internal clock and wait unitl 8 cycles\nTIM1-&gt;CCMR1 |= (TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_0);   \/\/ to ensure the low\/high state\n<\/code><\/pre>\n\n\n\n<p>We have configured the input as pull down. So when ever the button is pressed the raising edge will come. So the trigger should be raising edge. And then enable the capture module.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Select edge and channel\nTIM1-&gt;CCMR1 |= TIM_CCMR1_CC1S_0;                  \/\/ CC1 configured as input, IC1 mapped with TI1 (TIM1_CH1)\nTIM1-&gt;CCMR1 &amp;= ~(TIM_CCMR1_IC1PSC);               \/\/ No prescalar. capture on every event on the TI\nTIM1-&gt;CCER &amp;= ~(TIM_CCER_CC1P);                   \/\/ Raising edge of IC1.\nTIM1-&gt;CCER |= TIM_CCER_CC1E;                      \/\/ Capture enabled for channel 1\n<\/code><\/pre>\n\n\n\n<p>So we have completed the capture mode setup. Now from the main function we will wait until the CC1IF flag in the TIM1_SR register is set. When ever it&#8217;s set we can take the counter value from the TIM1_CCR1 register.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>uint16_t data;\nwhile( (TIM1-&gt;SR &amp; TIM_SR_CC1IF) == 0) {}\nTIM1-&gt;SR &amp;= ~(TIM_SR_CC1IF);\ndata = TIM1-&gt;CCR1;\nuart1_send_string(\"Captured data ... 0x%x\\r\\n\", data);\n<\/code><\/pre>\n\n\n\n<p>I have pushed the complete source code in my GitHub page, you can access it from <a href=\"https:\/\/github.com\/mshafeeqkn\/STM32-Bare-Metal\/tree\/master\/TIMER\/TIMER_CAPTURE\">this link<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The CC module can capture the value of the counter at the moment a specified event occurs on an input pin. This is useful for measuring input signal frequencies, pulse widths, and timing intervals. If you haven&#8217;t gone throught my previous post &#8220;STM32F103C6T6A Bare Metal Programming &#8211; Compare mode&#8221;, I strongly recommend you to go &#8230; <a title=\"STM32F103C6T6A Bare Metal Programming &#8211; Capture mode\" class=\"read-more\" href=\"https:\/\/blog.mshafeeq.com\/index.php\/2023\/10\/02\/stm32f103c6t6a-bare-metal-programming-capture-mode\/\" aria-label=\"Read more about STM32F103C6T6A Bare Metal Programming &#8211; Capture mode\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[38,10,15,24,27,36,12],"_links":{"self":[{"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/posts\/450"}],"collection":[{"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/comments?post=450"}],"version-history":[{"count":1,"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/posts\/450\/revisions"}],"predecessor-version":[{"id":451,"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/posts\/450\/revisions\/451"}],"wp:attachment":[{"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/media?parent=450"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/categories?post=450"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mshafeeq.com\/index.php\/wp-json\/wp\/v2\/tags?post=450"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}