CortexM0 development - How to use UART of LPC11C14

Publisher:明月昊天Latest update time:2019-01-15 Source: eefocusKeywords:CortexM0  LPC11C14  UART Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

LPC1100 Series Microcontroller UART LPC1100 series Cortex-M0 microcontroller has an asynchronous serial port (UART) that complies with the 16C550 industrial standard. This port also adds a modem interface, and the DSR, DCD and RI Modem signals are only used for the pin configuration of the LQFP48 and PLCC44 packages. 


 characteristic  


 16-byte transmit and receive FIFO; 


 Register location complies with 16C550 industrial standard;  


 Receiver FIFO trigger point can be 1, 4, 8 and 14 bytes; 


 Built-in baud rate generator;  


 Fractional divider for precise baud rate control, and automatic baud rate detection capability and mechanism for software flow control;  


 Support software or hardware flow control execution;  


 Contains standard Modem interface signals (CTS, DCD, DTS, DTR, RI, RTS); 


 Supports 9-bit mode and output enable of RS-458/EIA-485.



【Experimental steps】:


First look at the schematic diagram of the UART on the board



PL-2303HX is a UART-USB chip. Let's ignore its principle here. We only learn how to send data from the CPU to this TXD RXD.


1. LPC11C14 UART register description



Only part of it is posted here



The specific register analysis will not be elaborated here. Let's first look at how we define it in the header file.

 

/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/  

/** @addtogroup LPC11xx_UART LPC11xx Universal Asynchronous Receiver/Transmitter  

  @{ 

*/  

typedef struct  

{  

  union {  

  __I  uint32_t  RBR;                   /*!< Offset: 0x000 Receiver Buffer  Register (R/ ) */  

  __O  uint32_t  THR;                   /*!< Offset: 0x000 Transmit Holding Register ( /W) */  

  __IO uint32_t  DLL;                   /*!< Offset: 0x000 Divisor Latch LSB (R/W) */  

  };  

  union {  

  __IO uint32_t  DLM;                   /*!< Offset: 0x004 Divisor Latch MSB (R/W) */  

  __IO uint32_t  IER;                   /*!< Offset: 0x000 Interrupt Enable Register (R/W) */  

  };  

  union {  

  __I  uint32_t  IIR;                   /*!< Offset: 0x008 Interrupt ID Register (R/ ) */  

  __O  uint32_t  FCR;                   /*!< Offset: 0x008 FIFO Control Register ( /W) */  

  };  

  __IO uint32_t  LCR;                   /*!< Offset: 0x00C Line Control Register (R/W) */  

  __IO uint32_t  MCR;                   /*!< Offset: 0x010 Modem control Register (R/W) */  

  __I  uint32_t  LSR;                   /*!< Offset: 0x014 Line Status Register (R/ ) */  

  __I  uint32_t  MSR;                   /*!< Offset: 0x018 Modem status Register (R/ ) */  

  __IO uint32_t  SCR;                   /*!< Offset: 0x01C Scratch Pad Register (R/W) */  

  __IO uint32_t  ACR;                   /*!< Offset: 0x020 Auto-baud Control Register (R/W) */  

       uint32_t  RESERVED0;  

  __IO uint32_t  FDR;                   /*!< Offset: 0x028 Fractional Divider Register (R/W) */  

       uint32_t  RESERVED1;  

  __IO uint32_t  TER;                   /*!< Offset: 0x030 Transmit Enable Register (R/W) */  

       uint32_t  RESERVED2[6];  

  __IO uint32_t  RS485CTRL;             /*!< Offset: 0x04C RS-485/EIA-485 Control Register (R/W) */  

  __IO uint32_t  ADRMATCH;              /*!< Offset: 0x050 RS-485/EIA-485 address match Register (R/W) */  

  __IO uint32_t  RS485DLY;              /*!< Offset: 0x054 RS-485/EIA-485 direction control delay Register (R/W) */  

  __I  uint32_t  FIFOLVL;               /*!< Offset: 0x058 FIFO Level Register (R) */  

} LPC_UART_TypeDef;  

