zoukankan      html  css  js  c++  java
  • 电平波特率UART自适应波特率的设置方法

    最近使用开发的过程中出现了一个小问题,顺便记录一下原因和方法--电平波特率

        在单片机中,UART是经常使用的通信方法。最近在做Profibus DP的产品,由于Profibus DP有波特率自适应的特性,故研讨了一下UART的波特率自适应方法。当初介绍一种自适应波特率的设置方法。

        

    条件

        闲暇的外部定时器1个

        

    方法

        通过定时器,连续检测UART输入引脚RXD上的电平变更,以达到波特率自适应。 

        

    STM32来举例

        假设要自适应的UART为STM32的USART1,其RXD引脚为GPIOA.10。同时也假定定时器3闲暇。

        

    代码 

        每日一道理
    翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹。多年前的好友似乎当初看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切感,只是偶尔遇上,淡淡地微笑,如今也只能在这发黄的页张中找寻过去的那些让人难忘的,至少我可以握住这仅剩下一段的“丝线头”……
    u32 USART1_Baud(void)                                                                        
    {
            u16 t1=0,t2,t=0;               // 定时器寄存器为16位
            u32 b1,b2;
            u32 i;
             
            GPIO_Init(GPIOA, 10, GPIO_IN_FLOAT);         // GPIOA.10浮空输入
            TIM_Open(Tim3);                // 开TIM3的时钟
            TIM_Enable(TIM3);              // 开启TIM3
            b1 = GPIO_Pin_Get(GPIOA,10);            // 读GPIOA.10的电平
            for(i=0;i<32;)                                    // 连续检测GPIO.10引脚32次电平变更
            {
                    b2 = GPIO_Pin_Get(GPIOA,10);    // 读GPIOA.10的新值
                    if(b2 != b1)                               // 如果有电平变更
                    {
                            t2 = TIM3->COUNT;         // 读定时器中的值
                            b1 = b2;                          // 更新为新的引脚值
                            if((t1 == 0)&&(t==0))        // 第一个电平变更
                            {
                                    t1 = t2;                     // 记录第一个时刻点
                            }
                            else                                  // 不是第一个电平变更
                            {
                                    if(t == 0)                   // 第一段电平
                                    {
                                            t = t2-t1;           // 记录第一段电平所用时间
                                    }
                                    else                          // 不是第一段电平
                                    {
                                            if((t2-t1)< t)       // 保存电平段的最小值 
                                            {
                                                    t = t2-t1;
                                            }
                                    }
                                    t1 = t2;                      // 更新为新的时刻点
                            }
                            i++;                                  // 电平变更数+1
                    }
            }
             
            TIM_Close(Tim3);                               // 关闭TIM3的时钟
            return ((u32)t*403/400);  
     // 修正波特率值(加上电平变更的斜率,大概为0.75%,经验值)
    }

        上述函数的返回值,直接填入USART1的波特率寄存即可(如果APB2的时钟与定时器时钟雷同的话)。

        上述盘算检测出来的波特率值,与实际波特有一点点差异,但不影响正常通信。

        介入测试的波特率有1200、2400、4800、9600、14400、19200、28800、38400、56000、57600、115200、128000、250000、500000bps.

        

        还有一点要说明的是:我没有使用ST的库,下面的函数,是我自己用的。但注释已经很好的说明了如何进行自适应波特率的设置,不依赖于发送方的发送数据。当然,数据帧的后面部份,肯定有多个字节是收不到的(被检测用掉了)。

    文章结束给大家分享下程序员的一些笑话语录: 看到有人回帖“不顶不是中国人”,他的本意是想让帖子沉了。

  • 相关阅读:
    Ubuntu 配置IP地址方法
    ubuntu server 16.04安装GPU服务器
    Ubuntu 自动获取ip地址
    Typedef 用法
    linux mount命令详解(iso文件挂载)
    specrate 与specspeed 的区别
    SPEC CPU 使用简介
    编译错误you should not run configure as root (set FORCE_UNSAFE_CONFIGURE=1 in environment to bypass this check)
    SPEC CPU 2006编译perl 出错:undefined reference to `pow'
    'gets' undeclared here (not in a function)
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3087536.html
Copyright © 2011-2022 走看看