UART module based on BPS LKS32MC45X

Date2024-12-23

        Recently, I have been working on a portable energy storage BMS project, using the LKS32MC45x series MCU from ChipON. To meet the requirements of serial communication and low-power wake-up, I conducted some tests on the UART of the LKS32MC45x. Below is a description of the UART module driver.

The main features of the LKS32MC45x UART module are as follows:

  • Supports full-duplex and half-duplex;
  • Supports 8/9-bit data length;
  • Supports 1/2 stop bits;
  • Supports odd/even/no parity modes;
  • Includes a 1-byte transmit/receive buffer;
  • Supports LIN mode break character transmission and reception;
  • Supports multi-drop slave/master mode.

1. UART Function Configuration

        The UART configuration mainly includes GPIO initialization, UART module initialization, interrupt initialization, and DMA initialization.

1. GPIO Initialization

        Taking UART1's P2_5 (RXD) and P2_6 (TXD) as an example, the LKS32MC45x series MCU requires configuring the TXD IO as output (OUTPUT) and the RXD IO as input (INPUT).

    GPIO_StructInit(&uart1_gpio_config);

    uart1_gpio_config.GPIO_Pin    = GPIO_Pin_6;       // Pin to configure

    uart1_gpio_config.GPIO_Mode   = GPIO_Mode_OUT;    // GPIO mode: input, output, analog

    uart1_gpio_config.GPIO_PuPd   = GPIO_PuPd_NOPULL; // Pull-up/pull-down

    uart1_gpio_config.GPIO_PODEna = DISABLE;          // Open-drain enable

    uart1_gpio_config.GPIO_PFLT   = DISABLE;          // Filter enable

    GPIO_Init(GPIO2, &uart1_gpio_config);

 

    GPIO_StructInit(&uart1_gpio_config);

    uart1_gpio_config.GPIO_Pin    = GPIO_Pin_5;       // Pin to configure

    uart1_gpio_config.GPIO_Mode   = GPIO_Mode_IN;     // GPIO mode: input, output, analog

    uart1_gpio_config.GPIO_PuPd   = GPIO_PuPd_NOPULL; // Pull-up/pull-down

    uart1_gpio_config.GPIO_PODEna = DISABLE;          // Open-drain enable

    uart1_gpio_config.GPIO_PFLT   = DISABLE;          // Filter enable

    GPIO_Init(GPIO2, &uart1_gpio_config);


Next, configure the P2_5 (RXD) and P2_6 (TXD) pins to multiplex UART mode.

    GPIO_PinAFConfig(GPIO2, GPIO_PinSource_5, GPIO_AF_UART);

    GPIO_PinAFConfig(GPIO2, GPIO_PinSource_6, GPIO_AF_UART);



2. UART Module Initialization

       The UART module initialization is as follows. Among these parameters, it is essential to configure the baud rate (BAUDRATE) correctly. Other parameters can be modified according to your needs.

    uart1_config.DUPLEX       = DISABLE;   // Half-duplex mode enable

    uart1_config.MD_EN        = DISABLE;   // Multi-drop enable

    uart1_config.CK_EN        = DISABLE;   // Data verification enable

    uart1_config.CK_TYPE      = 0;         // Parity configuration: 0: Even; 1: Odd

    uart1_config.BIT_ORDER    = 0;         // Data transmission order: 0: LSB; 1: MSB

    uart1_config.STOP_LEN     = 0;         // Stop bit length: 0: 1-Bit; 1: 2-Bit

    uart1_config.BYTE_LEN     = 0;         // Data length: 0: 8-Bit; 1: 9-Bit

    uart1_config.BAUDRATE     = 9600;    // Baud rate

    uart1_config.ADR          = 0;         // Slave address for multi-device communication

    uart1_config.TX_BUF_EMPTY = DISABLE;   // Transmit buffer empty DMA request enable

    uart1_config.RX_DONE      = DISABLE;   // Receive complete DMA request enable

    uart1_config.TX_DONE      = DISABLE;   // Transmit complete DMA request enable

    uart1_config.TXD_INV      = DISABLE;   // TXD output polarity inversion

    uart1_config.RXD_INV      = DISABLE;   // RXD input polarity inversion

uart1_config.IE           = DISABLE;   // Interrupt configuration

 

    UART_Init(UART1, &uart1_config);



3. Interrupt Initialization

       If interrupt functionality is required, you must enable the corresponding IE bits in the UART initialization described earlier, such as transmit complete interrupt (UART_IRQEna_SendOver), receive complete interrupt (UART_IRQEna_RcvOver), and transmit buffer empty interrupt (UART_IRQEna_SendBuffEmpty), among others.

uart1_config.IE  = UART_IRQEna_SendOver | UART_IRQEna_RcvOver;  // Enable transmit & receive complete interrupts



Additionally, you need to enable UART interrupts and set their priority, for example:

NVIC_SetPriority(UART1_IRQn, 1);  // Set UART1 interrupt priority

NVIC_EnableIRQ(UART1_IRQn);   // Enable UART1 interrupt



4. DMA Initialization

       If DMA functionality is required, you must enable the corresponding DMA features in the UART initialization described earlier, such as TX_BUF_EMPTY, RX_DONE, and TX_DONE.

uart1_config.TX_DONE  = ENABLE;   // Enable transmit complete DMA request

2. UART Data Transmission and Reception