/*@}*/ /* end of group LPC11xx_UART */  

Related macro definitions (partial)



****************************************************************************/  

#ifndef __UART_H   

#define __UART_H  

  

#define RS485_ENABLED   0  

#define TX_INTERRUPT    0       /* 0 if TX uses polling, 1 interrupt driven. */  

#define MODEM_TEST      0  

  

#define IER_RBR         (0x01<<0)  

#define IER_THRE        (0x01<<1)  

#define IER_RLS         (0x01<<2)  

  

#define IIR_PEND        0x01  

#define IIR_RLS         0x03  

#define IIR_RDA         0x02  

#define IIR_CTI         0x06  

#define IIR_THRE        0x01  

  

#define LSR_RDR         (0x01<<0)  

#define LSR_OE          (0x01<<1)  

#define LSR_PE          (0x01<<2)  

#define LSR_FE          (0x01<<3)  

#define LSR_BI          (0x01<<4)  

#define LSR_THRE        (0x01<<5)  

#define LSR_TEMT        (0x01<<6)  

#define LSR_RXFE        (0x01<<7)  

  

#define UART0_RBUF_SIZE 64  


2. UART initialization


[cpp] view plain copy  

/***************************************************************************** 

** Function name:       UARTInit 

** 

** Descriptions:        Initialize UART0 port, setup pin select, 

**                      clock, parity, stop bits, FIFO, etc. 

** 

** parameters:          UART baudrate 

** Returned value:      None 

**  

*****************************************************************************/  

void UARTInit(uint32_t baudrate)  

{  

  uint32_t Fdiv;  

  uint32_t regVal;  

  

  UARTTxEmpty = 1;  

  UARTCount = 0;  

    

  NVIC_DisableIRQ(UART_IRQn);  

  

  LPC_IOCON->PIO1_6 &= ~0x07;    /*  UART I/O config */  

  LPC_IOCON->PIO1_6 |= 0x01;     /* UART RXD */  

  LPC_IOCON->PIO1_7 &= ~0x07;      

  LPC_IOCON->PIO1_7 |= 0x01;     /* UART TXD */  

  

  /* Enable UART clock */  

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);  

  LPC_SYSCON->UARTCLKDIV = 0x1;     /* divided by 1 */  

  

  LPC_UART->LCR = 0x83;             /* 8 bits, no Parity, 1 Stop bit */  

  regVal = LPC_SYSCON->UARTCLKDIV;  

  Fdiv = ((SystemAHBFrequency/regVal)/16)/baudrate ;    /*baud rate */  

  

  LPC_UART->DLM = Fdiv / 256;                              

  LPC_UART->DLL = Fdiv % 256;  

  LPC_UART->LCR = 0x03;      /* DLAB = 0 */  

  LPC_UART->FCR = 0x07;      /* Enable and reset TX and RX FIFO. */  

  

  /* Read to clear the line status. */  

  regVal = LPC_UART->LSR;  

  

  /* Ensure a clean start, no data in either TX or RX FIFO. */  

  while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );  

  while ( LPC_UART->LSR & LSR_RDR )  

  {  

    regVal = LPC_UART->RBR;  /* Dump data from RX FIFO */  

  }  

   

  /* Enable the UART Interrupt */  

  NVIC_EnableIRQ(UART_IRQn);  

  

#if TX_INTERRUPT  

  LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS;  /* Enable UART interrupt */  

#else  

  LPC_UART->IER = IER_RBR | IER_RLS; /* Enable UART interrupt */  

#endif  

  return;  

}  


UART and CPIO ports are multiplexed in CortexM0. Here we see PIO1_6 and PIO1_7 are used.



1. Set the IO port


Take PIO1_7 register as an example



You can see that the lower 3 bits are used to configure pin function 001 to TXD, and the configuration of PIO1_6 is the same.


LPC_IOCON->PIO1_6 &= ~0x07;    /*  UART I/O config */  

LPC_IOCON->PIO1_6 |= 0x01;     /* UART RXD */  

LPC_IOCON->PIO1_7 &= ~0x07;    

