mcu之间通信Word下载.docx
《mcu之间通信Word下载.docx》由会员分享,可在线阅读,更多相关《mcu之间通信Word下载.docx(14页珍藏版)》请在冰豆网上搜索。
)主CPU回应ACK。
或,1)主CPU发送命令,2)主CPU发送数据,3)从CPU回应ACK。
命令格式:
2字节同步码
+
1字节标记码
1字节从CPU地址码
1字节命令码
2字节参数码
1字节CRC校验码
数据格式:
1字节数据长度码
N
字节数据
ACK格式:
1字节回应码
(0x55表示接收正确,否则失败)
侦错与纠错机制:
靠同步码进行帧同步,靠CRC校验码进行帧检错,接收方发现错误丢弃错误帧,发送方等待数据超时重发,连续重发3次失败
放弃发送。
协议2:
竞争协议
借用以太网的机制,每个CPU都是平等地位,都可以随时发送数据。
步骤如下,当任何一个CPU想发送数据时,
1)探听COM线1ms时间,之内若无数据接收,则转2),否则继续探听。
2)向COM线发送数据,同时接收回来,一旦发现接收数据和发送数据不相同,则转3),否则一直发送数据直到数据发送完毕,返回。
3)停止发送,等待一个随机时间
ms,转1)。
发送数据格式:
1字节源CPU地址码
1字节目的CPU地址码
靠同步码进行帧同步,靠CRC校验码进行帧检错,靠高层协议进行纠错,高层协议略。
疑问解答:
发送数据时Tx变成低电平,电源岂不对地短路啦?
如果不接电感L1,COM又接地,确实会发生电源对地短路,但是接了L1后就不会了,COM接地相当于此时电源只接了L1一个负载,电源消耗的
电能随着L1电流增加变成了储存在L1中的磁能,当COM又变回高电平时,这部分磁场能量会随着D2的泄压作用转移到电容C1中,变成电场能量,
最终被CPU消耗掉,是不是和升压DC-DC有点像?
因此可以预期在通信期间,CPU供电电压(即C1电压)会有所升高。
为何选择串口(Tx、Rx)作为数据收发口?
从原理上看,调制信号占空比应该越大越好,占空比越大,每个周期内低电平时间相对越短,因DC-DC效应对CPU电源电压影响就越小;
凡事
不能走极端,占空比也不能太小,否则抗干扰能力就差了。
另外,通信速率也不宜太低,速率太低,造成发送1bit时COM线电平被拉低时间太长,L1电流过大,会造成L1储能饱和,电源效率降低。
因此,使用串口不是最好选择,串口信号调制占空比为‘1’100%可以,‘0’0%太小了;
串口速率普遍较低,最高才115Kbps。
但是,因为单
片机上一般不集成有专门适用于我这个方案的硬件收发器,软件模拟或外挂CPLD又太麻烦,所以干脆用串口算了,硬件简单,成本还低,软件
也不复杂,直接操作串口就行了。
////////////////////////////////////////////////////////////////////////////////////////////
双MCU通讯的几种方法
众所周知,单片机的硬件资源是非常有限的。
因此一些设计者喜欢扩展总线,外挂一些专用芯片,其结果是造成系统臃肿,PCB布线费事费力,成本大幅度提高,而系统的稳定性却降低!
本人曾见过一个设计:
为了周期输出一个宽度400mS的脉冲(误差:
0.1mS),而扩展了一片8155。
借用8155的定时器输出脉冲。
这种设计与再用一片MCU直接输出脉冲,哪个简单可靠呢?
MCS51系列单片机的UART口只有一个,因此扩展UART专用芯片的方法随处可见。
而实际上完全可以采用双MCU的工作方式,为系统提供两个UART口,同时也提供了T0、T1、INT0、RAM等大量的硬件资源。
现在介绍四种双MCU通讯的方法。
一、模拟SPI串口方式
电路见图一,主、从MCU之间采用3线式通讯。
主MCU负责系统的数据采集、计算、RS485通讯,而从MCU只负责显示数据。
我们知道动态驱动多位LED数码管,将占用大量MCU的时间,如果这个任务也由主MCU完成,那么编程技巧是何等的重要!
本人认为:
在应用系统中,程序的可读性、易维护性应该比编程技巧更重要。
采用双MCU系统后,主MCU只是在数据更新时,才与从MCU通讯一次,其余时间可全部用于数据采集、处理上,这样不但程序流程简单,而且可由多人独立编制。
从MCU的任务单一:
动态扫描LED数码管。
这样系统的实时性得以提高,而硬件成本并未大幅度提高!
从MCU可以设计成一个通用LED数码管驱动器,应用于其它系统中!
(附一:
串口通讯源程序)
二、并口方式
电路见图二,这是一个远程打印机的接口电路。
主MCU负责接收RS485通讯总线发来的数据,解析后通过P0口发送到从MCU。
从MCU采用RS232通讯方式,再发送到打印机打印!
虽然此电路可以用硬件代替,但是这种方法可以在不改动硬件的情况下,通过修改软件而应用于其它场合。
双MCU采用并口通讯速度快、接口简单,但占用较多的I/O线。
(附二:
并口通讯源程序)
三、采用串口RAM芯片
串口RAM芯片在市面上不易购买,但是可以利用一些带有RAM的专用芯片代替。
见图三,利用DS1302内部的31个RAM字节做RAM缓存区。
双MCU不分主次,均可访问DS1302,因此可方便地交换双MCU的数据。
而且通讯速度高!
访问DS1302时,必须通过“A线”判别访问权限。
A=1说明无MCU访问DS1302,此时可以读写DS1302。
置A=0!
访问完毕后置A=1,释放访问权。
如果A=0则必须等待!
为了防止DS1302被单个MCU多次访问,而造成数据覆盖现象,在主程序中应该合理安排访问DS1302的次数。
(附三:
DS1302的读写子程序)
四、采用双端口RAM
双端口RAM(如:
IDT7134)是专门为双MCU系统设计的,其优点显而易见。
但其价格昂贵,而且系统必须扩展总线,建议只有在不得已的情况下才使用,一般设计应尽量避免!
附:
1:
所有电路图、波形图在TWOMCU.s01文件中
附一:
串口通讯程序
;
***********************************
Clk=p3.2:
时钟脚
Sda:
数据脚
Res:
复位脚
DataNumber:
需发送的数据个数
SendDataAdr:
需发送的数据首地址
SendData:
clrClk
;
启动时钟脚
movr7,#01fh
nop
setbClk
i2c_1:
jnbSda,i2c_next;
判别是否有应答
djnzr7,i2c_1
;
等待50uS
setbRes
复位从机
CLRRes
ret
i2c_next:
***********************
movr5,#30d
djnzr5,$
有应答后等待从机初始化
movr7,#DataNumber
movr0,#SendDataAdr
clrc
i2c_s1:
movr6,#08d
mova,@r0
i2c_s2:
rlca
movSda,c
clrClk
movr5,#20d
djnzr6,i2c_s2
incr0
djnzr7,i2c_s1
i2c_end:
************************************
在INTO中断中接收
ReceByte:
需接收的数据个数
ReceBit:
需接收的数据的位数
ReceDataAdr:
需接收的数据首地址
ReceF:
接收启动标志
ReceData:
pusha
pushb
pushpsw
push00h
push01h
jbReceF,i2c_ne1
setbReceF
clrSda
movr1,#040d
!
2001.5.25
djnzr1,$
;
应答主机
movReceByte,#00h;
初始化
movReceBit,#08h
setbSda
sjmpint0_end
i2c_ne1:
mova,#ReceDataAdr
adda,ReceByte
movr0,a
mova,@r0
movc,Sda
clrc
mov@r0,a
mova,ReceBit
djnzReceBit,int0_end
movReceBit,#08d
incReceByte
mova,ReceByte
cjnea,#DataNumber,int0_end
movReceByte,#00h
movReceBit,#08h
clrReceF
*****数据转移到使用区
MOVR0,#ReceDataAdr
MOVR1,#USE_DATA;
使用区的首地址
push07h
MOVR7,#DataNumber
MOV_1:
MOVA,@R0
MOV@R1,A
incr1
DJNZR7,MOV_1
pop07h
int0_end:
pop01h
pop00h
poppsw
popb
popa
reti
附二:
并口通讯程序
*******************************************
需发送数据的首地址
需发送数据的个数
SendOverF:
=1发送完毕标志
IntoF==p3.2:
中断脚
******************************************
SendOut:
rd_d1:
movp0,a
****************sendprinter_s
**************
clrIntoF
senddatatoprinter_cpu
movr6,#03
rd_d2:
mulab
djnzr6,rd_d2
延时等待15uS
setbIntoF
djnzr7,rd_d1
setbSendOverF
************************************************
接收子程序(在INT0中接收)
需接收数据的个数地址
ReceNumber:
需接收数据的个数
ReceOverF:
push00h
movr0,#ReceDataAdr
mova,DateNumber;
countaddress
adda,r0
*********************
mova,p0
incDataNumber
mova,DataNumber
cjnea,#ReceNumber,int0_do_end
movDataNumber,#0
setbReceOverF;
receprinter_mdata
int0_do_end:
附三:
DS1302读写子程序
**********************************
r6数据位计数器
r7数据字节计数器
a命令
*****************************************
发送数据程序
名称:
Send_Byte
描述:
发送A个字节给被控器DS1302
命令字节地址在@r0中,Usea,b,r7
所发送数据的字节数在A中,发送的数据在XmtDat缓冲区中
****************************************
SendByte:
CLRCsDs1302;
复位引脚为低电平所有数据传送终止
NOP
CLRClkDs1302;
清时钟总线
NOP
SETBCsDs1302;
复位引脚为高电平逻辑控制有效
push07h;
movr7,a
S_b1:
MOVA,@R0;
传送数据过程与传送命令相同
MOVb,#08h
S_Byte2:
RRCA
MOVSoDs1302,C
SETBClkDs1302
nop
CLRClkDs1302
DJNZb,S_Byte2
INCR0;
发送数据的内存地址加1
DJNZr7,S_B1
pop07h
CLRCsDs1302
RET
接收数据程序;
ReceByte
从被控器DS1302接收a个字节数据
命令字节地址在@r0中;
usea,b,r7
所接收数据的字节数在@r0中接收的缓冲区中
CLRClkDs1302;
清时钟总线
nop
push07
movb,a
mova,@r0;
ReadOrder
MOVr7,#08h;
传送位数为8
R_Byte0:
RRCA;
将最低位传送给进位位C
MOVSoDs1302,C;
位传送至数据总线
SETBClkDs1302;
时钟上升沿发送数据有效
DJNZr7,R_Byte0;
位传送未完毕则继续
*************************
R_B1:
CLRA
CLRC
接收位数为8
R_Byte2:
MOVC,SoDs1302;
数据总线上的数据传送给C
从最低位接收数据
时钟总线置高
时钟下降沿接收数据有效
DJNZr7,R_Byte2;
位接收未完毕则继续
MOV@R0,A;
接收到的完整数据字节放入接收内存缓冲区
INCR0;
接收数据的内存地址加1
DJNZb,R_B1
*************************************
1写保护寄存器操作
当写保护寄存器的最高位为0时允许数据写入寄存器写保护寄存器可以通过命令字节8E,8F来
规定禁止写入/读出写保护位不能在多字节传送模式下写入
Write_Enable:
MOVa,#2;
命令字节+命令=2
单字节传送模式
MOVR0,#Temp;
数据地址覆给R0
mov@r0,#WrEnable;
命令字节为8E
incr0
MOV@r0,#00h;
数据内容为0写入允许
ACALLSendByte;
调用写入数据子程序
RET
当写保护寄存器的最高位为1时禁止数据写入寄存器
Write_Disable:
MOVa,#2;
MOVR0,#Temp
MOV@r0,#80h;
数据内容为80h禁止写入
当把秒寄存器的第7位时钟停止位设置为0时起动时钟开始
Osc_Enable:
单字节传送模式
mov@r0,#80h
数据内容为0振荡器工作允许
//////////////////////