1、貌似现在申请软著财政全额补贴,也就是说不要钱。如果有闲心的话,可以去申请。
2、但楼主公布的是一种方法,软著对方法没有保护力度,有保护力度的是专利。
3、但是我掐指一算,这种方法的发明不会晚于1900年,因此不具备专利性。
4、这种方法的问题在于,如果线路很长,传输需要较长时间的话,他的传输速率受限于电缆中的光速,如果考虑线缆的分布参数,就必须更慢。假设传输距离达到1msC',那么至少2ms才能传送一位。
5、这是一个有趣的“发明”和实验,鼓掌。
今天我又是一个碌碌无为的知食分子,趁着学校的复习周比较闲暇发个帖子先。
一个乌漆嘛黑的晚上,我还是一如既往睡不着,实操完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年5个月前 - 2021/07/17 17:15:54]
1、貌似现在申请软著财政全额补贴,也就是说不要钱。如果有闲心的话,可以去申请。
2、但楼主公布的是一种方法,软著对方法没有保护力度,有保护力度的是专利。
3、但是我掐指一算,这种方法的发明不会晚于1900年,因此不具备专利性。
4、这种方法的问题在于,如果线路很长,传输需要较长时间的话,他的传输速率受限于电缆中的光速,如果考虑线缆的分布参数,就必须更慢。假设传输距离达到1msC',那么至少2ms才能传送一位。
5、这是一个有趣的“发明”和实验,鼓掌。
原来1211是admin
传输一个bit要2根线4次传输 效率太低了
没有实际可以应用的场景啊 当前几乎没有对不同“速度”相连的需求
而且从粒度上说 这不能称为一种“协议” 大概属于某种协议的“编码方式” 或者干脆说某种“信号”方式
原来1211是admin 传输一个bit要2根线4次传输 效率太低了 没有实际可以应用的场景啊 当前...
传输一个bit需要两线,一根拉低电平,一根应答线,视频中是在拉低后设置了个延时函数看起来像是四次。实则是两次啦
定义上应属于一个新的协议叭?实际应用场景或许比较少,暂时作为私人协议开发的时候用一下吧,前途确实不太大
传输一个bit需要两线,一根拉低电平,一根应答线,视频中是在拉低后设置了个延时函数看起来像是四次。实...
是4次 红灯亮是一次 然后绿灯亮 然后是红灯灭 然后是绿灯灭 一共4次电平传递过程
而且类似这样无时钟电平传输的方法 抗干扰很差的 如果用硬件实现两边 大概会有latch或毛刺的问题吧
比如说有个干扰让红灯亮了一下 被对方观察到了 怎么办
是4次 红灯亮是一次 然后绿灯亮 然后是红灯灭 然后是绿灯灭 一共4次电平传递过程而且类似这样无时钟...
这个灯是为了更好观察传输一个字节的过程焊的,实际应用中可有可无吧。在实际传输过程是两边先把电平拉高,然后一边一个io口拉低另一边,所以另一边是被动拉低的,实际上只有两次电平传递。
楼主提出的这个方法最突出的本质就是逐位的进行ack,算得上一点巧妙的地方就是ack线同时也是数据线,节省了几个信号。
然后来看一下为什么现代通信物理层几乎没有使用逐位的ack的设计,最浅显的原因显然是overhead太大了,使用ack/nak来机制来保证传输可靠性的协议很多,而ack的间隔越短效率就越低,所以各种通信协议都是尽量增大ack的间隔,比如TCP/IP协议里就有cumulative ack的机制。一般的通信协议ack最小的粒度也是1byte,相比之下1bit的粒度的overhead显得难以接受了;
更深层的一个原因和楼主希望实现的“不需要进行时钟同步”的目标有关系。实际上UART或者USB的收发两端的phy时钟还是同步的,他们被称为异步只是因为没有时钟信号线而已。而这种同步的需求的根源是现代数字电路的同步本性,所有的动作在最底层都是被时钟信号同步的,异步只发生在更高层次的逻辑抽象里。我们来看一下楼主提出的这个协议里同步是怎么被抽象掉的:
注意楼主写的伪码里有
while(Wire1);
这样的语句。这个语句的语义如果用软件实现,那么就是CPU要陷入一段时间的spin wait,要平白地浪费一些时钟周期。假设收发两端的CPU主频一样,那么两端spin wait的周期在信道上信号稳定的时候就会是一致的——同步又出现了。如果语句的语义是硬件实现,那么phy的实现就要以一个固定的采样率采样线上的信号,假设两端的采样率是一样的,每次传输经历的采样时钟数在两端也会是一致的,所以本质上还是同步的。
但比起两端先通过预定的时钟进行通信或者通过preamble进行时钟同步进行通信的协议,楼主的协议还存在一个劣势:对于软件实现,劣势上面已经说明过了,spin wait是浪费CPU周期的;对于硬件实现而言,采样周期设定得太长会降低通信效率,设定得太短又会增大能耗,相比之下时钟频率已知的物理层实现可以通过硬件分频来保证工作频率恰好满足采样频率的要求,从而降低功耗。
“吾尝终日而思矣,不如须臾之所学也。”楼主爱思考是好事,思考之后立马付诸实践的行动力也值得赞叹,但如果在此之前已经对数字电路的实现原理以及各种通讯协议更底层的了解,就可以节省下这样“瞎想想”的精力以投入在更有意义的事务上,顺便多保住一些头发(雾
(编辑了一些typo
楼主提出的这个方法最突出的本质就是逐位的进行ack,算得上一点巧妙的地方就是ack线同时也是数据线,...
woc这个评论用心了!
确实在while里面产生的spin wait,但貌似if和&&需要的周期更加大,这涉及到硬件底层原理里面了,还未往这个方向了解。
高频与低频之间的时间差用while来解决的话就可以不用调频过程,在这个过程或许应属于等待同频的过程,代替了同步传输中的调频过程,对于非同频设备传输上的编程有一定的简便性,但这又确实违背了高效性的初衷。
确实这学期才算得上是真正入门51还有很多东西没学上,更多底层原理应熟知才更利于后期学习,愿听大佬之言保住一些头发(雾
这样讨论非常好,即使最初的设想并不高大上。楼主的阐述深入浅出,表达得很到位。大佬的回复切中关键知识点,对学弟循循善诱。因为这些原因我给文章加了精。
如果硬件实现(一般通信电路都会硬件实现传输和buff)实际上等同电路分离在两边的特殊锁存器 注意锁存器与寄存器的差别 这也是可以非时钟化的原因
但是现在大多数通信电路甚至规模大点的逻辑电路 都使用寄存器机制 避免锁存器的出现 这是有原因的 锁存器很难免因为干扰或者其他会遇到“不应该存在”的状态 而要完整考虑锁存器的所有可能状态 比寄存器要复杂太多
就楼主的软件代码而言 许多while都可能因为干扰而死锁
比方说 小明和小伙伴约定发送1位数字 小明按下红色按钮 小伙伴按下绿色按钮 这时候忽然有个干扰 使得红色按钮暗了一下 小伙伴注意到了 松开绿色按钮 然后就不管了 认为收好了 小明反应慢 这时候才刚开始去while绿色按钮 显然他会while到断电
我觉得还有一个问题,就是冲突的解决,如果双方同时发起通讯,不管是双方同时打算发0或者1,还是一方发0,另一方打算发1,都会导致双方死等。即使在发送之前判断了线上电平的状态也没用,可能在你判断的时候,电平还是1,但是在你判断完了准备拉低的时候,对方也在做同样的事,这样的冲突是不能忽略的,因为它会导致双方同时进入死等,直到掉电。解决的方法也不是没有,就是加入一个发送超时的判断,等一段时间之后收不到应答就认为发送失败,可是这样的话,又可能因为对方正在忙别的事没顾上去启动receive()而导致误判。所以,我觉得,楼主的想法是好的,但是第一个问题是代码太简陋,考虑得不够周全,代码中的while太多,可能会导致死锁的概率大幅增加;第二个问题是通讯调度的过程完全是不可控的,谁先发起谁就是发送方,对方只能作为接收方,这可能也会导致冲突的发生。为了解决这两个问题,又需要大幅增加代码,代码的和判断条件的增加又会迅速降低通讯效率,所以,距离实用可能还有很长的路要走。
不要考虑有没有申请软著的价值,申请就完事了。
因为本身软著就没有什么价值,比专利差远了。
软著的意义是证明“某一段代码”是你创作的,没有内涵价值,你点个流水灯都能申请软著的。
不抗干扰是个大问题?随便来个脉冲通信就错误了。还有是有方法多机通信吗?
不抗干扰是个大问题?随便来个脉冲通信就错误了。还有是有方法多机通信吗?
干扰可以在软件上做个类似看门狗的程序,如果通讯错误大概率会卡死在while里面,检测到不对劲就重新发送之类的;多机通信可以用地址的方式判断是否接收该信号,会比原程序复杂一些,但是理论上都是可以完成这些功能的
引用forkeureka发表于11楼的内容我觉得还有一个问题,就是冲突的解决,如果双方同时发起通讯,不管是双方同时打算发0或者1,还是一方发0...
是的是的,你这想的挺周到,确实理论上会发生所述情况,改良的话可以双方用计时中断做个卡死判断;你提出的第二个问题的话如果两机要判断谁先发起信号,防止错乱可以在发送以及接收函数里面做个判断先进行改良,确实这样会大大减小了传输的效率冗余度过高
这个想法还是不错的。硬件上的设计方法简单,而且理论上也很适合不同系统间通信。但是我考虑到一个可能的问题。如果借助此方式进行信号传输,信号的周期和电缆长度是成正比例的,可认为单个bit信号在电缆上的传递频率为电缆固有谐振频率的一半。而电缆长度是恒定的,故信号的传递频率往往是一个恒定值。因此信号传递时,若附近存在与信号传递同频的干扰耦合到了信号线上并产生振荡,在信号传递时将会产生持久性的误码。是否有办法避免这种情况?
这个想法还是不错的。硬件上的设计方法简单,而且理论上也很适合不同系统间通信。但是我考虑到一个可能的问...
这问题有点专业,硬件上应该可以往双绞线那个方向避免上述问题(不确定),软件上这类错误会使程序卡死在while因此可以做个类似看门狗的程序在检测到卡死时重新接发
楼主提出的这个方法最突出的本质就是逐位的进行ack,算得上一点巧妙的地方就是ack线同时也是数据线,...
不要强行套用不正确的概念,非常容易误导新手。
楼主的设计是一种无时钟方案,属于典型的异步通信。根本不是什么“本质上还是同步的”。这个结构更类似RS触发器,两根线对应Set/Reset,复用数据线作为应答。
在cpu上采用自旋锁实现,并不是一个很明显的劣势,楼主也可以做中断方式实现。因为嵌入式环境是非常多样和复杂的,这样的协议有它独特的优势。没有严格的时序要求,面对各种厂家各种器件混用的环境,就是一个极大的优势。
如果采用硬件实现,也不像你说的需要固定的采样时钟,完全可以做成全异步的。使用RS触发器接收,逻辑门应答,由于无需时钟功耗能降到最低。
“现代数字电路的同步本性”不知道是谁凭空发明的概念。应当说是由于eda工具的限制,绝大部分设计会做成同步的,并不等于必须这么做。
低功耗或者极高频率,传统的同步逻辑已经走不通了,得考虑异步逻辑。
这个想法还是不错的。硬件上的设计方法简单,而且理论上也很适合不同系统间通信。但是我考虑到一个可能的问...
这不是应该加强屏蔽或者滤波吗?明显是硬件不合格,你换别的通信协议也一样。常用的有线通信方式,纠错功能都是非常有限的。
200字以内,仅用于支线交流,主线讨论请采用回复功能。