程序匠人 发表于 2011-5-31 21:36

喜欢串口辅助调试的进(8月19日《串口猎人》V31发布在484楼)

有时候,单片机没有显示,为了观测实时数据(比如温度、压力、角度、加速度等等),可以把数据通过串口传到电脑上,以辅助调试。——你有没有这种工作经历?或者有没有这种需求?

如果有的话,你会用什么样的通信协议呢?请大家畅所欲言。

匠人先抛砖引玉,举几个例子:

如果数据比较单一,比如说只有一个单字节的数据。那么可以不要搞什么协议,直接发即可。

如果数据比较多,那么为了让上位机知道这次是什么数据。可能就要加前缀了。

如果是双向通讯,由上位机发命令查询,那么还要有应答机制。比如上位机发个命令字,下位机就根据指示回复指定的数据。

如果每次发的数据不止一个字节,必然要打包发送,以帧为单位传输。那么还涉及到帧长的传输,以及校验等协议。比如说可以用首字节代表帧长,尾字节代表校验和。

——除了这些,如果大家还有什么,不妨说说看。因为匠人正在编一个串口调试平台,主要功能就是通过串口提取有效数据,然后用类似示波器和码表的方式显示。匠人希望能尽可能多地兼容各种常见协议和功能(复杂的量大的数据,如图像数据,不在本次考虑之列)。

--------------------------------
请新进的网友直接去484楼下载最新版本《串口猎人》V31

sdwys 发表于 2011-6-19 16:04









串行通讯规范
                         版本:1.0
                      2010年12月10日

一、协议原理
本规范定义的串行链路协议是一个主-从协议。 在同一时刻,只有一个主节点连接于总线,一个或多个子节点
(最大编号为247 ) 连接于同一个串行总线,通信总是由主节点发起。子节点在没有收到来自主节点的请求时,从不会发送数据。子节点之间从不会互相通信。主节点在同一时刻只会发起一个事务处理。
主节点以两种模式对子节点发出请求:
1、单播模式:
主节点以特定地址访问某个子节点,子节点接到并处理完请求后,子节点向主节点返回一个报文(一个 ‘应答’)。在这种模式, 一个事务处理包含2个报文: 一个来自主节点的请求, 一个来自子节点的应答。
2、广播模式:
主节点向所有的子节点发送请求。对于主节点广播的请求没有应答返回,所有设备必须接受广播模式的写功能。地址0是专门用于表示广播数据。
二、字节格式

起始位Bit0Bit1Bit2Bit3Bit4Bit6Bit6Bit7地址数据检测停止位
说明:
1、每个字节包含11位
2、主节点发送的所有地址字节第10(地址数据检测位)位必须为1
3、所有数据字节和从机发送帧第10(地址数据检测位)位必须为0
4、字节发送时低位在前,从左到右顺序发送

三、数据编码

在多个字节发送时,使用高字节在前的发送方式,即首先发送最高有效位。
例如:
16比特0x1234, 发送的第一字节为0x12 ,然后0x34。


四、报文帧
所有在总线上的通讯都是以报文的形式进行收发,由主节点或从节点发出的符合报文帧结构的一串数据称为报文帧。一个报文帧的最大长度为256字节,整个报文帧必须以连续的数据流发送,主节点和从节点发送的数据必须符合报文帧结构。
报文帧结构
地址域(1Byte)功能码(1Byte)数据域(0-252Byte)差错校验域(2Byte)
五、报文帧描述

地址域说明
1、地址范围1-247。
2、地址0为广播地址,所有的子节点必须识别广播地址,对于主节点广播的请求没有应答返回。
3、地址248-255为保留地址
4、主节点没有地址,所有子节点必须有一个地址,该地址在同一串行总线上必须是唯一的
5、主节点通过将子节点的地址放到报文的地址域对子节点寻址。
6、当子节点返回应答时, 它将自己的地址放到应答报文的地址域以让主节点知道哪个子节点在回答。

功能码说明
1、
指明要执行的动作。功能码后面可跟有表示含有请求和响应参数的数据域。
2、
功能码范围为:1-127,十六进制为:0x01-0x7F

数据域说明
1、
根据功能码的不同数据域数据含义和数据多少不同。
2、
在某些功能码中,数据域可以是不存在的(0长度),在此情况下任何附加信息。功能码仅说明操作。
差错校验
1、差错检验域是对报文内容执行
“冗余校验” 的计算结果,占用2字节
2、采用CRC16,计算方式见附录A.。
3、发送时校验值的低字节在前,高字节在后



sdwys 发表于 2011-6-20 16:50

