搜索
bottom↓
回复: 50

串口(UART)速度深度分析!!欢迎大家指正 (^_^) --(乞讨裤子)

[复制链接]

出0入0汤圆

发表于 2011-3-19 16:33:42 | 显示全部楼层 |阅读模式
串口(UART)速度深度分析!!欢迎大家指正 (^_^) --(乞讨裤子)

//*************************[ 1 ]*************************
基础知识

什么是波特率?
就是每秒钟内发送的位(BIT)数

假设波特率(Baud)=9600, 无校验, 1位停止位/起始位
主站发送10个字节数据,从站CPU响应(发送)80个字节

先不管主站的速度,从站的各个时间如下:

接收/发送一个字节时间=10/波特率 (秒)
TB=10/BAUD=10/9600=1/960

理论(主站-->从站)接收10个字节时间=10*TB=(1/96) (秒)
理论(从站-->主站)发送80个字节时间=80*TB=(8/96) (秒)

理论的总处理时间
= CPU处理时间(T) + (接收字节数+发送字节数)*(10/BAUD)
= CPU处理时间(T) + (9/96)
约等于 (T+0.094) (秒)

//******************************************************
[CPU"定律"] :
单个CPU是不能实现全双工的, 原因很简单:
同一时间只能执行一个指令
同一时间只能操作一个内存空间
中断处理也遵循上述规定动作
(这个问题欢迎大家提出自己的见解)
//******************************************************

也就是说CPU在同一时间UART要么是收数据要么是发数据

到这里前面计算出来的(T+0.094)就很有意思了

//*************************[ 2 ]*************************
时间T和CPU的型号是直接对应的

有人说为什么不是CPU速度? 现在是型号代表速度...

(AVR,AT91,STM的速度相信大家都如雷灌耳了...呵呵)
就拿AVR的MEGA64,16MH来说.
   
程序架构:中断收发,双缓冲 (参考马老师的程序)
PC程序:comdebug.exe (小飞机图标那个)

发现总处理时间在250ms以上,只要comdebug发送时间一小就开始出现丢包
CPU的执行时间 T=0.25-0.094 约等于 0.15 秒

//-----------------------------------------------------
有耐心看到这里的人会说:怎么这么慢?!
//-----------------------------------------------------

其实我个人分析是:
中断处理和其他代码的执行时间开销是比较大的
可根据前面说的[CPU"定律"]解释
(开始砸东西过来了...)

好!现在用comdebug,在PC的两个串口上收发测试,发送时间1ms
结果是没有丢包,这说明了一点:只要CPU速度够快,CPU的执行时间可忽略不计

如果AVR要达到PC的水平(假设响应时间=0.0001秒),那频率应该是?
可以这样算: 0.0001*F=0.15*16  F=(0.15*16)/0.0001=24000
那AVR要超频到2.4G, (-_-)!

//-----------------------------------------------------
有耐心看到这里的人会说:为什么这样算?!
//-----------------------------------------------------

好!顺便讲一下:
假设代码量为N
0.15=N/16
那如果同样的代码量要求缩短时间
那新时间 = N/F
这样一来不就是: N=0.15*16=0.0001*F
呵呵

//======================================================
// 现在可以得出第一个结论: 只要CPU够快,神马都不是问题!
//======================================================

//*************************[ 3 ]*************************
时间0.094是直接和波特率对应的

波特率越高
在同一时间内数据的收发量越大
主从站之间数据的响应时间越短
(谁都知道了,还用你说...)

好还是拿AVR的MEGA64,16MH来说

先测试115200, 不试不知道,这一试...
就算comdebug发送时间是一秒钟,也会丢包
唉...速度啊

57600,38400,19200...

最后发现38400是上限了,超过后容易造成丢包

//-----------------------------------------------------
有耐心看到这里的人会说:怎么老拿MEGA64来测试?!
//-----------------------------------------------------

AVR天下皆知嘛...

还有就要说一下AT91的PDC,网上有人说怎么怎么快,
可是我实际测试时发现速度是一样的

AT91的代码:

