最近在做一個便攜式儲能的 BMS 項目,使用的主控晶片是晶豐明源的 LKS32MC45x 系列 MCU。應串口通信和低功耗喚醒的需求,在 LKS32MC45x 的 UART 上做了一些測試,以下是關於 UART 模塊的驅動說明。
先說明 LKS32MC45x 的 UART 模塊主要特徵如下:
- 支持全雙工、半雙工;
- 支持 8/9 bit 數據位
- 支持 1/2 bit 停止位
- 支持奇/偶/無校驗模式
- 帶 1 Byte 發送/接收緩存
- 支持 LIN 模式 break character 收發
- 支持一主多從的 Multi-drop Slave/Master 模式
一、UART 功能配置
UART 的配置主要有:GPIO 的初始化配置、UART 模塊的初始化配置、中斷的初始化配置、DMA 的初始化配置。
1、GPIO 的初始化配置
以 UART1 的 P2_5(RXD)和 P2_6(TXD)為例,LKS32MC45x 系列 MCU 要求將 TXD 的 IO 配置為輸出(OUTPUT),將 RXD 的 IO 配置為輸入(INPUT)。
GPIO_StructInit(&uart1_gpio_config); uart1_gpio_config.GPIO_Pin = GPIO_Pin_6; // 要配置的PIN uart1_gpio_config.GPIO_Mode = GPIO_Mode_OUT; // GPIO模式:輸入、輸出、模擬 uart1_gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL; // 上拉/下拉 uart1_gpio_config.GPIO_PODEna = DISABLE; // 開漏使能 uart1_gpio_config.GPIO_PFLT = DISABLE; // 濾波使能 GPIO_Init(GPIO2, &uart1_gpio_config);
GPIO_StructInit(&uart1_gpio_config); uart1_gpio_config.GPIO_Pin = GPIO_Pin_5; // 要配置的PIN uart1_gpio_config.GPIO_Mode = GPIO_Mode_IN; // GPIO模式:輸入、輸出、模擬 uart1_gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL; // 上拉/下拉 uart1_gpio_config.GPIO_PODEna = DISABLE; // 開漏使能 uart1_gpio_config.GPIO_PFLT = DISABLE; // 濾波使能 GPIO_Init(GPIO2, &uart1_gpio_config); |
接著要把 P2_5(RXD)和 P2_6(TXD)兩個管腳配置成復用 UART 模式。
GPIO_PinAFConfig(GPIO2, GPIO_PinSource_5, GPIO_AF_UART); GPIO_PinAFConfig(GPIO2, GPIO_PinSource_6, GPIO_AF_UART); |
2、UART 模塊的初始化配置
UART 模塊的初始化配置如下,這些參數中首先要注意將波特率(BAUDRATE)配置成正確的值。其它參數配置可根據自己的需求來修改。
uart1_config.DUPLEX = DISABLE; // 半雙工模式使能,tx_data uart1_config.MD_EN = DISABLE; // Multi-drop 使能 uart1_config.CK_EN = DISABLE; // 數據校驗使能 uart1_config.CK_TYPE = 0; // 奇偶校驗配置 0: 偶校驗(EVEN); 1: 奇校驗(ODD) uart1_config.BIT_ORDER = 0; // 數據發送順序配置 0: LSB; 1: MSB uart1_config.STOP_LEN = 0; // 停止位長度配置 0: 1-Bit; 1: 2-Bit uart1_config.BYTE_LEN = 0; // 數據長度配置 0: 8-Bit; 1: 9-Bit uart1_config.BAUDRATE = 9600; // 波特率 uart1_config.ADR = 0; // 多機通訊時的從機地址 uart1_config.TX_BUF_EMPTY = DISABLE; // 發送緩衝區空 DMA 請求使能 uart1_config.RX_DONE = DISABLE; // 接收完成 DMA 請求使能 uart1_config.TX_DONE = DISABLE; // 發送完成 DMA 請求使能 uart1_config.TXD_INV = DISABLE; // TXD 輸出極性取反 uart1_config.RXD_INV = DISABLE; // RXD 輸入極性取反 uart1_config.IE = DISABLE; // 中斷配置
UART_Init(UART1, &uart1_config); |
3、中斷的初始化配置
如果需要用到中斷功能,首先要在前面描述的 UART 初始化中,使能 IE 的相應位,比如:發送完成中斷(UART_IRQEna_SendOver)、接收完成中斷(UART_IRQEna_RcvOver)、發送緩衝區空中斷(UART_IRQEna_SendBuffEmpty),等等。
uart1_config.IE = UART_IRQEna_SendOver | UART_IRQEna_RcvOver; // 使能發送&接收完成中斷 |
另外,還需要開啟 UART 中斷,並設置其中斷優先級,比如:
NVIC_SetPriority(UART1_IRQn, 1); // 設置 UART1 中斷優先級 NVIC_EnableIRQ(UART1_IRQn); // 使能 UART1 中斷 |
4、DMA 的初始化配置
如果需要用到 DMA 功能,首先要在前面描述的 UART 初始化中,使能相應的 DMA 功能,比如:TX_BUF_EMPTY、RX_DONE、TX_DONE。
uart1_config.TX_DONE = ENABLE; // 發送完成 DMA 請求使能 |
二、UART 數據發送和接收
1、數據發送
在發送數據之前,需要等待上一個數據已發送完成,即發送緩衝區空才能發送下一個數據。
在沒有開啟“發送完成”中斷時,需要調用函數 UART_DelaySendOver(UART1) 等待發送緩衝區空。
UART_DelaySendOver(UART1); // 發送數據前需要等待之前的數據發送完成 UART_SendData(UART1, num); // 發送數據 |
如果開啟“發送完成”中斷,可以在中斷處理函數 UART1_IRQHandler 中處理。
void UART1_IRQHandler(void) { if (UART_GetIRQFlag(UART1, UART_IF_SendOver)) { UART_SendData(UART1, num); // 發送數據 UART_ClearIRQFlag(UART1, UART_IF_SendOver); } } |
如果使用 DMA 發送,則只需要指定發送數據的長度和數據的源地址,然後使能 DMA。
void uart1_dma_senddata(u8 *t, u16 len) { DMA_InitTypeDef uart1_dma_config; uart1_dma_config.DMA_Channel_EN = ENABLE; /* DMA 通道使能*/ uart1_dma_config.DMA_IRQ_EN = DISABLE; /* DMA 中斷使能 */ uart1_dma_config.DMA_RMODE = ENABLE; /* 多輪傳輸使能 */ uart1_dma_config.DMA_CIRC = DISABLE; /* 循環模式使能 */ uart1_dma_config.DMA_SINC = ENABLE; /* 源地址遞增使能 */ uart1_dma_config.DMA_DINC = DISABLE; /* 目的地址遞增使能 */ uart1_dma_config.DMA_SBTW = 0; /* 源地址訪問位寬, 0:byte, 1:half-word, 2:word */ uart1_dma_config.DMA_DBTW = 0; /* 目的地址訪問位寬, 0:byte, 1:half-word, 2:word */ uart1_dma_config.DMA_REQ_EN = DMA_REQ_UART1_TX; /* 通道 x 硬體 DMA 請求使能,高有效 */ uart1_dma_config.DMA_TIMES = len; /* DMA 通道 x 數據搬運次數 */ uart1_dma_config.DMA_SADR = (u32)t; /* DMA 通道 x 源地址 */ uart1_dma_config.DMA_DADR = 0; /* DMA 通道 x 目的地址 */
DMA_Init(DMA_CH0, &uart1_dma_config); DMA_CH0->REN |= DMA_REQ_SW; } |
2、數據接收
在接收數據之前,需要等待接收完成,才能讀取數據。如果開啟“接收完成”中斷,可以在中斷處理函數 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); } } |
如果使用 DMA 接收,則只需要指定接收數據的長度和目標地址,然後使能 DMA。
這裡要注意的是:每一個 DMA 通道一般在同一時間通常只使能一個硬體 DMA 請求,所以如果發送和接收同時使用 DMA 的時候,就需要設置 2 個 DMA 通道。
DMA_InitTypeDef uart1_dma_config; uart1_dma_config.DMA_Channel_EN = ENABLE; /* DMA 通道使能*/ uart1_dma_config.DMA_IRQ_EN = DISABLE; /* DMA 中斷使能 */ uart1_dma_config.DMA_RMODE = ENABLE; /* 多輪傳輸使能 */ uart1_dma_config.DMA_CIRC = DISABLE; /* 循環模式使能 */ uart1_dma_config.DMA_SINC = ENABLE; /* 源地址遞增使能 */ uart1_dma_config.DMA_DINC = DISABLE; /* 目的地址遞增使能 */ uart1_dma_config.DMA_SBTW = 0; /* 源地址訪問位寬, 0:byte, 1:half-word, 2:word */ uart1_dma_config.DMA_DBTW = 0; /* 目的地址訪問位寬, 0:byte, 1:half-word, 2:word */ uart1_dma_config.DMA_REQ_EN = DMA_REQ_UART1_RX; /* 通道 x 硬體 DMA 請求使能,高有效 */ uart1_dma_config.DMA_TIMES = len; /* DMA 通道 x 數據搬運次數 */ uart1_dma_config.DMA_SADR = 0; /* DMA 通道 x 源地址 */ uart1_dma_config.DMA_DADR = (u32)&UART1_BUFF; /* DMA 通道 x 目的地址 */
DMA_Init(DMA_CH1, &uart1_dma_config); |
三、總結
以上是關於晶豐明源的 LKS32MC45x 的 UART 模塊軟體驅動的說明。如果想了解更多,可以在下方評論區留言,或者發郵件給我們:atu.sh@wpi-group.com。
四、參考資料
LKS32M45x 外設示例工程:lks32mc45x_demo_prj_v2.9。
如有更多需求,歡迎聯繫大聯大世平集團 ATU 部門:atu.sh@wpi-group.com 作者:五月小姐姐
更多資訊,請掃碼關注我們!
評論