传输一个bit需要两线,一根拉低电平,一根应答线,视频中是在拉低后设置了个延时函数看起来像是四次。实则是两次啦
定义上应属于一个新的协议叭?实际应用场景或许比较少,暂时作为私人协议开发的时候用一下吧,前途确实不太大
今天我又是一个碌碌无为的知食分子,趁着学校的复习周比较闲暇发个帖子先。
一个乌漆嘛黑的晚上,我还是一如既往睡不着,实操完51单片机的数码管使用后躺在床上瞎想想,单片机之间的通信是怎么完成的捏?于是躺在舒服的床上辗转反侧想了约莫两个小时后,不仅隔着床摇醒了舍友,还想到了一种异于IIC,SPI这类需要时钟信号的通信协议,也不同于UART串口通信这种需要设置波特率的一种新型通信协议,然后发现md又是三点钟!
所以有没有什么不失眠的方法啊???熬夜真的会掉头发啊,每次洗头的时候都希望他们下次还在。
前言
一般来说,通信协议分为两大类,一是同步通信,二是异步通信。同步通信是一种比特同步,要求发收双方具有同频同相的同步时钟信号,建立好同样的同频字符数和特定频率时钟信号后,在该同步时钟控制下发收一位位的信号;异步通信则是在开头结尾加上标志,然后中间加上数据位信息。对于两大类的通信协议来说各有各自优缺点。
基于该分类定义下,我发现本文讨论的通信协议不符合同步/异步通信的其中一种,反之是一种新类型通信协议。为下文更好地辨别这种新型通信协议,暂以“小明协议”命名讨论。
小明协议的特点
在讨论前先卖下关子,小明协议具有以下特点:
1.预设置后可收发任意比特数的比特(是真的可以任意比特)
2.无需预设置波特率(是真的不需要)
3.一种两线半双工通信协议(不计GND线)
4.可完成单总线结构通信(本文不涉及讨论)
5.很酷(是真的很酷,反正我这么觉得)
6.可以在两晶振频率不一样的单片机间直接传输(无需调频)
7.数据紧凑
8.非同步传输也非异步传输
通俗易懂的基本原理
我们先讨论单比特的传输,为我的更好述说与读者更好理解工作原理,我们先思考一下如何以以下结构完成二进制的通信
规则如下:
有两组led,当一方按下红色led按钮时,两边红色led同时亮起,绿色同之。
当一方按下红色led按钮时,另一方再按下无反应,绿色同之。
记红色led为信号0,记绿色led为信号1。
OK~熬夜的小明和聪明的小伙伴很快就能想到若要发出个信号0,只需要按下红色按钮。
若小明要多比特发送,则发出信号 0 的话,仅需要按下以下步骤完成单比特发送:
1.失眠的小明按住红色按钮(并等待绿色led亮起)
2.小伙伴看见红灯亮起,同时按下绿色按钮(并等待红灯暗下)
3.失眠的小明看见绿灯亮起,同时放开红灯按钮(完成单比特发送,并等待下个比特的发送)
4.小伙伴看见红灯暗下,同时放开绿灯按钮(完成单比特接收,并等待下个比特的接收)
我们只需要事前讨论好发收多少个比特作为一个字节便可以完成信息通信。
小明协议的代码
在该思想下,我们完全可以用C语言代码表达小明协议的通信方式。
用两条线分别为Wire0和Wire1,空闲状态下将两条线拉为高电平,设定为当Wire0被拉低时数据被即为0,反之为1。
则单比特的收发函数用以下代码完成。
//Bin[i]为存储二进制数组,需要提前在两单片机中设置同比特。 send1(uint x)//单比特发送 { if(x == 0) { Wire0 = 0; while(!Wire1); Wire0 = 1; } else { Wire1 = 0; while(!Wire0); Wire1 = 1; } } receive1() { while(Wire0 && Wire1);//等待收到信号 if(!Wire0){Bin[i] = 0;send1(1);} //若收到Wire0,Wire1回复低电平 else {Bin[i] = 1;send1(0);} }
由以上代码我们可以得知只要在发送端使用一个send函数,在接收端设置receive函数即可完成单比特的通信。
芜湖!代码和逻辑是不是极其简单!!你觉得不简单就算了
以下是单比特传输流程
d72f0d8e4b1266649daece29216261ce.mp4 点击下载
若要完成多比特接发,则仅需要for函数完成多次的发送与接收,我们可以用以下代码完成:
//二进制数组转十进制 输出十进制数 bd(Bin) 叫bd()函数是因为binary to decimalism而已啦 bd(uint x[]) { uint i,j,k,c,b,a = 0; for(j = Digit-1,i = 0;i<Digit;i++,j--)//换算 { c = 1; if(j == 0){c = 1;} else { for(k = j;k>0;k--) { c=2*c; } } b =x[i]*c; a = a+b; } return a; } /*******************传输函数*******************/ send1(uint x)//单比特发送 { if(x == 0) { Wire0 = 0; while(!Wire1); Wire0 = 1; } else { Wire1 = 0; while(!Wire0); Wire1 = 1; } } send(uint x)//多比特发送 不带地址 { uint a,i = Digit-1; for(i = 0;i<Digit;i++)//发射信号 { a = x&0x200; if(a != 0x200) { Wire0 = 0; while(Wire1); Wire0 = 1; } else { Wire1 = 0; while(Wire0); Wire1 = 1; } x = x<<1; } } receive()//多比特接收 不带地址 { uint i,x; for(i = 0;i<Digit;i++) { while(Wire0 && Wire1);//等待收到信号 if(!Wire0){Bin[i] = 0;send1(1);}//若收到Wire0,Wire1回复低电平 else {Bin[i] = 1;send1(0);} } x = bd(Bin); return x; }
所以说我们仅需要把函数打包好作为库函数引用,在主函数中调用即可
具体使用方法我们仅仅需要在发送端写入send(100);接收端写入x = receive();则可以在接收端得到x = 100。
直接使用打包后的库文件极其方便,代码逻辑结构清晰好写,完全不需要设定波特率,这样的通信协议传输数据紧凑,速度快,错误率极低(不讨论接线稳定性下),小明协议可以完成日常调试下的一些参数外部显示等功能(好像作用不大,我实在想不出有什么用)
本文写出的仅是两单片机之间的两线半双工通信协议,私下完善了能带地址传输单总线收发结构代码,本文不参与讨论。本人在考虑是否存在申请软著的价值,在此前希望各位大佬仅作为学习参考,不要用于商业用途。
功能实现演示
作为测试我们使用发送机产生一个数字,发送到接收端并用数码管显示出来。
为方便我们用十进制的num = 0然后发送一次进行对num加1,然后重复这个流程。
发送与接收端的主函数为:
其中 -begin()为I/O口初始化函数 -send()为发送函数 -receive()为接收函数 -show()为数码管显示函数
(均未显示函数内代码,其中show函数内包括了delay函数)接发函数包装为trainsmit.h库文件,以后直接调用即可。
以下为功能实现效果(两根信号线,两根电源线)
19d8d101bec24ad0371c0fc3c1468ff5.mp4 点击下载
在11.0592晶振下的51单片机传输,得到以下十位信号收发的波形图
可以约莫即得到一位信号收发需要60us,换算得到传输速率在16.67kbps左右!!
下图为单比特传输过程(代码原因0与1的传输速率是不一样的)
这里可以看出信号线被拉低并判断仅需要约2us的时间,一比特传输需要两次拉低则占用4us,其余时间为单片机执行各类函数的时间,若用高频stm32进行传输则可以大大提高传输速率,其速率受限于晶振频率最小一方。
酷毙了有没有!!没有就算了
总结
小明协议异于同步通信与异步通信定义;其不需要时钟线与设定特定的传输波特率;两根线作为信号线与应答线交替变换使用;信息紧凑,无需设定起始位与结束位信息传输高效;在11.0952M的晶振下传输速率达到16.67kbps;传输速率受限于晶振频率小的一方;仅需两根信号线...
小明协议可以直接调用包装库内的函数完成传输,使主代码极其简洁,可以跨平台,不同晶振频率且无需调频步骤,便于日常开发中的参数外部显示与调试,使开发更加简便,存在较大实际应用意义(也没多大)。
不足之处请指出,小明定虚心听教!
[修改于 3年4个月前 - 2021/07/17 17:15:54]
原来1211是admin 传输一个bit要2根线4次传输 效率太低了 没有实际可以应用的场景啊 当前...
传输一个bit需要两线,一根拉低电平,一根应答线,视频中是在拉低后设置了个延时函数看起来像是四次。实则是两次啦
定义上应属于一个新的协议叭?实际应用场景或许比较少,暂时作为私人协议开发的时候用一下吧,前途确实不太大
是4次 红灯亮是一次 然后绿灯亮 然后是红灯灭 然后是绿灯灭 一共4次电平传递过程而且类似这样无时钟...
这个灯是为了更好观察传输一个字节的过程焊的,实际应用中可有可无吧。在实际传输过程是两边先把电平拉高,然后一边一个io口拉低另一边,所以另一边是被动拉低的,实际上只有两次电平传递。
楼主提出的这个方法最突出的本质就是逐位的进行ack,算得上一点巧妙的地方就是ack线同时也是数据线,...
woc这个评论用心了!
确实在while里面产生的spin wait,但貌似if和&&需要的周期更加大,这涉及到硬件底层原理里面了,还未往这个方向了解。
高频与低频之间的时间差用while来解决的话就可以不用调频过程,在这个过程或许应属于等待同频的过程,代替了同步传输中的调频过程,对于非同频设备传输上的编程有一定的简便性,但这又确实违背了高效性的初衷。
确实这学期才算得上是真正入门51还有很多东西没学上,更多底层原理应熟知才更利于后期学习,愿听大佬之言保住一些头发(雾
不抗干扰是个大问题?随便来个脉冲通信就错误了。还有是有方法多机通信吗?
干扰可以在软件上做个类似看门狗的程序,如果通讯错误大概率会卡死在while里面,检测到不对劲就重新发送之类的;多机通信可以用地址的方式判断是否接收该信号,会比原程序复杂一些,但是理论上都是可以完成这些功能的
引用forkeureka发表于11楼的内容我觉得还有一个问题,就是冲突的解决,如果双方同时发起通讯,不管是双方同时打算发0或者1,还是一方发0...
是的是的,你这想的挺周到,确实理论上会发生所述情况,改良的话可以双方用计时中断做个卡死判断;你提出的第二个问题的话如果两机要判断谁先发起信号,防止错乱可以在发送以及接收函数里面做个判断先进行改良,确实这样会大大减小了传输的效率冗余度过高
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |
200字以内,仅用于支线交流,主线讨论请采用回复功能。