AT91F_US_SendFrame((AT91PS_USART) AT91C_BASE_DBGU, (char *)PDC_header,sizeof(PDC_header),0,0);
while (AT91F_PDC_IsTxEmpty (AT91C_BASE_PDC_DBGU)==0){}

就是这里,再怎么快也要等,既然如此,还不如:

while (!AT91F_US_TxReady((AT91PS_USART) AT91C_BASE_DBGU)){}
AT91F_US_PutChar((AT91PS_USART) AT91C_BASE_DBGU,Data);

小的不才, 测试情况发现速度的确没多大的差别
如有冒犯请多多谅解...

//-----------------------------------------------------
有耐心看到这里的人会说:你想说什么?!
//-----------------------------------------------------

理论上讲:
如果在主从模式的网络中提高波特率来提高数据的响应速度,是不合理的

换句话说我就那点运算速度,你看着办吧  (-_-)!

其实网上早有大侠写过这个问题的文章
"基于VxWorks的多路高速串口的通信方法设计"
http://www.donews.com/tele/201009/217624.shtm

//******************************************************
由于代码都是在FLASH内,但是FLASH的操作速度基本在40MH以内
所以AVR,AT91SAM7的运行效率也就在40MH的速度内
当然在SRAM内运行除外
(这个问题欢迎大家提出自己的见解)
//******************************************************

//======================================================
// 现在可以得出第二个结论: 只要波特率过快,神马都是问题!
//======================================================

就写这么点了,欢迎大家指出错误!

总结:
(1)关于波特率=115200的问题在程序的处理方式上,参考程序在 【15楼】 ccstc 已给出

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2011-3-19 16:48:18 | 显示全部楼层
CPU再快不如一个硬件FIFO有用. 你以为PC不丢包是因为PC的CPU快?

出0入0汤圆

 楼主| 发表于 2011-3-19 17:18:10 | 显示全部楼层
回复【1楼】aozima
cpu再快不如一个硬件fifo有用. 你以为pc不丢包是因为pc的cpu快?
-----------------------------------------------------------------------

aozima 你好

硬件FIFO对UART收发来速度来说是很有用,
假设深度是32位,能同时缓冲3个字节的数据,也就是说PC可以等到3个字节都收到再处理
可以很大提高执行效率

不过本文是针对MCU的,对于计算机只是拿来比较一下而已.

还有就是不管如何CPU总要访问操作外设,这个是需要时间的,

出0入0汤圆

发表于 2011-3-19 17:21:24 | 显示全部楼层
深度

出0入0汤圆

发表于 2011-3-19 17:27:55 | 显示全部楼层
回复【楼主位】WOTASOM  突击驾驶员
-----------------------------------------------------------------------

我认为波特率太高通讯有问题是因为,MCU产生的波特率偏差大了,把晶振换成7.3728MHz看看,就会解决好,我试过的可以到115200BPS

出0入0汤圆

 楼主| 发表于 2011-3-19 17:32:20 | 显示全部楼层
回复【4楼】linghu2 令狐二中
回复【楼主位】wotasom  突击驾驶员
-----------------------------------------------------------------------
我认为波特率太高通讯有问题是因为,mcu产生的波特率偏差大了,把晶振换成7.3728mhz看看,就会解决好,我试过的可以到115200bps
-----------------------------------------------------------------------

linghu2 令狐二中 你好!

这个问题我也试过,不过用的是18.432的晶振,偏差为0.0%, 结果是有点改善,但情况不是很理想.
(测试环境: 用comdebug,发送时间250ms, MEGA64收到什么回发什么)

出0入0汤圆

发表于 2011-3-19 18:37:32 | 显示全部楼层
大部分mcu的串口收发都是硬件处理的,并不需要cpu参与,
做到全双工是很容易的
cpu其实只需要把数据写入/读出就可以了
115200处理起来应该是没问题的

出0入42汤圆

发表于 2011-3-19 18:45:30 | 显示全部楼层
我只能说我11.0592M的M8跑115200没问题

出0入21汤圆

发表于 2011-3-19 18:45:52 | 显示全部楼层
在nios中使用44.2368MHz晶振,1.2288Mbps很稳定