1. Data Transmission

Before transmitting data, you need to wait for the previous data to be sent, i.e., the transmit buffer must be empty before sending the next data.

       If the "transmit complete" interrupt is not enabled, you need to call the function UART_DelaySendOver(UART1) to wait for the transmit buffer to be empty.

UART_DelaySendOver(UART1);    // Wait for the previous data to be sent before transmitting new data

UART_SendData(UART1, num);    // Transmit data



If the "transmit complete" interrupt is enabled, you can handle it in the interrupt handler UART1_IRQHandler.

void UART1_IRQHandler(void)

{

    if (UART_GetIRQFlag(UART1, UART_IF_SendOver))

    {

        UART_SendData(UART1, num); // Transmit data

        UART_ClearIRQFlag(UART1, UART_IF_SendOver);

    }

}



If using DMA for transmission, you only need to specify the length of the data to be transmitted and the source address, then enable DMA.

void uart1_dma_senddata(u8 *t, u16 len)

{

    DMA_InitTypeDef uart1_dma_config;

    uart1_dma_config.DMA_Channel_EN = ENABLE;           /* Enable DMA channel */

    uart1_dma_config.DMA_IRQ_EN     = DISABLE;          /* Disable DMA interrupt */

    uart1_dma_config.DMA_RMODE      = ENABLE;           /* Enable multi-round transfer */

    uart1_dma_config.DMA_CIRC       = DISABLE;          /* Disable circular mode */

    uart1_dma_config.DMA_SINC       = ENABLE;           /* Enable source address increment */

    uart1_dma_config.DMA_DINC       = DISABLE;          /* Disable destination address increment */

    uart1_dma_config.DMA_SBTW       = 0;                /* Source address access width: 0: byte, 1: half-word, 2: word */

    uart1_dma_config.DMA_DBTW       = 0;                /* Destination address access width: 0: byte, 1: half-word, 2: word */

    uart1_dma_config.DMA_REQ_EN     = DMA_REQ_UART1_TX; /* Enable hardware DMA request for channel x */

    uart1_dma_config.DMA_TIMES      = len;              /* Number of data transfers for DMA channel x */

    uart1_dma_config.DMA_SADR       = (u32)t;           /* Source address for DMA channel x */

    uart1_dma_config.DMA_DADR       = 0;               /* Destination address for DMA channel x */

 

    DMA_Init(DMA_CH0, &uart1_dma_config);

    DMA_CH0->REN |= DMA_REQ_SW;

}



2. Data Reception

       Before receiving data, you need to wait for the reception to complete before reading the data. If the "receive complete" interrupt is enabled, you can handle it in the interrupt handler UART1_IRQHandler.

void UART1_IRQHandler(void)

{

    if (UART_GetIRQFlag(UART1, UART_IF_RcvOver))

    {

        uart_buffer[uart_buffer_p] = UART_ReadData(UART1);

        uart_buffer_p++;

        UART_ClearIRQFlag(UART1, UART_IF_RcvOver);

    }

}



If using DMA for reception, you only need to specify the length of the data to be received and the target address, then enable DMA.

       Note: Each DMA channel generally enables only one hardware DMA request at a time. Therefore, if both transmission and reception use DMA simultaneously, two DMA channels need to be configured.

DMA_InitTypeDef uart1_dma_config;

uart1_dma_config.DMA_Channel_EN = ENABLE;           /* Enable DMA channel */

uart1_dma_config.DMA_IRQ_EN     = DISABLE;          /* Disable DMA interrupt */

uart1_dma_config.DMA_RMODE      = ENABLE;           /* Enable multi-round transfer */

uart1_dma_config.DMA_CIRC       = DISABLE;          /* Disable circular mode */

uart1_dma_config.DMA_SINC       = ENABLE;           /* Enable source address increment */

uart1_dma_config.DMA_DINC       = DISABLE;          /* Disable destination address increment */

uart1_dma_config.DMA_SBTW       = 0;                /* Source address access width: 0: byte, 1: half-word, 2: word */

uart1_dma_config.DMA_DBTW       = 0;                /* Destination address access width: 0: byte, 1: half-word, 2: word */

uart1_dma_config.DMA_REQ_EN     = DMA_REQ_UART1_RX; /* Enable hardware DMA request for channel x */

uart1_dma_config.DMA_TIMES      = len;              /* Number of data transfers for DMA channel x */

uart1_dma_config.DMA_SADR       = 0;                /* Source address for DMA channel x */

uart1_dma_config.DMA_DADR       = (u32)&UART1_BUFF; /* Destination address for DMA channel x */

 

DMA_Init(DMA_CH1, &uart1_dma_config);

 

3. Summary

       The above is a description of the software driver for the UART module of the LKS32MC45x from ChipON. If you want to learn more, feel free to leave a comment below or email us at: atu.sh@wpi-group.com.

4. References

LKS32M45x User Manual: LKS32MC45x_UM_v1.52.pdf.
LKS32M45x Peripheral Example Project: lks32mc45x_demo_prj_v2.9.


Feel free to leave a comment below, and we will respond promptly.

For further inquiries, contact the ATU department of WPI Group: atu.sh@wpi-group.com   
Author: Miss May

For more information, scan the QR code below to follow us!


★All content is provided by individuals and is unrelated to the platform. For any legal or infringement issues, please contact the Tech Highlights Exclusive Email