🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
【126.1 同步通信与异步通信。】 既然芯片之间通信离不开“数据”和“时钟”这两种信号,那么是不是说,通信必须至少两根线(双线)以上?不是。单线也可以通信,继续拿甲乙两人的肢体通信做比喻,这一次只允许用一只“手”不许用“脚”,“手”继续做数据信号,那么时钟信号在哪?时钟信号在甲乙两人各自的“心跳”。用两个人的“心跳”作为时钟信号就有两个时钟节拍,初学者可能在这里会有疑惑,这两人的“心跳”频率可能不一致,时钟节拍可能不同步,怎么能进行通信呢?说到这里,恰好通讯界有两个专业的概念,一个是“同步通信”另一个是“异步通信”。像上一节讲那种用脚的动作“踢一脚”作为时钟信号,这个时钟信号只有一个,对于通讯的甲乙双方是实时“同步的”时钟信号,因此这种通信叫做“同步通信”。而本节提到的用两个人各自的“心跳”做时钟信号,有两个时钟源,时钟信号是“不同步的”,这种通信叫做“异步通信”。 【126.2 异步通信的原理。】 既然两人各自的“心跳”不同步(异步),而且“心跳”是从甲乙两人出生开始就一直持续存在不停跳动的,那么发送一个字节的数据是从什么时候开始到什么时候结束就必须事先有一个约定。他们是这样约定的: (1) 平时的待命状态。甲是发送方,乙是接收方,平时待命没有发送数据的时候,甲手的状态一直是“松开”的(电平1)。 (2) 1个开始位与8个数据位。当甲要发送数据给乙的时候,第1个心跳甲先“握紧”(电平0)代表“开始位”,“开始位”用来通知乙方请做好接收数据的准备,然后第2个到第9个心跳甲依次靠手的状态发送8个位的字节数据(数据位),乙方因为“甲的开始位”的存在已经做好了接收第2个心跳数据的准备,因此乙方能完全接收第2个心跳至第9个心跳的数据位的数据。 (3) 1个停止位。甲发送了第9个心跳的数据后,必须马上恢复到待命的状态“松开”(电平1),以便为下一次发送数据时能正确发送“开始位”,但是这个待命的状态“松开”至少应该持续多长的时间呢?至少持续1个“心跳”的时间以上。这样,虽然两个人的“心跳”不同步并且频率也不一样,但是只要8个“心跳”的累加误差不超过1个“心跳”的停止位时间,数据就肯定不会错位。这个至少持续1个“心跳”的待命状态就起到消除累加误差的作用。 【126.3 异步的肢体通信的例子。】 “手”可以产生“两种”状态“握紧”和“松开”,甲发送数据给乙,乙每“心跳”一次就去判断一次手的状态,“握紧”代表二进制的0,“松开”代表二进制的1,这样,如果他们之间想传输一个字节的十六进制数据0x59,只需把十六进制的数据0x59展开成二进制01011001,从右到左(从低位到高位)以“位”为单位挨个发送,过程如下: 平时手的状态一直处于“松开”的待命状态,直到手第一次出现“握紧”的状态...... 第一次“心跳”:手的状态是“握紧”,开始位,通知乙作好接收即将过来的8个“心跳”数据位。 第二次“心跳”:手的状态是“松开”,数据位bit0,记录1。 第三次“心跳”:手的状态是“握紧”,数据位bit1,记录0。 第四次“心跳”:手的状态是“握紧”,数据位bit2,记录0。 第五次“心跳”:手的状态是“松开”,数据位bit3,记录1。 第六次“心跳”:手的状态是“松开”,数据位bit4,记录1。 第七次“心跳”:手的状态是“握紧”,数据位bit5,记录0。 第八次“心跳”:手的状态是“松开”,数据位bit6,记录1。 第九次“心跳”:手的状态是“握紧”,数据位bit7,记录0。 第十次“心跳”:手的状态是“松开”,停止位,至少持续1个“心跳”的待命状态。 现在把上述的“单线”(异步)的肢体通信过程翻译成C语言代码,甲发送数据的代码如下: sbit Hand\_DATA=P2^6; //手的数据线 void SendByte(unsiged char u8Data) //甲发送数据的发送函数 { static unsigned char i; Hand\_DATA=0; //开始位。0代表“握紧” Delay(); //甲的心跳间隔时间 for(i=0;i<8;i++) //发送8个数据位 { if(0==(u8Data&0x01)) //根据数据的每一位状态,发送对应的位数据。 { Hand\_DATA=0; //0代表“握紧” } else { Hand\_DATA=1; //1代表“松开” } Delay(); //甲的心跳间隔时间 u8Data=u8Data>>1; //右移一位,为即将发送下一位做准备 } Hand\_DATA=1; //停止位。1代表“松开” Delay(); //甲的心跳间隔时间 }