LPC_IOCON->PIO1_7 |= 0x01;     /* UART TXD */  

2. Clock settings


/* Enable UART clock */  

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);  

  LPC_SYSCON->UARTCLKDIV = 0x1;     /* divided by 1 */  

3. Set the baud rate and data bit

 

LPC_UART->LCR = 0x83;             /* 8 bits, no Parity, 1 Stop bit */  

regVal = LPC_SYSCON->UARTCLKDIV;  

Fdiv = ((SystemAHBFrequency/regVal)/16)/baudrate ;  /*baud rate */  

4. UART corresponding configuration


LPC_UART->DLM = Fdiv / 256;                            

LPC_UART->DLL = Fdiv % 256;  

LPC_UART->LCR = 0x03;        /* DLAB = 0 */  

LPC_UART->FCR = 0x07;        /* Enable and reset TX and RX FIFO. */  

Line 4 FCR is the FIFO control register. It controls the use and mode of the UART FIFO. 



5. Enable interrupt and other operations


  /* Read to clear the line status. */  

  regVal = LPC_UART->LSR;  

  

  /* Ensure a clean start, no data in either TX or RX FIFO. */  

  while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );  

  while ( LPC_UART->LSR & LSR_RDR )  

  {  

    regVal = LPC_UART->RBR;  /* Dump data from RX FIFO */  

  }  

   

  /* Enable the UART Interrupt */  

  NVIC_EnableIRQ(UART_IRQn);  

  

#if TX_INTERRUPT  

  LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS;  /* Enable UART interrupt */  

#else  

  LPC_UART->IER = IER_RBR | IER_RLS; /* Enable UART interrupt */  

#endif  

LCR register function


3. Sending Data


[cpp] view plain copy  

/***************************************************************************** 

** Function name:       UARTSend 

** 

** Descriptions:        Send a block of data to the UART 0 port based 

**                      on the data length 

** 

** parameters:          buffer pointer, and data length 

** Returned value:      None 

**  

*****************************************************************************/  

void UARTSend(uint8_t *BufferPtr, uint32_t Length)  

{  

    

  while ( Length != 0 )  

  {  

      /* THRE status, contain valid data */  

#if !TX_INTERRUPT  

      while ( !(LPC_UART->LSR & LSR_THRE) );  

      LPC_UART->THR = *BufferPtr;  

#else  

      /* Below flag is set inside the interrupt handler when THRE occurs. */  

      while ( !(UARTTxEmpty & 0x01) );  

      LPC_UART->THR = *BufferPtr;  

      UARTTxEmpty = 0;  /* not empty in the THR until it shifts out */  

#endif  

      BufferPtr++;  

      Length--;  

  }  

  return;  

}  



4. Receiving Data


       Here we use interrupt


/***************************************************************************** 

** Function name:       UART_IRQHandler 

** 

** Descriptions:        UART interrupt handler 

** 

** parameters:          None 

** Returned value:      None 

**  

*****************************************************************************/  

void UART_IRQHandler(void)  

