{"id":133,"date":"2014-05-17T12:17:48","date_gmt":"2014-05-17T12:17:48","guid":{"rendered":"http:\/\/visualgdb.com\/w\/?p=133"},"modified":"2017-09-12T22:43:04","modified_gmt":"2017-09-13T05:43:04","slug":"arm-stm32-uart","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/stm32\/uart\/","title":{"rendered":"Using the STM32 UART interface"},"content":{"rendered":"<p><strong>Warning: this tutorial describes a deprecated STM32 StdPeriph API. For detailed instructions on using the new HAL API follow <a href=\"https:\/\/visualgdb.com\/tutorials\/arm\/stm32\/uart\/hal\/\">this tutorial<\/a>.<\/strong><\/p>\n<p>This tutorial shows how to use the STM32 UART interface to exchange some data with the computer. We will use the STM32F100B-eval board to make a basic firmware that will allow the computer to control onboard LEDs by sending on and off commands. We will use the Olimex ARM-USB-OCD-H JTAG programmer that supports JTAG debugging and contains a USB-to-UART adapter. To use this tutorial you will need Visual Studio with <a href=\"\/download\">VisualGDB 4.2<\/a> or later installed.<\/p>\n<ol>\n<li>Start Visual Studio, open VisualGDB Embedded Project Wizard:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/01-newprj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/01-newprj.png\" alt=\"01-newprj\" width=\"700\" height=\"394\" \/><\/a><\/li>\n<li>On the first page of the wizard proceed with the default project type:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/02-elf.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/02-elf.png\" alt=\"02-elf\" width=\"702\" height=\"565\" \/><\/a><\/li>\n<li>On the third page select the ARM toolchain and the STM32F100VB device. If you don&#8217;t have the toolchain or the BSP, VisualGDB will allow installing them from the wizard:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/03-device.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/03-device.png\" alt=\"03-device\" width=\"702\" height=\"565\" \/><\/a><\/li>\n<li>Proceed with the default &#8220;LED Blink&#8221; sample:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/04-sample.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/04-sample.png\" alt=\"04-sample\" width=\"702\" height=\"565\" \/><\/a><\/li>\n<li>Select &#8220;OpenOCD&#8221; as the debug method. Connect your USB programmer and click &#8220;Detect&#8221;. Then press &#8220;Test selected OpenOCD settings&#8221; to verify them:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/05-openocd.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/05-openocd.png\" alt=\"05-openocd\" width=\"702\" height=\"568\" \/><\/a><\/li>\n<li>Press &#8220;Finish&#8221; to create your project. Build the sample project with Ctrl-Shift-B and ensure you can debug it by pressing F5:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/06-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/06-debug.png\" alt=\"06-debug\" width=\"699\" height=\"622\" \/><\/a><\/li>\n<li>Now we will add the UART support. Add the following code before your main() function:\n<pre class=\"\">#include &lt;stm32f10x_usart.h&gt;\r\n\r\nvoid InitializeUSART()\r\n{\r\n    USART_InitTypeDef usartConfig;\r\n\r\n    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);\r\n    USART_Cmd(USART1, ENABLE); \r\n\r\n    usartConfig.USART_BaudRate = 9600; \r\n    usartConfig.USART_WordLength = USART_WordLength_8b; \r\n    usartConfig.USART_StopBits = USART_StopBits_1; \r\n    usartConfig.USART_Parity = USART_Parity_No;\r\n    usartConfig.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;\r\n    usartConfig.USART_HardwareFlowControl = USART_HardwareFlowControl_None;\r\n    USART_Init(USART1, &amp;usartConfig);\r\n\r\n    GPIO_InitTypeDef gpioConfig;\r\n\r\n    \/\/PA9 = USART1.TX =&gt; Alternative Function Output\r\n    gpioConfig.GPIO_Mode = GPIO_Mode_AF_PP;\r\n    gpioConfig.GPIO_Pin = GPIO_Pin_9;\r\n    gpioConfig.GPIO_Speed = GPIO_Speed_2MHz;\r\n    GPIO_Init(GPIOA, &amp;gpioConfig);\r\n\r\n    \/\/PA10 = USART1.RX =&gt; Input\r\n    gpioConfig.GPIO_Mode = GPIO_Mode_IN_FLOATING;\r\n    gpioConfig.GPIO_Pin = GPIO_Pin_10;\r\n    GPIO_Init(GPIOA, &amp;gpioConfig);\r\n}\r\n\r\nunsignedchar USART_ReadByteSync(USART_TypeDef *USARTx)\r\n{\r\n    while ((USARTx-&gt;SR &amp; USART_SR_RXNE) == 0)\r\n    {\r\n    }\r\n\r\n    return (unsigned char)USART_ReceiveData(USARTx);\r\n}<\/pre>\n<\/li>\n<li>The easiest way to test the UART interface is to connect the RX and TX pins together and see whether the sent data gets echoed back. Put a jumper between pins 2 and 3 on the USART1 plug:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/07-jumper.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/07-jumper.jpg\" alt=\"07-jumper\" width=\"700\" height=\"230\" \/><\/a><\/li>\n<li>Then replace the contents of the for() loop in main() with the code that sends a value of 0x55 to the UART and reads is back:\n<pre class=\"\">InitializeUSART();\r\n\r\nfor (;;)\r\n{\r\n    USART_SendData(USART1, 0x55);\r\n    unsigned char byte = USART_ReadByteSync(USART1);\r\n\r\n    asm(\"nop\");\r\n}<\/pre>\n<\/li>\n<li>Put a breakpoint on the &#8220;nop&#8221; line. Start debugging your firmware. Ensure that your breakpoint hits and the value of &#8216;byte&#8217; matches the value sent to the UART:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/08-readback.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/08-readback.png\" alt=\"08-readback\" width=\"700\" height=\"531\" \/><\/a><\/li>\n<li>Install the USB-to-RS232 drivers for the Olimex JTAG programmer. They can be found in the CDM20808 folder in the <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/stm32\/uart\/https:\/\/www.olimex.com\/Products\/ARM\/JTAG\/_resources\/OpenOCD_OnlinePackage_v1.1.zip\"> Olimex driver package<\/a>. The second device instance should be appear as &#8216;USB Serial Converter B&#8217; in Device Manager:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/09-port.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/09-port.png\" alt=\"09-port\" width=\"428\" height=\"108\" \/><\/a><\/li>\n<li>Go to VisualGDB project properties. Enable the Raw Terminal on the COM port displayed in the Device Manager. Set the speed to the same value as you specified in InitializeUSART(). In this example we use 9600:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/10-com3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/10-com3.png\" alt=\"10-com3\" width=\"700\" height=\"592\" \/><\/a>Select the &#8216;text and hex&#8217; mode and enable echoing of entered characters.<\/li>\n<li>Connect the UART port on the Olimex programmer with UART1 on your board. If you don&#8217;t have a cable, you can solder one very simply: connect pins #5 (ground), #2 (tx) and #3 (rx). Note that pin #2 on either side should be connected to pin #3 on the other side and vice versa. This ensures that the sender is connected to a receiver on the opposite side:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/11-comport.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-11\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/11-comport.jpg\" alt=\"11-comport\" width=\"400\" height=\"230\" \/><\/a><\/li>\n<li>Start debugging with F5 and open the terminal. You will see the 0x55 character in the raw terminal. Click the &#8216;break all&#8217; button to see what code is currently running. You will see that your firmware is waiting for a reply on the COM port. You can use the Hardware Registers window to examine the USART module registers:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/12-readdata.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-12\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/12-readdata.png\" alt=\"12-readdata\" width=\"700\" height=\"780\" \/><\/a><\/li>\n<li>Press F5 to resume debugging. Type something (e.g. 5A) in reply. See how the reply you typed ended up in the &#8216;byte&#8217; variable:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/13-terminal.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-13\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/13-terminal.png\" alt=\"13-terminal\" width=\"700\" height=\"530\" \/><\/a>The values of 0x55 and 0x5A are chosen because of their binary representation: <strong>0101 0101<\/strong> and <strong>0101 1010<\/strong>. If the UART speed is chosen slightly incorrectly and a single bit transmission is longer or shorter than expected and overlaps with the next bit, those values will be received incorrectly giving an early indication of the problem.<\/li>\n<li>Now we will add text mode support to our example. We will add a basic interface that will ask for a command and run it. It will support 2 commands: &#8216;led&#8217; and &#8216;help&#8217;. Replace your main() with the following code:\n<pre class=\"\">#include &lt;stdio.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\nint main()\r\n{\r\n    GPIO_InitTypeDef GPIO_InitStructure;\r\n\r\n    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);\r\n\r\n    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;\r\n\r\n    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;\r\n    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\r\n    GPIO_Init(GPIOC, &amp;GPIO_InitStructure);\r\n\r\n    InitializeUSART();\r\n    static const int LEDs[] = {GPIO_Pin_6, GPIO_Pin_7, GPIO_Pin_8, GPIO_Pin_9};\r\n\r\n    for (;;)\r\n    {\r\n        printf(\"Enter a command: \");\r\n        char sz[32];\r\n        scanf(\"%31s\", sz);\r\n        if (!strcmp(sz, \"help\"))\r\n        {\r\n            printf(\"Supported commands:\\r\\n\");\r\n            printf(\"\\thelp\\r\\n\\tled &lt;number&gt; &lt;on|off&gt;\\r\\n\");\r\n        }\r\n        else if (!strcmp(sz, \"led\"))\r\n        {\r\n            unsigned number = 0;\r\n            scanf(\"%d%31s\", &amp;number, sz);\r\n            bool on;\r\n            if (!strcmp(sz, \"on\"))\r\n                on = true;\r\n            else if (!strcmp(sz, \"off\"))\r\n                on = false;\r\n            else\r\n            {\r\n                printf(\"Invalid mode: %s\\r\\n\", sz);\r\n                continue;\r\n            }\r\n\r\n            if (number &lt;= 0 || \r\n                number &gt; sizeof(LEDs)\/sizeof(LEDs[0]))\r\n            {\r\n                printf(\"Invalid LED number: %d\\r\\n\", number);\r\n                continue;\r\n            }\r\n\r\n           if (on)\r\n               GPIO_SetBits(GPIOC, LEDs[number - 1]);\r\n           else\r\n               GPIO_ResetBits(GPIOC, LEDs[number - 1]);\r\n       }\r\n       else\r\n           printf(\"Invalid command\\r\\n\");\r\n    }\r\n}<\/pre>\n<\/li>\n<li>If you build the project now, the linker complain about certain syscall implementations missing. Here are the most important ones:\n<ul>\n<li><strong>_sbrk<\/strong> dynamically increases the heap size. The heap starts right after the &#8220;end&#8221; symbol defined by the linker and is extended on demand until a collision with the stack pointer is detected.<\/li>\n<li><strong>_fstat<\/strong>\/<strong>_isatty <\/strong>are used to tell the C library that stdout is a console and not a file and should not be buffered excessively.<\/li>\n<li><strong>_read<\/strong>\/<strong>_write<\/strong> are called by the C library to actually transfer the data.<\/li>\n<\/ul>\n<p>Add a new file to the project (e.g. syscalls.cpp) and paste the following code into it:<\/p>\n<pre class=\"\">#include &lt;stdio.h&gt;\r\n#include &lt;sys\/stat.h&gt;\r\n#include &lt;stm32f10x_usart.h&gt;\r\n\r\nextern \"C\"\r\n{\r\n    int _fstat (int fd, struct stat *pStat)\r\n    {\r\n        pStat-&gt;st_mode = S_IFCHR;\r\n       return 0;\r\n    }\r\n\r\n    int _close(int)\r\n    {\r\n       return -1;\r\n    }\r\n\r\n    int _write (int fd, char *pBuffer, int size)\r\n    {\r\n        for (int i = 0; i &lt; size; i++)\r\n        {\r\n            while (!(USART1-&gt;SR &amp; USART_SR_TXE))\r\n            {\r\n            }\r\n            USART_SendData(USART1, pBuffer[i]);\r\n        }\r\n        return size;\r\n    }\r\n\r\n    int _isatty (int fd)\r\n    {\r\n       return 1;\r\n    }\r\n\r\n    int _lseek(int, int, int)\r\n    {\r\n       return -1;\r\n    }\r\n\r\n    int _read (int fd, char *pBuffer, int size)\r\n    {\r\n        for (int i = 0; i &lt; size; i++)\r\n        {\r\n            while ((USART1-&gt;SR &amp; USART_SR_RXNE) == 0)\r\n            {\r\n            }\r\n\r\n            pBuffer[i] = USART_ReceiveData(USART1);\r\n        }\r\n        return size;\r\n    }\r\n\r\n    caddr_t _sbrk(int increment)\r\n    {\r\n       extern char end asm(\"end\");\r\n       register char *pStack asm(\"sp\");\r\n\r\n       static char *s_pHeapEnd;\r\n\r\n       if (!s_pHeapEnd)\r\n            s_pHeapEnd = &amp;end;\r\n\r\n       if (s_pHeapEnd + increment &gt; pStack)\r\n            return (caddr_t)-1;\r\n\r\n        char *pOldHeapEnd = s_pHeapEnd;\r\n        s_pHeapEnd += increment;\r\n        return (caddr_t)pOldHeapEnd;\r\n    }\r\n}<\/pre>\n<\/li>\n<li>Switch the Raw Terminal to text mode, build your firmware and start debugging. Enter some commands and observe the LEDs:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/14-textterm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-14\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/14-textterm.png\" alt=\"14-textterm\" width=\"701\" height=\"675\" \/><\/a><\/li>\n<li>You can use the Embedded Memory Explorer window to analyze the footprint of your firmware. By analyzing the footprint of this example you can see that adding text mode support considerably increased the code size due to heavy functions related to sprintf():<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/15-memexp.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/uart\/15-memexp.png\" alt=\"15-memexp\" width=\"701\" height=\"675\" \/><\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Warning: this tutorial describes a deprecated STM32 StdPeriph API. For detailed instructions on using the new HAL API follow this<\/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":[61,70],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/133"}],"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=133"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/133\/revisions"}],"predecessor-version":[{"id":3230,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/133\/revisions\/3230"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}