出0入0汤圆

 楼主| 发表于 2011-3-19 18:51:57 | 显示全部楼层
回复【6楼】chenchuan
大部分mcu的串口收发都是硬件处理的,并不需要cpu参与,
做到全双工是很容易的
cpu其实只需要把数据写入/读出就可以了
115200处理起来应该是没问题的
-----------------------------------------------------------------------

chenchuan 你好!

UART属于外设硬件,
CPU只要把数据写进TXD寄存器,发送部分是由UART外设自动执行
UART外设自动接收数据并保存到RXD寄存器,再等待CPU读取

这样问题就出来了,单个CPU不可能同时操作TXD寄存器和RXD寄存器
既然如此,全双工岂不是...

只有CPU速度足够快的时候,才让人感觉到数据的收发是同时进行的,就是"全双工"了

波特率=115200在正常情况下是没问题,比如说一秒钟收发一次
但是如果250毫秒一次呢?
这个如果试过就知道了(可参考马潮老师MEGA128的代码)

出0入0汤圆

 楼主| 发表于 2011-3-19 18:55:49 | 显示全部楼层
回复【7楼】ccstc
我只能说我11.0592m的m8跑115200没问题
-----------------------------------------------------------------------

ccstc 你好!

波特率=115200在正常情况下是没问题,比如说一秒钟收发一次
但是如果250毫秒一次呢?

出0入0汤圆

 楼主| 发表于 2011-3-19 19:02:15 | 显示全部楼层
回复【8楼】kunnsd 魏坤
在nios中使用44.2368mhz晶振,1.2288mbps很稳定
-----------------------------------------------------------------------

kunnsd 魏坤 你好!


在下不才,NIOS核我不太懂,呵呵

请问大侠是用来做主站还是从站,如果是作为从站功能那主站的发送时间是否小于250毫秒呢?
但是如果发送时间<=250毫秒,1.2288mbps是否能每次都正确接收和响应.

还请大侠指点.

出0入0汤圆

发表于 2011-3-19 19:04:34 | 显示全部楼层
处理速度的问题,现在的单片机16M晶振,只收发数据1Mbps普遍都没有什么问题的,是双工的,你处理不过来并不表示就是单工,只不过是接收了数据,你没有来的急处理而被丢弃,关键是用好中断和缓冲,DMA神马东东的,你要总是对接收数据进行神马浮点FIR运算,当然慢了。

出0入0汤圆

发表于 2011-3-19 19:13:05 | 显示全部楼层
谢谢!受教了。

出0入0汤圆

 楼主| 发表于 2011-3-19 19:17:18 | 显示全部楼层
回复【12楼】first blood
处理速度的问题,现在的单片机16m晶振,只收发数据1mbps普遍都没有什么问题的,是双工的,你处理不过来并不表示就是单工,只不过是接收了数据,你没有来的急处理而被丢弃,关键是用好中断和缓冲,dma神马东东的,你要总是对接收数据进行神马浮点fir运算,当然慢了。
-----------------------------------------------------------------------

first blood 你好!

你说的是对的,外设是全双工的(可同时进行数据收发)
但我个人认为不是由于CPU处理不够快,才导致是半双工效果,这是效CPU的运行机制造成的

具体见 【9楼】回复

出0入42汤圆

发表于 2011-3-19 19:41:53 | 显示全部楼层
我手头的都是485的串口
专门焊了块16F877A+11.0592+MAX232来测试
115200波特率,发送3M的文件,CRC校验完全正常
程序如下
#include <htc.h>

__CONFIG(WDTDIS & LVPDIS & HS & PWRTDIS & BORDIS);//设置配置位
//WDTDIS:disable watchdog timer
//LVPDIS:low voltage programming disabled
//HS:high speed crystal/resonator
//PWRTDIS:disable power up timer
//BORDIS:disable brown out reset

/******************************************************************************
* 函 数 名: mian()
* 函数功能:
* 入口参数: 无
* 返    回: 无
*******************************************************************************/