对匠人的项目谈一下自己粗略的想法,还不具体 还没调理想到那写到哪,细节有待完善,希望抛砖引玉,动用大家的智力来辅助匠人把软件做一个好的,易于扩展的框架,细节可以慢慢填充修改。

下面我谈一下我对该项目的认识,供楼主参考。

本人认为用串口调试单片机是一种折中的方式,不但占用单片机资源,还增加软件的编写难度,不过对没有仿真器的用户还是相当实用的。门槛很低,现在的单片机都带有串口,用串口调试潜力很大,在这方面还没有成熟的东西。对楼主的这个项目严重支持,在通讯协议方面楼主不应该考虑去兼容多少协议,而是要根据实际情况去做一个标准调试协议,只要大家遵守该协议,并在单片机程序中加入对协议的支持就可以用串口调试单片机。

用串口对单片机的调试无非是为了观察程序运行中数据的变化,对于具有固定地址的存储器只需要将数据用串口读写,然后用串口调试软件配合地址显示(如IDE中RAM显示方式)出来就可以了。
具有具体地址的数据显示格式

0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
00

10
20
30
40
50
60
70



对于单片机调试中的断点,可在单片机RAM中定义一地址,用串口对该地址进行写入,并定义一断点特征码,单片机运行中不断对此RAM进行检测,一旦出现特征码,就像串口发送一段信息,并原地踏步,直到特征码被修改,程序在继续执行。

对于楼主的调试软件可分为两个侧重点,1、现实工程中的串口调试,2、用串口对单片机进行调试.

对于现实工程中的串口调试,每个项目,每个公司都会有不同的协议,没有必要对所有协议进行支持,只要做到通用,功能齐全,稳定可靠就好。

对于用串口对单片机进行调试,使用环境已定,楼主就可以制定一专门针对于单片机调试的特定标准协议,让各个单片机开发者来适应支持标准,比楼主去适应不同的协议要强的多,而且在标准化后软件的通用性还更好。



调试时选择10位模式,1启始位,8数据位,1停止位
波特率尽量高,115200或57600

用串口调试单片机软件我认为会遇到两种情况:

1、
单片机运行过程中程序触发某些事件而向串口主动发送数据。对此种情况,串口调试软件应对端口进行监听,一旦有正确的数据要随时接收
2、由串口调试软件主动发送命令,单片机接收到正确命令后,对命令做出反应。


对于用串口对单片机进行调试的协议格式
一、
1、格式
功能码 :数据地址高 :数据地址低 :字节数高 :字节数低 :数据 :CRC校验
2、
适用于对单片机内部有具体地址的RAM、ROM或其它有具体地址的存储器进行大数据块的读写,通过改变功能码可实现不同的功能。
3、
优缺点
(1)、优点
          可对较大的数据块进行读写
   (2)、缺点
          占用时间多,大数据块时容易出错
二、
1、格式
功能码 :数据地址 :字节数:数据 :CRC校验
2、适用于对单片机内部有具体地址的RAM、ROM或其它有具体地址的存储器进行小数据块的读写,通过改变功能码可实现不同的功能,通过功能码可实现变址寻址来访问整个单片机内的存储空间。
3、
优缺点
(1)、优点
          占用时间相对较少,速度快
   (2)、缺点
          一次读写空间有限
三、
1、格式
功能码 :字节数 :数据 :CRC校验
2、适用于对单片机运行中一些临时的或没有具体地址的如A,状态寄存器等进行读取,根据功能码用户可实现不同的功能
3、优缺点
(1)、优点
          没有具体地址限制使用随意
   (2)、缺点
          字节很少时CRC占用太多资源

四、
1、格式
功能码 :字节数 :数据 :异或校验
2、适用于对单片机运行中一些临时的或没有具体地址的如A,状态寄存器等进行读取,根据功能码用户可实现不同的功能,由于使用异或校验占用资源较少


请匠人审阅,如感觉有用,那么大家继续完善,如有违匠人的设计思想,大家可一笑而过。

21ele 发表于 2011-9-25 10:12

