嵌入式工程師在開發產品中經常會用到MCU的片上UART和其它模塊進行通信,為了在某些非正常的惡劣環境下能正常使用串口通信,可能需要對UART通信波特率進行自適應校準,在我們之前的微課堂中講解過關于MM32通用MCU的UART串口通信方面的基礎知識,這里我們增加基于靈動微電子MM32F013x 系列UART硬件自適應波特率的使用。
1、原理
UART硬件波特率自適應檢測首個通信字節的位寬(1bit、2bit、4bit、8bit),檢測前一個邊沿和后一個邊沿之間的位長,即檢測前一個邊沿為下降沿,后一個邊沿為上升沿或前一個邊沿為下降沿,后一個邊沿為下降沿,可通過軟件靈活配置。
本實例以串口工具作為上位機,MM32F013x的UART1作為下位機,MCU端初始化為非標準波特率9200,使能空閑中斷及其他狀態標志位,上位機切換不同的波特率,由于上位機和MCU端的波特率不同,可能出現通信失敗的情況,啟動UART硬件波特率自適應功能,即檢測上位機發的首個字節位寬來識別上位機的波特率,MCU端通過硬件波特率自適應切換到對應的波特率,與上位機維持后續正常的通信。
如下圖所示,以首字節0XF8為例,首字節位寬為4bit的原理說明:
2、程序配置
2.1 初始化MM32F013x UART1串口
從官網下載MM32F013x例程,這里我們在MM32F0133C7P的樣例程序中添加注釋并對代碼修改。
#include "bsp_UART.h" #include "led.h" /******************************************************************************* * 函數名稱:void bsp_UART1_Init(u32 baudrate) * 函數功能:初始化UART1 PA9/PA10分別作為UART1的TX/RX * 輸入參數:無 * 返回數值:無 ******************************************************************************/ void bsp_UART1_Init(u32 baudrate) { //GPIO初始化結構體 GPIO_InitTypeDef GPIO_InitStructure; //UART初始化結構體 UART_InitTypeDef UART_InitStructure; //NVIC初始化結構體 NVIC_InitTypeDef NVIC_InitStructure; //使能UART1時鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE); //使能GPIOA時鐘 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //開啟GPIOA PA9復用于UART1_TX功能 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1); //開啟GPIOA PA10復用于UART1_RX功能 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); //UART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //配置GPIOA.9 速度為高速50MHz GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //配置GPIOA.9為復用推挽輸出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //根據GPIO結構體初始化UART1_TX GPIOA.9 GPIO_Init(GPIOA, &GPIO_InitStructure); //UART1_RX GPIOA.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置UART1_RX GPIOA.10為上拉輸入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //根據GPIO結構體初始化UART1_RX GPIOA.10 GPIO_Init(GPIOA, &GPIO_InitStructure); //串口波特率 UART_InitStructure.UART_BaudRate = baudrate; //字長為8位數據格式 UART_InitStructure.UART_WordLength = UART_WordLength_8b; //一位停止位 UART_InitStructure.UART_StopBits = UART_StopBits_1; //無奇偶校驗位 UART_InitStructure.UART_Parity = UART_Parity_No; //無硬件數據流控 UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None; //允許收發模式 UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; //根據UART結構體初始化串口UART1 UART_Init(UART1, &UART_InitStructure); //硬件自動波特率檢測第1個字節位的位寬前一個邊沿為下降沿,后一個邊沿為上升沿 //___ _______ // |_ _ _ _|1 x x x x| = Binary:xxxx 1000 Fall to Rise -> 1 start bit //AutoBaudRate Mode Fall to Rise 4bit width,the first byte is 0xF8 use test UART_AutoBaudRateSet(UART1, ABRMODE_FALLING_TO_RISINGEDGE4BIT, ENABLE); //接收數據中斷、接收幀錯誤中斷、自動波特率結束中斷、自動波特率錯誤中斷、空閑中斷 UART_ITConfig(UART1, UART_IT_RXIEN | UART_ICR_RXFERRCLR | UART_ICR_ABRENDCLR |\ UART_ICR_ABRERRCLR | UART_ICR_RXIDLE | UART_IT_ERR, ENABLE); //使能UART1 UART_Cmd(UART1, ENABLE); //UART1 NVIC中斷優先級設置 NVIC_InitStructure.NVIC_IRQChannel = UART1_IRQn; //UART通道優先級0 NVIC_InitStructure.NVIC_IRQChannelPriority = 0; //IRQ通道使能 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //根據指定的參數初始化NVIC寄存器 NVIC_Init(&NVIC_InitStructure); }
2.2 編寫MM32F013x UART1串口中斷服務函數
繼續在bsp_UART.c文件中編寫MM32F013x UART1串口中斷服務函數如下所示。
/******************************************************************************* * 函數名稱:void UART1_IRQHandler(void) * 函數功能:串口1 UART1中斷服務程序 * 輸入參數:無 * 返回數值:無 *******************************************************************************/ //自動波特率幀錯誤標志 u8 Auto_BaudRate_FraErr_Flag = 0; void UART1_IRQHandler(void) { u8 Res; //UART1接收中斷 if(UART_GetITStatus(UART1, UART_IT_RXIEN) != RESET) { //清UART1接收中斷標志 UART_ClearITPendingBit(UART1,UART_IT_RXIEN); //讀取UART1接收到的數據 Res = UART_ReceiveData(UART1); //UART1接收數據緩存起來,最大接收UART1_REC_LEN個字節 UART1_Rx_Buf[UART1_Rx_Cnt] = Res; //UART1作接收緩存溢出判斷,最大接收UART1_REC_LEN個字節 if(UART1_Rx_Cnt < UART1_REC_LEN-1) { //還有數據要接收,接收計數變量自加 UART1_Rx_Cnt++; } else { UART1_Rx_Cnt = 0; } } //幀錯誤中斷標志位 if(UART_GetITStatus(UART1, UART_IER_RXFERR) != RESET) { //自動波特率幀錯誤標志置1 Auto_BaudRate_FraErr_Flag = 1; //清幀錯誤中斷標志位 UART_ClearITPendingBit(UART1,UART_IER_RXFERR); } //接收數據幀錯誤中斷 if(UART_GetITStatus(UART1, UART_ICR_RXFERRCLR) != RESET) { UART_ClearITPendingBit(UART1,UART_ICR_RXFERRCLR); } //空閑中斷硬件波特率自校準 if(UART_GetITStatus(UART1, UART_ICR_RXIDLE) != RESET) { UART_ClearITPendingBit(UART1,UART_ICR_RXIDLE); //自動波特率幀錯誤標志 if(Auto_BaudRate_FraErr_Flag == 1) { Auto_BaudRate_FraErr_Flag = 0; //----------------Check MM32F013x UART_AutoBaudRateHard---------- //___ _______ // |_ _ _ _|1 x x x x| = Binary:xxxx 1000 Fall to Rise -> 1 start bit //AutoBaudRate Mode Fall to Rise 4bit width,the first byte is 0xF8 use test UART_AutoBaudRateSet(UART1, ABRMODE_FALLING_TO_RISINGEDGE4BIT, ENABLE); } } //自動波特率錯誤中斷清除位 if(UART_GetITStatus(UART1, UART_ICR_ABRERRCLR) != RESET) { UART_ClearITPendingBit(UART1,UART_ICR_ABRERRCLR); } //自動波特率結束中斷清除位 if(UART_GetITStatus(UART1, UART_ICR_ABRENDCLR) != RESET) { UART_ClearITPendingBit(UART1,UART_ICR_ABRENDCLR); } }
2.3 MM32F013x UART1串口接收函數
在bsp_UART.h文件中宏定義UART1波特率、接收字節長度,變量聲明以及UART1接收數據函數和發送數據函數聲明。
void UART1_Recv_Task(void) { //收到的數據原樣返回到串口上位機 UART_SendBytes(UART1,UART1_Rx_Buf, UART1_Rx_Cnt); }
2.4 MM32F013x UART串口發送函數
在bsp_UART.c文件中編寫MM32F013x UART1發送數據函數,發送單字節數據和發送多字節數據函數分別如下所示:
/******************************************************************************* * 函數名稱:void UART_SendByte(UART_TypeDef* UARTx,u8 dat) * 函數功能:UART發送單字節數據 * 輸入參數:UARTx:UART1/UART2;dat:待發送的數據 * 返回數值:無 *******************************************************************************/ void UART_SendByte(UART_TypeDef* UARTx,u8 dat) { UART_SendData(UARTx, dat); while(!UART_GetFlagStatus(UARTx, UART_FLAG_TXEPT)); } /******************************************************************************* * 函數名稱:void UART_SendBytes(UART_TypeDef* UARTx,u8* buf, u16 len) * 函數功能:UART發送多字節數據 * 輸入參數:UARTx:UART1/UART2;buf:待發送的數據;len:待發送數據的長度 * 返回數值:無 *******************************************************************************/ void UART_SendBytes(UART_TypeDef* UARTx,u8* buf, u16 len) { while(len--) { UART_SendByte(UARTx,*buf++); } }
3、MM32F013x UART硬件 自適應波特率的功能演示
在main.c文件的main函數里初始化bsp_UART1_Init(9200)串口初始化函數,在while(1)大循環里調用測試UART1硬件自動波特率收發數據函數:UART1_Recv_Task();這里以檢測UART1通信首字節為4bit寬為例,模式為前一個邊沿為下降沿,后一個邊沿為上升沿。
MCU端設置非標準波特率9200,我們通過上位機以不同的波特率發送F8進行硬件波特率自適應,自適應完成后UART1就切換到對應的波特率,MCU端收到數據后直接返回給上位機。
編輯:hfy
-
mcu
+關注
關注
146文章
17942瀏覽量
363435 -
uart
+關注
關注
22文章
1275瀏覽量
103713 -
串口通信
+關注
關注
34文章
1638瀏覽量
56736
發布評論請先 登錄
靈動微電子MM32F5370 MCU產品特色

請問MSC1210串口UART1如何設置波特率?
RS232通信的波特率設置說明
波特率與串行通信的關系 各種設備波特率轉換的方法
常見的波特率標準和協議
Wi-Fi與藍牙的波特率對比分析
波特率的定義和計算方法 波特率與數據傳輸速度的關系
波特率9600和115200的區別
波特率與比特率有何關系 波特率與數據傳輸速率的關系
uart波特率和傳輸頻率的關系 UART串口的常用波特率為多少

評論