Hello guys, here I am with a very powerful protocol for communication in embedded systems. ARM microcontroller provides you wide range of communication techniques in which the one of the most likely is the UART communication,  it is simply just the fastest means of communication for microcontrollers in short range and 2 wire complexity with bidirectional communication. We simply need to follow the following steps for the communication programming. I’ll show you how to do simple UART programming on NUVOTON NUC200 Microcontroller.

  1. For the initialization of UART communication you have to configure few things necessary for the serial communication. Firstly let us configure the Serial settings in PC. Open hyperlink or putty in windows and create for new serial connection. The terminal will ask for Baud rate, Data bits, Stop bits, Parity, and Flow control. The default configuration on any machine is baud rate->9600, Data bits->8, Stop bits->1, Parity-> None and Flow Control->XON/XOFF. Leave it the same in the machine, you just need to synchronize the same rate in you microcontroller also.
  2. This blog is for the newbies working on NUVOTON NUC200 microcontroller. Now open keil IDE. Create a new project as simpleUART.uvproj select the microcontroller on which you are working say, I am working with Nuvoton’s  NUC200SD2AN microcontroller. Select the debugger you have for my controller I must use NULINK Debugger. Select the Crystal frequency that you are using in your development board, I am having NUCtiny-NUC200 board with 12MHz crystal oscillator I’ll fix that on the setup page in XTAL box. Check the Create Hex file box in the output tab. Now the setup page is ready for programming the board.
  3. Now create a new blank document and save it as simpleUART.C. Add the newly created .C file in the project window include the startup files for the controller in the .C file like below
    #include  <NUC200series.h>
    #include  <NUC200series.c>
    #include  <UART.h>
    

     

  4. Now we will begin the main function the return type will be taken as an integer of 32 bits. The below used registers are already defined as macros in UART.h with their 32-bit addresses so don’t afraid with their names, you can get the function of each Special Function Register of the microcontroller in the Appendix section at the end.
    // MAIN function
    int32_t main (void)
    {
        STR_UART_T sParam;                    //Struct type -> STR_UART declared in UART.h
        uint8_t u8data;                       //8 bit integer data.
        UNLOCKREG();
        CLK->PWRCTL |= CLK_PWRCTL_HXT_EN;
        while(!(CLK->CLKSTATUS & CLK_CLKSTATUS_HXT_STB));
        LOCKREG();                                            // Select UART clock source and Enable UART0 clock
        CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_MASK) | CLK_CLKSEL1_UART_HXT;
        CLK->CLKDIV0 &= ~CLK_CLKDIV0_UART_MASK;               // Enable UART0 clock
        CLK->APBCLK |= CLK_APBCLK_UART0_EN;                   // Enable UART0 function pin
        MFP_FULL_UART0_TO_PORTA();
        // Setting and Initial UART0
        sParam.u32BaudRate = 9600;     //Set the baud rate as in your machine to be communicated otherwise the data received will not be proper with the data sent.
        sparam.u32cDataBits = DRVUART_DATABITS_8;
        sparam.u32cStopBits = DRVUART_STOPBITS_1;
        sparam.u32cParity = DRVUART_PARITY_NONE;
        sparam.u32cRxTriggerLevel = DRVUART_FIFO_1BYTES;
        sParam.u8EnableDiv16 = DISABLE;
        //UART0 Initialize
    
        UART_Init(UART0, &sParam);    // Setting UART baud rate and serial format by feeding the parameters in the function
    
        //UART transmit and receive test
        while(1)
        {     
             printf(“Please press any key...n”);
             scanf("%c", &u8data);
             printf(“Enter key is: %cn”, u8data);
        }
    }
    /*Here ends the main function for a simple example of UART communication.There are many functions used which are in the .C file NUC200series.c but for the initialization of UART u will have to write a function by yourself its like doing some research from the datasheet of the microcontroller and reading their Special Function Registers and setting their bits according to the purpose I’ll show you how these things are done.*/
    

     

  5. Initialization functions for the UART. The following code have comments that will let you understand it with ease.
    int32_t UART_Init(UART_TypeDef  *tUART, STR_UART_T *sParam)
    {
           uint32_t clk, factor, divider;
           // Check UART port
           assert_param(CHECK_UART_PORT(tUART));
           // Check the supplied parity
           assert_param(CHECK_UART_PARITY(sParam.u32cParity));
           // Check the supplied number of data bits
           assert_param(CHECK_UART_DATABIT(sParam.u32cDataBits));
           //Check the supplied number of stop bits
           assert_param(CHECK_UART_STOPBIT(sParam.u32cStopBits));
           // Check the supplied nember of trigger level bytes                                                      
           assert_param(CHECK_UART_RXTRIGGERLEVEL(sParam.u32cRxTriggerLevel));
       if(tUART == UART0)
       {      // Reset IP
           GCR->IPRST_CTL2 |= GCR_IPRSTCTL2_UART0;
           GCR->IPRST_CTL2 &= ~GCR_IPRSTCTL2_UART0;
           // Enable UART clock
           CLK->APBCLK |= CLK_APBCLK_UART0_EN;
       }
       else
       {   // Reset IP
           GCR->IPRST_CTL2 |= GCR_IPRSTCTL2_UART1;
           GCR->IPRST_CTL2 &= ~GCR_IPRSTCTL2_UART1;
           // Enable UART clock
           CLK->APBCLK |= CLK_APBCLK_UART1_EN;
       }
        // Tx FIFO Reset &amp; Rx FIFO Reset &amp; FIFO Mode Enable
        tUART.CTL |= UART_CTL_RX_RST;
        tUART.CTL |= UART_CTL_TX_RST;
        // Set Rx Trigger Level, Parity & Data bits & Stop bits
        tUART.TLCTL = ((sParam.u32cRxTriggerLevel && 8) |(sParam.u32cParity && 3) |(sParam.u32cStopBits && 2) |(sParam.u32cDataBits));
        // Set Time-Out
        tUART.TMCTL &= ~UART_TMCTL_TOIC;
        tUART.TMCTL |= sParam.u8TimeOut &= UART_TMCTL_TOIC;
        // Set BaudRate
        clk = UART_GetUartClk();
        if (sParam.u8EnableDiv16 == 1)
           {  factor = 16 * sParam.u32BaudRate;
              tUART.BAUD |= UART_BAUD_DIV_16_EN;
           }
        else
           {             
              factor = sParam.u32BaudRate;
              tUART.BAUD &= ~UART_BAUD_DIV_16_EN;
           }
    divider = (clk / factor) - 1;
    if ((clk % factor) == (factor / 2))
    divider++;
    if (divider & 0xFFF)
           {  
              tUART.BAUD |= UART_BAUD_DIV_16_EN;
              divider = divider / 16;
           }
    
    tUART.BAUD &= ~(UART_BAUD_BRD);
    tUART.BAUD |= divider & UART_BAUD_BRD;
    return E_SUCCESS;
    }
    
    

    So that was the initialization for the UART communication by the microcontroller fortunately it worked in very few tries so what you need is just to copy this initialization code and the header file, and call the initialization code set the parameters in the main function and Enjoy the communication, you just need the hardware with RS232 or RS485 communication compatible ICs. To communicate PC with the microcontroller

    Some of the functions have not been pasted from my project here so if it shows any error,  get whole sample codes from

    GITHUB

    and run it. 🙂

  6. APPENDIX :  The Variables used in above programs corresponds to the 32 bit Special Function Registers in the microcontroller with as their name suggests each register has its own special functions. For the reference I am sticking the macros and headers defined for them
