{"id":1126,"date":"2020-11-03T23:06:29","date_gmt":"2020-11-03T22:06:29","guid":{"rendered":"https:\/\/www.klokocka.info\/?p=1126"},"modified":"2020-11-15T20:44:09","modified_gmt":"2020-11-15T19:44:09","slug":"stm32-cubemx-cubeide-usart-receive-by-interrupt-different-way","status":"publish","type":"post","link":"https:\/\/www.klokocka.info\/?p=1126","title":{"rendered":"STM32, CubeMX &#8211; USART &#8211; receive by interrupt &#8211; different way"},"content":{"rendered":"\n<p><\/p>\n\n\n<style>.wp-block-kadence-advancedheading.kt-adv-heading_67c3cb-27, .wp-block-kadence-advancedheading.kt-adv-heading_67c3cb-27[data-kb-block=\"kb-adv-heading_67c3cb-27\"]{font-style:normal;}.wp-block-kadence-advancedheading.kt-adv-heading_67c3cb-27 mark.kt-highlight, .wp-block-kadence-advancedheading.kt-adv-heading_67c3cb-27[data-kb-block=\"kb-adv-heading_67c3cb-27\"] mark.kt-highlight{font-style:normal;color:#f76a0c;-webkit-box-decoration-break:clone;box-decoration-break:clone;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.wp-block-kadence-advancedheading.kt-adv-heading_67c3cb-27 img.kb-inline-image, .wp-block-kadence-advancedheading.kt-adv-heading_67c3cb-27[data-kb-block=\"kb-adv-heading_67c3cb-27\"] img.kb-inline-image{width:150px;vertical-align:baseline;}<\/style>\n<h3 id=\"kt-adv-heading_67c3cb-27\" class=\"kt-adv-heading_67c3cb-27 wp-block-kadence-advancedheading\">The clasic way:<\/h3>\n\n\n\n<ol class=\"wp-block-list\"><li>Generate project by Cube, enable USART in asynchronous mode and enable global interrupt<\/li><li>Insert function HAL_UART_Receive_IT(&#8230;) to main() function before while() loop.<\/li><li>Write HAL_UART_RxCpltCallback(&#8230;) function for interrupt callback and insert code for processing RX data<\/li><\/ol>\n\n\n\n<p>This way has a drawback &#8211; you have to know the amount of received data. In this case RXBUFFERSIZE 10. Callback function si called only when 10 characters have been received. And in my case it didn&#8217; work well, sometimes interrupt was not executed. (STM32F103C8T6, CubeIDE 1.4.2, CubeMX 6.0.1, FW F1xx 1.8.2) <\/p>\n\n\n\n<p>Although it is possible to set buffer size to 1, interupt callback function is then called after receiving every character. It worked, but sometimes it stuck on interrupt. I didn&#8217;t  try to solve it, i had read somwhere at st.com forum that this way is not recomended.<\/p>\n\n\n\n<p><strong>main.c<\/strong><\/p>\n\n\n\n<p>Define buffer size:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Private define ------------------------------------------------------------*\/\n\/* USER CODE BEGIN PD *\/\n#define RXBUFFERSIZE 10\n\/* USER CODE END PD *\/<\/pre>\n\n\n\n<p>Define buffer<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Private variables ---------------------------------------------------------*\/\nUART_HandleTypeDef huart1;\n\/* USER CODE BEGIN PV *\/\nvolatile uint8_t rxBuff[RXBUFFERSIZE]\n\/* USER CODE END PV *\/<\/pre>\n\n\n\n<p>Insert usart IT start function HAL_UART_Receive_IT() before while {}:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int main(void)\n{\n.\n.\n.\n MX_USART3_UART_Init();\n  \/* USER CODE BEGIN 2 *\/\n     HAL_UART_Receive_IT(&amp;huart1, (uint8_t *)rxBuff, RXBUFFERSIZE);\n  \/* USER CODE END 2 *\/<\/pre>\n\n\n\n<p>Write callback function HAL_UART_RxCpltCallback() (which is defined in stm32f1xx_hal_uart.c) and insert code for processing rx data.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* USER CODE BEGIN 4 *\/\nvoid HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {\n    if(UartHandle->Instance == USART1)\n    {\n        \/\/ HERE INSERT THE CODE FOR PROCESS RX DATA:\n        YourFunctionForProcessRXData((uint8_t *)rxd);\n        \/\/THIS FUNCTION RE-ENABLES INTERRUPT\n        HAL_UART_Receive_IT(&amp;huart1, (uint8_t *)rxd, 1);\n    }\n}\n\/* USER CODE END 4 *\/<\/pre>\n\n\n<style>.wp-block-kadence-advancedheading.kt-adv-heading_92e741-b7, .wp-block-kadence-advancedheading.kt-adv-heading_92e741-b7[data-kb-block=\"kb-adv-heading_92e741-b7\"]{font-style:normal;}.wp-block-kadence-advancedheading.kt-adv-heading_92e741-b7 mark.kt-highlight, .wp-block-kadence-advancedheading.kt-adv-heading_92e741-b7[data-kb-block=\"kb-adv-heading_92e741-b7\"] mark.kt-highlight{font-style:normal;color:#f76a0c;-webkit-box-decoration-break:clone;box-decoration-break:clone;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.wp-block-kadence-advancedheading.kt-adv-heading_92e741-b7 img.kb-inline-image, .wp-block-kadence-advancedheading.kt-adv-heading_92e741-b7[data-kb-block=\"kb-adv-heading_92e741-b7\"] img.kb-inline-image{width:150px;vertical-align:baseline;}<\/style>\n<h3 id=\"kt-adv-heading_92e741-b7\" class=\"kt-adv-heading_92e741-b7 wp-block-kadence-advancedheading\">The different way<\/h3>\n\n\n\n<p>In this way the interrupt is executed when every character is received and doesn&#8217;t use HAL_UART_Receive_IT(&#8230;) and HAL_UART_RxCpltCallback(&#8230;) functions.  I found it here: <\/p>\n\n\n\n<p><a href=\"https:\/\/community.st.com\/s\/question\/0D50X00009XkggBSAR\/stm32cube-uart-receive-interrupt\" data-type=\"URL\" data-id=\"https:\/\/community.st.com\/s\/question\/0D50X00009XkggBSAR\/stm32cube-uart-receive-interrupt\">https:\/\/community.st.com\/s\/question\/0D50X00009XkggBSAR\/stm32cube-uart-receive-interrupt<\/a><\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Generate project by CubeMX, enable USART in asynchronous mode and enable global interrupt<\/li><li>Insert code in main.c before while{} to enable appropriate interupts<\/li><li>Insert code to stm32f1xx_it into USART1_IRQHandler to handle interrupt<\/li><li>Write function called from USART1_IRQHandler to process data, which fills receive buffer and sets a flag when buffer is ful or for example &#8216;\\r&#8217; (or &#8216;\\n&#8217; ) is received (enter key)<\/li><\/ol>\n\n\n\n<p><strong>Step 1<\/strong> &#8211; <strong>main.c<\/strong> <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int main(void)\n{\n.\n.\n.\n  MX_USART1_UART_Init();\n\n  \/* USER CODE BEGIN 2 *\/\n  \/\/ enable interrupts\n   __HAL_UART_ENABLE_IT(&amp;huart3, UART_IT_RXNE);\n  HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);\n  HAL_NVIC_EnableIRQ(USART3_IRQn);\n  \/* USER CODE BEGIN 2 *\/<\/pre>\n\n\n\n<p><strong>Step 2 &#8211; stm32f1xx_it.c<\/strong><\/p>\n\n\n\n<p>Define global buffer variable and write code inside USART1_IRQHandler:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">uint8_t incomingChars;\n.\n.\nvoid USART1_IRQHandler(void)\n{\n  \/* USER CODE BEGIN USART1_IRQn 0 *\/\n\t ich = USART1->DR;\n\t Interrupt_USART1(&amp;incomingChars,sizeof(incomingChars));\n         \/\/it is not necessary to call  HAL_UART_IRQHandler(), so return.\t \n         return; \n  \/* USER CODE END USART3_IRQn 0 *\/\n  HAL_UART_IRQHandler(&amp;huart3);\n  \/* USER CODE BEGIN USART3_IRQn 1 *\/\n  \/* USER CODE END USART1_IRQn 1 *\/\n}<\/pre>\n\n\n\n<p><strong>Step 3 &#8211; main.c<\/strong><\/p>\n\n\n\n<p>Write function which will be called by USART1_IRQHandler interupt routine:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void Interrupt_USART3(uint8_t *pData, uint16_t Size) {\n   \/*\n   - Insert code for filling rx buffer\n   - Set a flag when Enter is received or buffer is full \n   - Write code in main() while() loop to process data and reset flag\n   *\/\n    \n\t\/\/\n\tif(pData[k] != '\\n' &amp;&amp; rxDataReceivedFlag == 0) { \/\/skip '\\n'\n        if(i &lt; USART_RXBUFFERSIZE &amp;&amp; pData[k] != '\\r' ) { \/\/check carriage return\n\t    USARTreceiveBuffer[i] = pData[k]; \/\/add to buffer\n            i++;\n        } else { \n            \/\/in case the buffer is at the end - returns only overlaping characters\n            if(i >= USART_RXBUFFERSIZE) {\n                i = 0;\n                return;\n            } else { \/\/end the bufferr with '\\0' and set flag\n                USARTreceiveBuffer[i] = '\\0';\n                rxDataReceivedFlag = i; \/\/flag is used also as length\n\t        i = 0;\n            }\n        }\n    }\n}\n<\/pre>\n\n\n\n<p><strong>Step 4 &#8211; main.c<\/strong><\/p>\n\n\n\n<p>Define flag as global variable<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Private variables ---------------------------------------------------------*\/\nUART_HandleTypeDef huart1;\n\/* USER CODE BEGIN PV *\/\nvolatile uint8_t rxBuff[RXBUFFERSIZE]\nuint8_t rxDataReceivedFlag  = 0;\n\/* USER CODE END PV *\/<\/pre>\n\n\n\n<p>Within main() while() loop check the flag , do something with data and reset the flag<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Infinite loop *\/\n\/* USER CODE BEGIN WHILE *\/\nwhile (1)\n{\n\tif(rxCmdReceivedFlag != 0) {\n\t\tHAL_UART_Transmit(&amp;huart3, USARTcommandBuffer,rxCmdReceivedFlag, HAL_MAX_DELAY);\n\t\trxCmdReceivedFlag = 0; \/\/flag is used also as length\n\t}\n.\n.\n.\n}\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Ring Buffer<\/h3>\n\n\n\n<p>The best way to handle  incoming serial data is to use ring buffer. I did mine solution using this very good article:<\/p>\n\n\n\n<p><a href=\"http:\/\/www.simplyembedded.org\/tutorials\/interrupt-free-ring-buffer\/\">http:\/\/www.simplyembedded.org\/tutorials\/interrupt-free-ring-buffer\/<\/a><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/main.c - global variable\nstatic rbd_t _rbd;\nstatic char _rbmem[32]; \/\/must be a power of 2 (2,4,8,16,32,64...)\n.\n.\n.\n\/\/main.c - within main() function, before while() - init ring buffer\nring_buffer_init(&amp;_rbd, &amp;attr)\n\n\/\/main.c - Interrupt_USART1()\nvoid Interrupt_USART1(uint8_t *pData, uint16_t Size) {\n\tif(USART1->SR &amp; UART_IT_RXNE) \/\/ = if (USART1->SR &amp; UART_IT_RXNE)\n\t{\n\t    const char c = USART1->DR;\n\t    ring_buffer_put(_rbd, &amp;c);\n\t}\n}\n\n\/\/main.c - within main() function, inside while() loop - check if there are data...\n\nring_buffer_get(_rbd, &amp;c);\n\n\/\/...and print or do somtehing with obtained c character \n<\/pre>\n\n\n\n<p>In other project i used this ring buffer solution, very simple, very good:<\/p>\n\n\n\n<p><a href=\"http:\/\/contiki.sourceforge.net\/docs\/2.6\/a01686.html#ga2972cc12c40c75e5c883e831ff8c14ab\">http:\/\/contiki.sourceforge.net\/docs\/2.6\/a01686.html#ga2972cc12c40c75e5c883e831ff8c14ab<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The clasic way: Generate project by Cube, enable USART in asynchronous mode and enable global interrupt Insert function HAL_UART_Receive_IT(&#8230;) to main() function before while() loop. Write HAL_UART_RxCpltCallback(&#8230;) function for interrupt callback and insert code for processing RX data This way &hellip; <a href=\"https:\/\/www.klokocka.info\/?p=1126\">Continued<\/a><\/p>\n","protected":false},"author":1,"featured_media":1139,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"kt_blocks_editor_width":"","pgc_sgb_lightbox_settings":"","footnotes":""},"categories":[8],"tags":[],"class_list":["post-1126","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-nezarazene"],"_links":{"self":[{"href":"https:\/\/www.klokocka.info\/index.php?rest_route=\/wp\/v2\/posts\/1126","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.klokocka.info\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.klokocka.info\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.klokocka.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.klokocka.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1126"}],"version-history":[{"count":55,"href":"https:\/\/www.klokocka.info\/index.php?rest_route=\/wp\/v2\/posts\/1126\/revisions"}],"predecessor-version":[{"id":1210,"href":"https:\/\/www.klokocka.info\/index.php?rest_route=\/wp\/v2\/posts\/1126\/revisions\/1210"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.klokocka.info\/index.php?rest_route=\/wp\/v2\/media\/1139"}],"wp:attachment":[{"href":"https:\/\/www.klokocka.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.klokocka.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1126"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.klokocka.info\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}