用了一下,感觉这个应该是目前最好用的一款基于帧的串口调试软件,但是也还有需要改进的地方,因为帧的定义和识别机制不同,所以调试时的需求也不同。

   先说帧定义的几种常用形式:
   1.帧长度识别机制。
   一般发送帧长度和接收帧长度是不同的,一般用在比较简单的通讯场合,比如温度,湿度传感器,感应卡读卡器等,发送帧一般是用来触发的,有用的数据在接收帧中,如果发送帧长度为零,就只有接收帧了,比如有的id卡读读头。虽然定长帧的是按长度识别帧的,但是因为帧通常不是连续发送的,帧间有较长的时间间隔,其实这个也可以算到时间间隔识别帧的类型里,而且用时间识别帧更好,如果单纯按长度识别帧,有异常时会出现帧内容错位,只有引入间隔时间的判断,才可以识别错位,恢复错位。

   2.字符间隔时间识别机制。
   这是最常用的一种帧识别机制,靠连续发送数据流时,判断连续两个字符之间的间隔时间大于设定时间,来判断为帧的起始和结束。 这种机制的原理是通常mcu或pc等硬件串口发送数据事,字符和字符间隔通常很小,或是完全是连续的。modbus rtu格式就是一典型的这种帧识别机制,rtu中规定,如果发送一个字符时间为t的话,连续两个字符间隔时间>3.5t则认为一个帧结束了。
    这种模式对于时间是极度敏感的,对于一般的电缆连接的rs232或rs485或电流环,这个没有问题,间隔时间是可以保证的。但是随着各种各样串口透传设备的出现,比如以usb转串、太网转串透传、无线串口透传、gprs串口透传(dtu)等,问题出现了。这些透传设备,可以保证数据传输的正确性,但是大部分透传都丢失了原串口上数据传输的时间特性,就是字符间间隔时间,并且由于透传大部分是先接收,然后打包发送,从而引入了新的字符间隔时间,这个在原串口数据流中是没有的。
    如果引入的字符间隔时间大到一定程度,就会识别为错误的帧,导致通讯错误。
    这里的一个关键就是透传设备打包再转发的时间,如果这个速度够快,就会基本无影响,比如usb转串。

   3.转义字符识帧识别机制。
   最典型的就是SLIP协议(Serial Line Internet Protocol,串行线路网际协议),可能很多人并不熟悉,但是它确实很有参考性,原理就是定义0xC0为帧头帧尾识别标志,数据中如果出现了0xC0,就发送两个字节的数据0xDB,0xDC代替,数据中如果出现了0xDB,就发两个字节的数据0xDB,0xDD代替。这是一种牺牲时间换取性能的做法,就是以发送,0xC0和0xDB需要发送两个字符为代价,换取了一个独立于数据00-FF之外的一个帧识别标志0xC0。这样,当数据大量发送是,损失的性能不大大,因为数据中0xC0和0xDB出现的概率通常并不多,但却实现了有效的帧识别。
   作为转义字符的一个特例,一个极端,就是ascii码格式的数据通讯,相当于所有的数据都要转义,每一个字节数据都要分成两个ascii码传送,效率变为原来的一半,但是换来的优势是,有大量的ascmii码可以用来做帧头、帧尾甚至其他特殊功能定义。
   常见的有modbus ascii 格式和AT指令格式。
   在所有的转义字符识别帧的机制了,帧识别完全不再依赖时间,所以可以有效的适用在各种串口透传设备下。但是,有时候,仍然会检测字符间隔时间,但这个只是用来检测物理链路是否被断开,而不是被用来识别帧的。

NE5532 发表于 2011-5-31 21:39

给匠人跑跑题——ESC/POS指令集到底写得好不好?WHY?


我想了2年没想通。

来与君 发表于 2011-5-31 21:45

仿µCOSView的

程序匠人 发表于 2011-5-31 21:52

给匠人跑跑题——ESC/POS指令集到底写得好不好?WHY?


我想了2年没想通。
NE5532 发表于 2011-5-31 21:39 https://bbs.21ic.com/images/common/back.gif

这是EPSON公司自己制定的针式打印机的标准化指令集,现在已成为针式打印机控制语言事实上的工业标准。ESC/POS打印命令集是ESC打印控制命令的简化版本,现在大多数票据打印都采用ESC/POS指令集。其显著特征是:其中很大一部分指令都是以ESC控制符开始的一串代码。

我没有研究过。不过初看了一下。这个协议主要是面向控制的。与我的目标不一致。

我要的是那种以传输简单数据为目标的协议。

精益求精 发表于 2011-5-31 22:01

本帖最后由 精益求精 于 2011-5-31 22:03 编辑

简单的:桢头,数据长,命令1,命令2,数据1.。。。。。。。数据N,检验值,帧尾。

还有看了一个老外的:桢头 数据1,。。。。帧尾。但是,数据的前四位和后四个位是互补。比如0XF0,或0XA5等,数据中只有后四个BIT有效,和下一个数据的后四BIT位合成一个数据。。
例如:数据1  0XA5,数据2 0XF0,那么就表示传输的是
数据0X50......