void main()
{       
        BRGH = 1;      
        SPBRG = 5;                //高速 波特率115200
        TXEN = 1;                //发送使能
        CREN = 1;                //接收使能
        SPEN = 1;                //开启USART

        TRISC6 = 1;                //设置为输入状态
        TRISC7 = 1;
       
        RCIF = 0;
        RCIE = 1;                //开接收中断
        PEIE = 1;                //开外设中断
        GIE = 1;                //开总中断
       
        while(1)
        {
                ;
        }       
}

/******************************************************************************
* 函 数 名: interrupt rxdata(void)
* 函数功能: 中断函数,等待接收字符数据,收到数据则返回接收到的字符串
* 入口参数: 无
* 返    回: 无
*******************************************************************************/

void interrupt rxdata(void)
{
        unsigned int temp;
        if(RCIF)                                                //有数据接收
        {
                RCIF=0;
                temp = RCREG;                                //读取数据                       
                TXREG = temp;                                //发送接收的数据
        }
}

出0入0汤圆

 楼主| 发表于 2011-3-19 19:52:22 | 显示全部楼层
回复【15楼】ccstc
-----------------------------------------------------------------------

非常感谢!
我对比了一下程序,原来处理方式是不一样的.
换成你的的确是可以的!

出0入0汤圆

 楼主| 发表于 2011-3-19 19:58:50 | 显示全部楼层
请教 ccstc 大侠:

如果要接收一个16进制数据帧,但长度不定,比如说MODBUS RTU报文,
怎样才能判断接收完整了?

出0入42汤圆

发表于 2011-3-19 20:09:59 | 显示全部楼层
只是无名小足,莫称大侠
一般都要靠协议判断,比如:
帧起始符+长度+信息报文+校验+帧结束符
循环接收,符合这一结构并且校验正确,就可以认为接收完整了

MODBUS RTU是一般认为当接收空闲达到3.5个字符时(长度一般理解为11位),上一帧结束
比如2400波特率的时候大约为16.1ms

出0入0汤圆

 楼主| 发表于 2011-3-19 20:22:16 | 显示全部楼层
ccstc 谦虚了!呵呵
如果这样判断帧结束,那是不是要开一个定时器?
这样一来在响应速度上时候会随波特率不同而有所变化,开销上会不会...

出0入4汤圆

发表于 2011-3-19 20:34:02 | 显示全部楼层
太多了,没看完,但我用STM32,内核24MHz,全双工收发115200完全没有问题,能把PC机上发过来的512KB数据全部正确接收。

出0入42汤圆

发表于 2011-3-19 20:37:13 | 显示全部楼层
Q1:
我的程序一般都用一个定时器做心跳,对各个任务进行轮询
那就顺便做超时计数,收到数据就清除,“溢出”就可以判断完成了
Q2:
对于不同的波特率,初始化串口的时候增加一个Switch()就可以了,几乎没什么多余的开销
都用上MODBUS了,系统应该不会太紧张

出110入109汤圆

发表于 2011-3-19 20:43:19 | 显示全部楼层
这看下,不说话,至今有个USART项目传输出小概率误码还没寻出bug出来
P.S. 本帖代码不全,估计难置cool

出0入0汤圆

 楼主| 发表于 2011-3-19 20:44:56 | 显示全部楼层
回复【21楼】ccstc
-----------------------------------------------------------------------

回头我也试看看,多谢了

出0入0汤圆

发表于 2011-3-19 20:59:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-20 08:47:14 | 显示全部楼层
受教了!

出0入0汤圆

发表于 2011-3-20 11:12:43 | 显示全部楼层
115200的速度不算快,一个字节才87us,不用FIFO,不用DMA,常用的单周期的MCU都能应付过来,关键是程序结构要好。

出0入0汤圆

发表于 2011-3-20 11:23:43 | 显示全部楼层
lz 对传输速度和响应速度理解有偏差。

响应首先是要处理通讯对自身执行流程无影响。你的程序执行周期是100ms,你做到10ms响应有啥用?起码也得是100ms级别的响应。

加一个定时器做接收超时判断很有必要。