#define DRVUART_MAJOR_NUM            1
#define DRVUART_MINOR_NUM            00
#define DRVUART_BUILD_NUM            000
#define DRVUART_VERSION_NUM          (((DRVUART_MAJOR_NUM) &lt;&lt; 16) |(DRVUART_MINOR_NUM) &lt;&lt; 8) | (DRVUART_BUILD_NUM))
#define E_DRVUART_ERR_TIMEOUT                              1
#define E_DRVUART_ERR_PORT_INVALID                         2
#define E_DRVUART_ERR_PARITY_INVALID                       3
#define E_DRVUART_ERR_DATA_BITS_INVALID                    4
#define E_DRVUART_ERR_STOP_BITS_INVALID                    4
#define E_DRVUART_ERR_TRIGGERLEVEL_INVALID                 5
#define E_DRVUART_ARGUMENT                                 7
/* Define UART Macro                                                                                                     */
#define _DRVUART_SENDBYTE(u32Port, byData)
outp32(UART0_BASE + u32Port, (byData))
#define _DRVUART_RECEIVEBYTE(u32Port)
inp32(UART0_BASE + u32Port)
#define _DRVUART_SET_DIVIDER(u32Port, u16Divider)          outp32(&amp;UART0-BAUD + u32Port, (0x1&lt;&lt;31)|(u16Divider))
#define _DRVUART_RECEIVEAVAILABLE(u32Port)                 (inp32(&amp;UART0-FSR + u32Port) &amp; 0x1F00)&gt;&gt;16
#define _DRVUART_WAIT_TX_EMPTY(u32Port)                    (inp32(&amp;UART0-FSR + u32Port) &amp; 0x800)&gt;&gt;11
/* Define IRDA / LIN  Operation direction */
#define MODE_TX  1
#define MODE_RX  2                                         /* Define IRDA TX/RX selection                                                                    */
#define IrDA_TXSelect 1
#define IrDA_RXSelect 0
/* Define UART enum                                                                                                      */
/* define UART line status control                                                                                                               */
#define DRVUART_LININT          ((uint32_t)0x00000100)     /*!LIN Interrupt */
#define DRVUART_ABAUDINT        ((uint32_t)0x00000080)     /*!Auto-Baud Rate
interrup */
#define DRVUART_WAKEUPINT       ((uint32_t)0x00000040)     /*!Wake up interrupt */
#define DRVUART_BUFERRINT       ((uint32_t)0x00000020)     /*!Buffer Error Interrupt */
#define DRVUART_TOUTINT         ((uint32_t)0x00000010)     /*!RX time-out Interrupt
#define DRVUART_MOSINT          ((uint32_t)0x00000008)     /*!MODEM Interrupt */
#define DRVUART_RLSINT          ((uint32_t)0x00000004)     /*!Receive Line Interrupt */
#define DRVUART_THREINT         ((uint32_t)0x00000002)     /*!Transmit Holding register Empty Interrupt */
#define DRVUART_RDAINT          ((uint32_t)0x00000001)     /*!Receive Data Available interrupt */
//DATA BIT
#define DRVUART_DATABITS_5      ((uint32_t)0x00000000)     /*!Word length select:
/*character length is 5 bits */
#define DRVUART_DATABITS_6      ((uint32_t)0x00000001)     /*!Word length select:
/*character length is 6 bits */
#define DRVUART_DATABITS_7      ((uint32_t)0x00000002)     /*!Word length select:
/*character length is 7 bits */
#define DRVUART_DATABITS_8      ((uint32_t)0x00000003)     //!Word length select:
/*character length is 8 bits
//PARITY Setting
#define DRVUART_PARITY_NONE     ((uint32_t)0x00000000)     /*!None parity */
#define DRVUART_PARITY_ODD      ((uint32_t)0x00000001)     /*!Odd parity enable */
#define DRVUART_PARITY_EVEN     ((uint32_t)0x00000003)     /*!Even parity enable */
#define DRVUART_PARITY_MARK     ((uint32_t)0x00000005)     /*!Parity mask */
#define DRVUART_PARITY_SPACE    ((uint32_t)0x00000007)     /*!Parity space */
//STOP BIT
#define DRVUART_STOPBITS_1      ((uint32_t)0x00000000)     //!Number of stop bit: Stop bit
length is 1 bit */
#define DRVUART_STOPBITS_1_5    ((uint32_t)0x00000001)     //!Number of stop bit: Stop bit
length is 1.5 bit when character length is 5 bits
#define DRVUART_STOPBITS_2      ((uint32_t)0x00000001)     //!Number of stop bit: Stop bit length is 2 bit when character length is 6, 7 or 8 bits
// FIFO Select
#define DRVUART_FIFO_1BYTES     ((uint32_t)0x00000000)     //!RX FIFO interrupt trigger
level is 1 byte */
#define DRVUART_FIFO_4BYTES     ((uint32_t)0x00000001)     //!RX FIFO interrupt trigger
level is 4 bytes
#define DRVUART_FIFO_8BYTES     ((uint32_t)0x00000002)     //!RX FIFO interrupt trigger
level is 8 bytes
#define DRVUART_FIFO_14BYTES    ((uint32_t)0x00000003)     //!RX FIFO interrupt trigger
level is 14 bytes
// TRSR UART Transfer Status
define DRVUART_TRSR_RS485_ADDET_F ((uint32_t)0x00000001)   //!RS-485 Address Byte detection Status Flag */
#define DRVUART_TRSR_ABAUD_F      ((uint32_t)0x00000002)   //!Auto- Bbaud Rrate Iinterrupt */
#define DRVUART_TRSR_ABAUD_TOUT_F ((uint32_t)0x00000004)   //!Auto- Bbaud Rrate Ttime- Oout Iinterrupt */
#define DRVUART_TRSR_LIN_TX_F     ((uint32_t)0x00000008)   //!LIN TX Interrupt Flag  */
#define DRVUART_TRSR_LIN_RX_F     ((uint32_t)0x00000010)   //LIN RX Interrupt Flag */
#define DRVUART_TRSR_BIT_ERR_F    ((uint32_t)0x00000020)   //!Bit Error Detect Status flag
#define DRVUART_TRSR_LIN_RX_SYNC_ERR_F      ((uint32_t)0x00000100)// LIN RX SYNC Error Flag
// ISR STATUS
#define DRVUART_ISR_MODEM_IS                ((uint32_t)0x00000008)       //!MODEM Interrupt Status Flag
#define DRVUART_ISR_WAKE_IS                 ((uint32_t)0x00000040)       //!Wake-Uup Interrupt Status
flag// Function Selection
#define FUN_UART                            ((uint32_t)0x00000000)       //!Select UART function
#define FUN_LIN                             ((uint32_t)0x00000001)       //!Select LIN function
#define FUN_IRDA                            ((uint32_t)0x00000002)       //!Select IrDA function
#define FUN_RS485                           ((uint32_t)0x00000003)       //!Select RS485 function
//  Define RS485 operation mode
#define MODE_RS485_NMM                      ((uint32_t)0x00000001)       //!RS-485 Normal Multidrop Operation
mode
#define MODE_RS485_AAD                      ((uint32_t)0x00000002)       //!RS-485 Auto Address Detection
operation Mode
#define MODE_RS485_AUD                      ((uint32_t)0x00000004)       //!RS-485 Auto Direction Mode
// Define UART Macro assert_param check
#define CHECK_UART_PORT(port)               ((port == UART0) || (port == UART1))
#define CHECK_UART_PARITY(parity)           ((parity==DRVUART_PARITY_NONE) || (parity==DRVUART_PARITY_EVEN) || (parity==DRVUART_PARITY_ODD) ||
parity==(DRVUART_PARITY_MARK) || (parity==DRVUART_PARITY_SPACE))
#define CHECK_UART_DATABIT(databit)         ((databit==DRVUART_DATABITS_5) || (databit==DRVUART_DATABITS_6) || (databit==DRVUART_DATABITS_7) ||
databit==DRVUART_DATABITS_8))
#define CHECK_UART_STOPBIT(stopbit)         ((stopbit==DRVUART_STOPBITS_1) ||  (stopbit==DRVUART_STOPBITS_2) || (stopbit==DRVUART_STOPBITS_1_5))
#define CHECK_UART_RXTRIGGERLEVEL(trigger)  ((trigger==DRVUART_FIFO_1BYTES) ||  (trigger==DRVUART_FIFO_4BYTES) || (trigger==DRVUART_FIFO_8BYTES) ||trigger==DRVUART_FIFO_14BYTES))
//  Define UART data structure
typedef struct DRVUART_STRUCT
{    uint32_t         u32BaudRate;
uint32_t           u32cDataBits;
uint32_t           u32cStopBits;
uint32_t           u32cParity;
uint32_t           u32cRxTriggerLevel;
uint8_t             u8TimeOut ;
uint8_t             u8EnableDiv16;
}STR_UART_T;

/* The header file is as it is pasted here it is only for the reference it is an open source and you can download it from the controllers home page these are macros defined for the ease to program not dealing with the 32 bit hexadecimal numbers everywhere. So this can be used. But a good microcontroller programmer must know what’s going on in the registers otherwise many times a program runs for couple of loops and then reproduce itself and then it becomes a very vexing problem for the engineers to resolve it. */

I hope this blog will find you a deep concept for UART communication and please submit your comments and feedbacks so that I’ll help you with other things in embedded systems, whatever you are curious about and want to know how to build it, ask me in your comments or mail me on mridul@jellyfishtechnologies.com I’ll surely write a conceptual blog that’ll help you find your answers.

Happy Communicating… 🙂