程序匠人 发表于 2011-5-31 22:02

简单的:桢头,数据长,命令1,命令2,数据1.。。。。。。。数据N,检验值,帧尾。

还有看了一个老外的:桢头 数据1,。。。。帧尾。但是,数据的前四位和后四个位是互补。比如0XF0,或0XA5等。 ...
精益求精 发表于 2011-5-31 22:01 https://bbs.21ic.com/images/common/back.gif

你这里的帧头和帧尾是指的什么?几个字节构成?是固定的还是非固定的?

精益求精 发表于 2011-5-31 22:08

我用的桢头一般是 0XFF,帧尾用0XFE.  .或0X02,0X03。。。。。

最好串口传输中数据用BCD码,桢头和帧尾用0XFF,0XFE,总有带字母的。0~9的数据表示数据。
比如0XFF ,0XF1  表示桢头,帧尾,命令。数据全部是0~9的数。0X01,0X99..
解析串口数据,自己定义。如0X99表示99,或其他值。

程序匠人 发表于 2011-5-31 22:25

我用的桢头一般是 0XFF,帧尾用0XFE.  .或0X02,0X03。。。。。

最好串口传输中数据用BCD码,桢头和帧尾用0XFF,0XFE,总有带字母的。0~9的数据表示数据。
比如0XFF ,0XF1 ...
精益求精 发表于 2011-5-31 22:08 https://bbs.21ic.com/images/common/back.gif

哦,你喜欢用BCD码?

我本来也想做BCD码识别的,后来觉得用处不大,又给去掉了。看来还得加上啊。

程序匠人 发表于 2011-5-31 22:26

秀下俺的“串口调试平台”中的“示波器模块”

dodome521 发表于 2011-5-31 22:27

我们一般用3个关键字(帧头0x02,帧尾0x03,转义字符0x10)做通讯。
在一些专用设备上有时会用0183协议。

NE5532 发表于 2011-5-31 22:28

我认为包头应该用自然界干扰不易出现的波形,例如0xA5,0xAA之类,0xFF只要一个下降沿就可以干扰出来,推荐用0xAA。

程序匠人 发表于 2011-5-31 22:31

这个是俺做的“自动收码模块”
一共有8个通道,每个通道可单独设置,从不同的帧中提取有效数据,并形成历史数据记录。同时,这8个通道也向示波器提供输入。

NE5532 发表于 2011-5-31 22:31

我的无线模块是0xAA + Command + Leng + Dat(变长)对短距离有线传输,其实校验不校验问题都不大,还没见过出错的(不涵盖全部现场情况),包尾个人认为是很无聊的,没啥用。

程序匠人 发表于 2011-5-31 22:35

这个是“自动发码模块”
一共可以设置16组码/字符串。每组可以单独手动发送,也可以自动轮流发送。发送间隔可调。可以自动添加帧头、帧尾、帧长、校验和之类的东东。
同时,自动发码可以与自动收码相绑定。

程序匠人 发表于 2011-5-31 22:38

再秀一下“基本功能模块”

这个功能可以实现简单的手动发码、和记录收码数据。基本上可以取代市面上的一些小的串口软件如串口精灵之类的。

程序匠人 发表于 2011-5-31 22:40

我认为包头应该用自然界干扰不易出现的波形,例如0xA5,0xAA之类,0xFF只要一个下降沿就可以干扰出来,推荐用0xAA。
NE5532 发表于 2011-5-31 22:28 https://bbs.21ic.com/images/common/back.gif

有道理。
5和A是我们的最爱,因为这两个数展开为二进制后正好是0和1交错。
另外,有时也会用3、6、、9、C等几个凑凑数。

程序匠人 发表于 2011-5-31 22:45

我自己最喜欢的协议是

帧长 + 命令 + 数据(长度可变) + 校验和

我不单独用引导码AA。但是一般会把命令字的高位用5或A表示。

古道热肠 发表于 2011-5-31 22:48

呵呵,做得不错,顺便问一下,PC机上用什么软件开发的,做得功能蛮全的嘛。

程序匠人 发表于 2011-5-31 22:53

这个是俺做的自平衡小车传输的信号实时波形

程序匠人 发表于 2011-5-31 22:57

呵呵,做得不错,顺便问一下,PC机上用什么软件开发的,做得功能蛮全的嘛。
古道热肠 发表于 2011-5-31 22:48 https://bbs.21ic.com/images/common/back.gif

嘿嘿,不好意思,只会VB。所以……
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 喜欢串口辅助调试的进(8月19日《串口猎人》V31发布在484楼)