出0入0汤圆

 楼主| 发表于 2011-3-20 18:20:26 | 显示全部楼层
回复【26楼】modbus
-----------------------------------------------------------------------

modbus  你好

是的,如果程序冗长,那就影响很大了...

出0入0汤圆

 楼主| 发表于 2011-3-20 18:23:27 | 显示全部楼层
回复【27楼】heky
-----------------------------------------------------------------------

heky 你好!

说的是对的,这也是我想表达的意思,
如果本来要100ms执行的代码,只用10ms执行,
从速度上说就弥补了处理上时间的消耗,10ms级别的响应就没有问题了.

出0入0汤圆

发表于 2011-3-20 22:08:22 | 显示全部楼层
顶一下

出0入0汤圆

发表于 2011-3-20 23:53:40 | 显示全部楼层
你想想为什么波特率再快也不能超过主频的二分之一,而通常最少为256分之一,就是为了给CPU处理数据留出时间,硬件方面绝对能达到几十M的速度,串口本来就是低速设备,优先级是比较低的,响应时间本来就不快的,你非要达到1ms响应时间还是用USB吧

出0入0汤圆

 楼主| 发表于 2011-3-21 21:07:14 | 显示全部楼层
回复【31楼】first blood
-----------------------------------------------------------------------

是的,外设速度再快,也要等CPU来得及处理,非要那么快就把中断优先级设置为最高,或者整个程序就一个中断,
上刺刀拼了,呵呵...

出0入0汤圆

发表于 2011-3-21 23:02:08 | 显示全部楼层
这个要记录下,不错

出0入0汤圆

 楼主| 发表于 2011-3-21 23:45:54 | 显示全部楼层
多路高速串口的通信方法设计ourdev_624460C71UDZ.pdf(文件大小:77K) (原文件名:多路高速串口的通信方法设计.pdf)

出0入0汤圆

发表于 2011-3-27 20:22:06 | 显示全部楼层
串口(UART)速度深度分析!  <-- 太想當然

請計算 1 Byte 處理時間 ,CPU 執行時間。

出0入0汤圆

发表于 2011-3-27 21:42:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-27 23:03:53 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2011-4-1 01:20:23 | 显示全部楼层
回复【35楼】easier
串口(uart)速度深度分析!  &lt;-- 太想當然
請計算 1 byte 處理時間 ,cpu 執行時間。
-----------------------------------------------------------------------

那请你说一下,你的深度如何?!

出0入0汤圆

发表于 2011-4-1 17:31:30 | 显示全部楼层
多路高速串口的通信方法设计ourdev_624460C71UDZ.pdf(文件大小:77K) (原文件名:多路高速串口的通信方法设计.pdf)  

为什么打不开?

出0入0汤圆

发表于 2011-4-1 17:45:39 | 显示全部楼层
mark一下。

出0入0汤圆

发表于 2011-4-1 18:51:46 | 显示全部楼层
果断mark

出0入0汤圆

发表于 2011-4-26 22:21:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-27 12:15:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-27 12:36:21 | 显示全部楼层
1 - 楼主对串口硬件处理机制不了解
    好好查看DataSheet硬件机制介绍

2 - 楼主的软件构架,存在问题
    好好想想软件算法

我跑:128000都没问题!
   
   如果相应要求实在是高,还是选用USB 或 网络吧!

出0入0汤圆

发表于 2012-5-21 20:31:10 | 显示全部楼层
WOTASOM您好,
马潮老师MEGA128的代码能帖下网址么,想参考下……

出0入0汤圆

发表于 2012-5-22 07:53:23 | 显示全部楼层
一路飘过!!!

出0入0汤圆

发表于 2012-5-23 17:49:37 | 显示全部楼层
太深奥~~

出0入0汤圆

发表于 2012-5-23 18:15:10 | 显示全部楼层
处理周期〈= 接受周期

出0入0汤圆

发表于 2013-10-21 17:09:35 | 显示全部楼层
AT的M3还真是没用过

出0入0汤圆

发表于 2013-10-21 22:06:21 | 显示全部楼层
MARK~!正在整M16的串口,学习学习了~!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 00:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表