波特率的设置方法

时间:2021-10-23 23:31:21
在单片机中,UART是常用的通信方式。最近在做Profibus DP的产品,由于Profibus DP有波特率自适应的特性,故研究了一下UART的波特率自适应方法。现在介绍一种自适应波特率的设置方法。

条件

空闲的内部定时器1个

方法

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

STM32来举例

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

代码 

[cpp] view plain copy
  1. u32 USART1_Baud(void)                                                                          
  2. {  
  3.         u16 t1=0,t2,t=0;               // 定时器寄存器为16位  
  4.         u32 b1,b2;  
  5.         u32 i;  
  6.            
  7.         GPIO_Init(GPIOA, 10, GPIO_IN_FLOAT);         // GPIOA.10浮空输入  
  8.         TIM_Open(Tim3);                // 开TIM3的时钟  
  9.         TIM_Enable(TIM3);              // 开启TIM3  
  10.         b1 = GPIO_Pin_Get(GPIOA,10);            // 读GPIOA.10的电平  
  11.         for(i=0;i<32;)                                    // 连续检测GPIO.10引脚32次电平变化  
  12.         {  
  13.                 b2 = GPIO_Pin_Get(GPIOA,10);    // 读GPIOA.10的新值  
  14.                 if(b2 != b1)                               // 如果有电平变化  
  15.                 {  
  16.                         t2 = TIM3->COUNT;         // 读定时器中的值  
  17.                         b1 = b2;                          // 更新为新的引脚值  
  18.                         if((t1 == 0)&&(t==0))        // 第一个电平变化  
  19.                         {  
  20.                                 t1 = t2;                     // 记录第一个时刻点  
  21.                         }  
  22.                         else                                  // 不是第一个电平变化  
  23.                         {  
  24.                                 if(t == 0)                   // 第一段电平  
  25.                                 {  
  26.                                         t = t2-t1;           // 记录第一段电平所用时间  
  27.                                 }  
  28.                                 else                          // 不是第一段电平  
  29.                                 {  
  30.                                         if((t2-t1)< t)       // 保留电平段的最小值   
  31.                                         {  
  32.                                                 t = t2-t1;  
  33.                                         }  
  34.                                 }  
  35.                                 t1 = t2;                      // 更新为新的时刻点  
  36.                         }  
  37.                         i++;                                  // 电平变化数+1  
  38.                 }  
  39.         }  
  40.            
  41.         TIM_Close(Tim3);                               // 关闭TIM3的时钟  
  42.         return ((u32)t*403/400);    
  43.  // 修正波特率值(加上电平变化的斜率,大概为0.75%,经验值)  
  44. }  

上述函数的返回值,直接填入USART1的波特率寄存即可(如果APB2的时钟与定时器时钟相同的话)。
上述计算检测出来的波特率值,与实际波特有一点点差异,但不影响正常通信。
参与测试的波特率有1200、2400、4800、9600、14400、19200、28800、38400、56000、57600、115200、128000、250000、500000bps.


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


原文地址:http://blog.csdn.net/linlingpeng_/article/details/8944993