从单片机基础到程序框架(全集 2019pdf版).pdf - 第807页

上图 134.4.1 双机通讯的 2 32 串口接线图 上图 134.4.2 上位 机的独立按键 上图 134.4.3 上位 机的有源蜂鸣 器 【134.5 例程的通讯协议。 】 (一)通讯 参数。波特率 9 600,校验位 N ONE(无) ,数 据位 8,停 止位 1。 (二)上位 机读取下位机 的数组容量的 大小的 指令。 (1)上位机发 送十六 进制的数据: EB 01 0 0 00 00 07 E D。 EB 是数据头。 01…

100%1 / 836
第一百三十四节:“应用层半双工”双机串口通讯的程序框架。
【134.1 应用层的“半双工”和“全双工”
应用层的“半双工”主机与从机在程序应用层采用“一问一答”的查询模式,主机是主动方,从机
被动方,主机问一句从机答一句,聊天对话“的氛围很无趣很呆板。从机没有发言权,当从机想主动给
机发送一些数据时就“憋得慌”。半双工适用于大多数单向通讯的场合。
应用层的“全双工”主机与从机在程序应用层可以实现任意双向的通讯,这时从机也可变为主机,主
机也可变为从机,就像两个人平时聊天,无所谓谁是从机谁是主机,也无所谓非要对方对我每句话都要应答
附和(只要对方能听得清我讲什么就可以)“聊天对话”的氛围很生动很活泼。全双工适用于通讯更复杂
场合。
本节从“半双工“开始讲,让初学者先熟悉双机通讯的基本程序框架,下一节再讲“全双工“。
【134.2 双机通讯的三类核心函数。
双机通讯在程序框架层面有三类核心的涵数它们分别是:通讯过程的控制涵数,发送的队列驱动涵数
接收数据后的处理涵数。
“通讯过程的控制涵数”的数量可以不止 1 个,每一个通讯事件都对应一个独立的“通讯过程的控制涵
数”,根据通讯事件的数量,一个系统往往有 N 个“通讯过程的控制涵数”。顾名思义,它负责过程的控制
无论什么项目,凡是过程控制我都首 switch 句。此函数是属于上层应用的函数,它的基础底层是“发
送的队列驱动涵数”和“接收数据后的处理涵数”这两个函数
“发送的队列驱动涵数”在系统中只 1 个“发送的队列驱动涵数”负责“通讯管道的占用”的分配
负责数据的具体发送。当同时存在很多“待发送”的请求指令时,此函数会根据“if ,else if...”的优先
级,像队列一样安排各指令发送的先后顺序,确保各指令不会发生冲突。此函数属于底层的驱动函数。
“接收数据后的处理涵数”在系统中只有 1 负责处理当前接收到的数据,它既属于“底层函数”
属于“应用层函数”,二者成分皆有。
我们一旦深刻地领悟了这三类函数各自的分工与关联方式,将来应付再复杂的通讯系统都会脉络清析,
游刃有余。
【134.3 例程的功能需求。
上位机与下位机都有一个一模一样的 57 个字节的大数组。在上位机端按下独立按键 K1 后,上位机开始
与下位机建立通讯,上位机的目的是读取下位机的那 57 个字节的大数组,分批读取,每批读 10 个字节,
最后一批读取的是余下 7 个字节。读取完毕后,上位机把读取到的大数组与自己的大数组进行对比:如果
相等,表示通讯正确,蜂鸣器“长鸣”一声;如果不相等,表示通讯错误,蜂鸣器短鸣”一声。在通讯过
程中,如果出现通信异(比如因为接收超时或者接收某批次数据错误而导致重发的次数超过最大限制的次
数)也表示通讯错误,蜂鸣器也会发出“短鸣”一声的提示
【134.4 例程的电路图。
两个单片机进行 232 串口通讯,一共需要 3 根线:1 根作为共地线,其它 2 根是交叉的收发数据线(上
位机的“接收线”连接下位机的“发送线”,上位机的“发送线”连接下位机的“接收线”,如下图所示:
上图 134.4.1 双机通讯的 232 串口接线图
上图 134.4.2 上位机的独立按键
上图 134.4.3 上位机的有源蜂鸣
【134.5 例程的通讯协议。
(一)通讯参数。波特率 9600,校验位 NONE(无),数据位 8,停止位 1。
(二)上位机读取下位机的数组容量的大小的指令。
(1)上位机发送十六进制的数据:EB 01 00 00 00 07 ED。
EB 是数据头。
01 是指令类型,01 代表请求下位机返回大数组的容量大小。
00 00 00 07 代表整个指令的数据长度
ED 是前面所有字节数据的异或结果,用来作为校验数据。
(2)下位机返回十六进制的数据:EB 01 00 00 00 0C XX XX XX XX ZZ。
EB 是数据头。
01 是指令类型,01 代表返回大数组的容量大小。
00 00 00 0B 代表整个指令的数据长度
XX XX XX XX 代表大数组的容量大小
ZZ 是前面所有字节数据的异或结果,用来作为校验数据。
(三)上位机读取下位机的大数组的分段数据的指令。
(1)上位机发送十六进制的数据:EB 02 00 00 00 0F RR RR RR RR YY YY YY YY ZZ
EB 是数据头
02 是指令类型,02 代表请求下位机返回当前分段的数据。
00 00 00 0F 代表整个指令的数据长度
RR RR RR RR 代表请求下位机返回的数据的“请求起始地址”
YY YY YY YY 代表请求下位机从“请求起始地址”一次返回的数据长度
ZZ 是前面所有字节数据的异或结果,用来作为校验数据。
(2)下位机返回十六进制的数据:EB 02 TT TT TT TT RR RR RR RR YY YY YY YY HH ...HH ZZ
EB 是数据头
02 是指令类型,02 代表返回大数组当前分段的数据
TT TT TT TT 代表整个指令的数据长度
RR RR RR RR 代表下位机返回数据时的“请求起始地址”
YY YY YY YY 代表下位机从“请求起始地址”一次返回的数据长度
HH ...HH 代表中间有效的数据内容
ZZ 是前面所有字节数据的异或结果,用来作为校验数据。
【134.6 解决本节例程编译不过去的方法。
因为本节用到的全局变量比较多,如果有初学者在编译的时候出现“error C249: 'DATA': SEGMENT TOO
LARGE”的提示,请按下图的窗口提示来设置一下编译的环境。