{  

  uint8_t IIRValue, LSRValue;  

  uint8_t Dummy = Dummy;  

  

  IIRValue = LPC_UART->IIR;  

      

  IIRValue >>= 1;         /* skip pending bit in IIR */  

  IIRValue &= 0x07;         /* check bit 1~3, interrupt identification */  

  if (IIRValue == IIR_RLS)      /* Receive Line Status */  

  {  

    LSRValue = LPC_UART->LSR;  

    /* Receive Line Status */  

    if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))  

    {  

      /* There are errors or break interrupt */  

      /* Read LSR will clear the interrupt */  

      UARTStatus = LSRValue;  

      Dummy = LPC_UART->RBR; /* Dummy read on RX to clear  

                                interrupt, then bail out */  

      return;  

    }  

    if (LSRValue & LSR_RDR) /* Receive Data Ready */              

    {  

      /* If no error on RLS, normal ready, save into the data buffer. */  

      /* Note: read RBR will clear the interrupt */  

      UARTBuffer[UARTCount++] = LPC_UART->RBR;  

      if (UARTCount >= UART0_RBUF_SIZE)  

      {  

        UARTCount = 0;      /* buffer overflow */  

      }   

    }  

  }  

  else if (IIRValue == IIR_RDA) /* Receive Data Available */  

  {  

    /* Receive Data Available */  

    UARTBuffer[UARTCount++] = LPC_UART->RBR;  

    if (UARTCount >= UART0_RBUF_SIZE)  

    {  

      UARTCount = 0;        /* buffer overflow */  

    }  

  }  

  else if (IIRValue == IIR_CTI) /* Character timeout indicator */  

  {  

    /* Character Time-out indicator */  

    UARTStatus |= 0x100;        /* Bit 9 as the CTI error */  

  }  

  else if (IIRValue == IIR_THRE)    /* THRE, transmit holding register empty */  

  {  

    /* THRE interrupt */  

    LSRValue = LPC_UART->LSR;        /* Check status in the LSR to see if 

                                valid data in U0THR or not */  

    if (LSRValue & LSR_THRE)  

    {  

      UARTTxEmpty = 1;  

    }  

    else  

    {  

      UARTTxEmpty = 0;  

    }  

  }  

  return;  

}  


Let's learn about UART interrupts.



For the UART interface, there are two situations that can trigger the UART receive interrupt: the number of received bytes reaches the trigger point (RDA) of the receive FIFO, and the receive timeout (CTI).


(1) The number of received bytes reaches the trigger point (RDA) in the receive FIFO


     The LPC1100 series Cortex-M0 microcontroller UART interface has a 16-byte receive FIFO. The receive trigger point can be set to 1, 4, 8, or 14 bytes. When the number of bytes received reaches the receive trigger point, an interrupt is triggered.


     Through the UART FIFO control register U0FCR, the receive trigger point is set to "8-byte trigger". Then when the UART receives 8 bytes, the RDA interrupt will be triggered (Note: under the premise of enabling the receive interrupt).


Let's take a look at IIR



V. Other operations


[cpp] view plain copy  

/******************************************************************************* 

* Function Name  : UART0_PutChar 

* Description    : Send a char to uart0 channel. 

* Input          : c 

* Output         : None 

* Return         : None 

*******************************************************************************/  

void UART0_PutChar(char ch)  

{  

  while(!(LPC_UART->LSR & LSR_THRE));  

  LPC_UART->THR = ch;  

}  

  

/******************************************************************************* 

* Function Name  : uart0_sendstring 

* Description    : Send string to uart0 channel. 

* Input          : pString  --  string 

* Output         : None 

* Return         : None 

*******************************************************************************/  

void UART0_PutString(char *pString)  

{  

  while(*pString)  

  {  

    UART0_PutChar(*pString++);  

  }  

}  

  

/******************************************************************************* 

* Function Name  : UART0_printf 

* Description    : print format string. 

* Input          : fmt 

* Output         : None 

* Return         : None 

*******************************************************************************/  

void UART0_printf(char *fmt, ...)  

{  

  char      uart0_pString[101];  

  va_list uart0_ap;  

  

  va_start(uart0_ap, fmt);  

  vsnprintf(uart0_pString, 100, fmt, uart0_ap);  

  UART0_PutString(uart0_pString);  

  will_end(uart0_ap);  

}  

  

/******************************************************************************* 

* Function Name  : UART0_GetChar 

* Description    : print format string. 

* Input          : fmt 

* Output         : None 

* Return         : None 

*******************************************************************************/  

uint8_t UART0_GetChar(uint8_t *ch)  

{  

  if(UART_op != UARTCount)  

  {  

    *ch = UARTBuffer[UART_op];  

    UART_on ++;  

    if(UART_op >= UART0_RBUF_SIZE)  

      UART_on = 0;  

  

    return 1;  

  }  

  

  return 0;  

}  



Keywords:CortexM0  LPC11C14  UART Reference address:CortexM0 development - How to use UART of LPC11C14

Previous article:LPC11C14 startup code analysis
Next article:GPIO Interrupts for LPC178x/7x

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号