完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
嵌入式工程师在开发产品中经常会用到MCU的片上UART和其它模块进行通信,为了在某些非正常的恶劣环境下能正常使用串口通信,可能需要对UART通信波特率进行自适应校准,在我们之前的微课堂中讲解过关于MM32通用MCU的UART串口通信方面的基础知识,这里我们增加基于灵动微电子MM32F013x 系列UART硬件自适应波特率的使用。 PART.1 原理 UART硬件波特率自适应检测首个通信字节的位宽(1bit、2bit、4bit、8bit),检测前一个边沿和后一个边沿之间的位长,即检测前一个边沿为下降沿,后一个边沿为上升沿或前一个边沿为下降沿,后一个边沿为下降沿,可通过软件灵活配置。 本实例以串口工具作为上位机,MM32F013x的UART1作为下位机,MCU端初始化为非标准波特率9200,使能空闲中断及其他状态标志位,上位机切换不同的波特率,由于上位机和MCU端的波特率不同,可能出现通信失败的情况,启动UART硬件波特率自适应功能,即检测上位机发的首个字节位宽来识别上位机的波特率,MCU端通过硬件波特率自适应切换到对应的波特率,与上位机维持后续正常的通信。 如下图所示,以首字节0XF8为例,首字节位宽为4bit的原理说明: PART.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++); } } PART.3 MM32F013x UART硬件 自适应波特率的功能演示 在main.c文件的main函数里初始化bsp_UART1_Init(9200)串口初始化函数,在while(1)大循环里调用测试UART1硬件自动波特率收发数据函数:UART1_Recv_Task();这里以检测UART1通信首字节为4bit宽为例,模式为前一个边沿为下降沿,后一个边沿为上升沿。 MCU端设置非标准波特率9200,我们通过上位机以不同的波特率发送F8进行硬件波特率自适应,自适应完成后UART1就切换到对应的波特率,MCU端收到数据后直接返回给上位机。 |
|
相关推荐
1 个讨论
|
|
只有小组成员才能发言,加入小组>>
2252个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11813 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5970 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
11110 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4592 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4325 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
1263浏览 1评论
844浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 11:05 , Processed in 0.711355 second(s), Total 62, Slave 48 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号