0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于灵动微电子MM32F013x 系列的UART硬件自适应波特率

电子设计 来源:灵动MM32MCU 作者:灵动MM32MCU 2021-02-15 09:09 次阅读

嵌入式工程师在开发产品中经常会用到MCU的片上UART和其它模块进行通信,为了在某些非正常的恶劣环境下能正常使用串口通信,可能需要对UART通信波特率进行自适应校准,在我们之前的微课堂中讲解过关于MM32通用MCU的UART串口通信方面的基础知识,这里我们增加基于灵动微电子MM32F013x 系列UART硬件自适应波特率的使用。

1、原理

UART硬件波特率自适应检测首个通信字节的位宽(1bit、2bit、4bit、8bit),检测前一个边沿和后一个边沿之间的位长,即检测前一个边沿为下降沿,后一个边沿为上升沿或前一个边沿为下降沿,后一个边沿为下降沿,可通过软件灵活配置。

本实例以串口工具作为上位机,MM32F013x的UART1作为下位机,MCU端初始化为非标准波特率9200,使能空闲中断及其他状态标志位,上位机切换不同的波特率,由于上位机和MCU端的波特率不同,可能出现通信失败的情况,启动UART硬件波特率自适应功能,即检测上位机发的首个字节位宽来识别上位机的波特率,MCU端通过硬件波特率自适应切换到对应的波特率,与上位机维持后续正常的通信。

如下图所示,以首字节0XF8为例,首字节位宽为4bit的原理说明:

o4YBAF_8C3aAf1jtAADJl_q1Dqc572.png

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端收到数据后直接返回给上位机。

o4YBAF_8C4mAVXorAAHgpS9Jm6M455.png

编辑:hfy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    17040

    浏览量

    350511
  • uart
    +关注

    关注

    22

    文章

    1230

    浏览量

    101223
  • 串口通信
    +关注

    关注

    34

    文章

    1620

    浏览量

    55451
收藏 人收藏

    评论

    相关推荐

    波特率与串行通信的关系 各种设备波特率转换的方法

    波特率(Baud Rate)是串行通信中的一个重要参数,它指的是信号传输的速率,即单位时间内传输的符号(或信号状态)的数量。在串行通信中,波特率决定了数据传输的速度,因此对于通信效率和设备兼容性
    的头像 发表于 11-22 10:01 156次阅读

    常见的波特率标准和协议

    波特率是指在数据通信中,每秒钟传输的符号数(或比特数),是衡量数据通信速度的重要指标。在不同的通信协议和场景中,常见的波特率标准和协议有所不同。以下是一些常见的波特率标准和协议: 一、串口通信
    的头像 发表于 11-22 09:56 396次阅读

    Wi-Fi与蓝牙的波特率对比分析

    技术)是一种允许电子设备连接到一个无线局域网(WLAN)的技术。 其数据传输速率远高于蓝牙,适用于需要高速数据传输的场景。 发展历程与波特率提升 : 随着技术的发展,Wi-Fi的波特率不断提升。 例如,从最初的IEEE 802.
    的头像 发表于 11-22 09:54 135次阅读

    波特率的定义和计算方法 波特率与数据传输速度的关系

    波特率的定义 波特率(Baud Rate),又称调制速率或传符号,是指每秒传输的符号数目,单位为波特(Bd)。它是一个数字信号通信中重要的参数,在串行通信协议中经常被用作衡量串行数据
    的头像 发表于 11-22 09:49 298次阅读

    波特率9600和115200的区别

    在现代通信技术中,数据传输速率是一个关键的性能指标。对于串行通信,波特率是衡量数据传输速度的基本单位。波特率9600和115200是两种常见的设置,它们在不同的应用场景中有着各自的优势和局
    的头像 发表于 10-18 14:56 1031次阅读

    波特率与比特有何关系 波特率与数据传输速率的关系

    波特率(Baud Rate)和比特(Bit Rate)是衡量数据通信系统性能的两个重要参数,它们之间有着密切的关系,但并不完全相同。 波特率(Baud Rate): 波特率是指在数据
    的头像 发表于 10-18 14:55 537次阅读

    uart波特率和传输频率的关系 UART串口的常用波特率为多少

    频率是两个关键参数,它们之间存在一定的关系,并且UART串口有一系列常用的波特率。以下是对这两个概念的介绍。 一、UART波特率和传输频率的
    的头像 发表于 10-06 16:12 1950次阅读
    <b class='flag-5'>uart</b><b class='flag-5'>波特率</b>和传输频率的关系 <b class='flag-5'>UART</b>串口的常用<b class='flag-5'>波特率</b>为多少

    如何更改波特率

    尝试以下命令之一时,我总是收到一个错误: 在 UART=9600,8,1,0,0 在 uart_cur=9600,8,1,0,0 在 uart_def=9600,8,1,0,0 这个波特率
    发表于 07-16 06:10

    如何获得115200波特率的串行输出?

    uart_init_new() 波特率为 115200 这是行不通的。它仅适用于 74880。您能否告诉我如何获得 115200 波特率的串行输出?
    发表于 07-10 08:08

    RA UART实现串口波特率自适应

    Falling & Rising Edge trigger),然后等上位机发送波特率标识数据(LSB=1),这样IRQ4分别两次触发GPT(Start->Stop)就能够捕捉start bit的间隔时间,从而计算出上位机发送数据的波特率. 然后将IRQ4管脚切换到RXD
    发表于 06-07 15:25 1667次阅读
    RA <b class='flag-5'>UART</b>实现串口<b class='flag-5'>波特率</b><b class='flag-5'>自适应</b>

    如何使用示波器测量串口波特率

    在通信和电子测量领域,串口波特率是一个至关重要的参数,它决定了数据在串行通信线上的传输速率。使用示波器来测量串口波特率是一种常见且有效的方法,尤其是在没有专业串口调试工具或需要更精确测量时。本文将
    的头像 发表于 05-27 16:25 4596次阅读

    波特率有什么危害尼?又该如何避免?

    深入探讨了波特率过高可能带来的危害,并提供了一些实用建议来保护设备不受影响。在通信领域,波特率是决定数据传输速度的重要参数。然而,波特率设置不当可能会对设备造成严重的影响。本文旨在揭示波特率
    的头像 发表于 04-03 16:45 1298次阅读

    为啥要转换波特率 波特率和传输速率的关系

    对于串行多主 CAN 总线,如果波特率被称为“500000波特”,则 CAN 上的该端口每秒最多可传输500000位。
    的头像 发表于 03-06 17:38 4731次阅读
    为啥要转换<b class='flag-5'>波特率</b> <b class='flag-5'>波特率</b>和传输速率的关系

    波特率发生器使用哪个定时器 波特率发生器的时钟来源是什么

    波特率发生器是一种用于控制串行数据通信速率的设备,它可以生成特定波特率的时钟信号。在嵌入式系统、通信设备和计算机硬件中,波特率发生器的使用十分常见。
    的头像 发表于 01-24 09:56 1977次阅读

    什么是串口波特率?串口通信为什么要设置波特率

    什么是串口波特率?串口通信为什么要设置波特率波特率与比特的关系 如何选择串口波特率?  串口波特率
    的头像 发表于 01-22 16:10 2031次阅读