历史上的今天
返回首页

历史上的今天

今天是:2026年01月31日(星期六)

2023年01月31日 | 原理分享 | 单片机常用通信协议汇总(上)

2023-01-31 来源:zhihu

串口通信:

51单片机内部自带UART(通用异步收发器),可实现单片机串口通信。

RS232也是常用的串行通讯接口,最高速率为20KB/s,也是专为点对点通讯设计,最大传送距离为15m,适合本地设备之间的通信。


硬件电路


单片机对PC、单片机设备之间的接线为TXD连RXD,RXD连TXD

通信形式

全双工:允许数据在两个方向上同时传输

半双工:数据可以在一个信号载体的两个方向上传输,但是不能同时传输


单工:数据传输是单向的,一方固定为接收端,一方固定为发送端


UART通信方式为异步通信(通信双方各自约定通信速率)


UART数据帧格式


起始位:发送一位逻辑电平0开始传输数据

空闲位:当为高电平时,无数据传输

数据位:先发低位再发高位,传输8位数据

校验位:奇偶校验,1的位数为偶数(偶校验),1的位数为奇数(奇校验)

停止位:发送逻辑电平1停止数据传输



各参数值计算方法

SCON计算:

通常情况下选择工作方式1(8位UART,波特率可变),并且单片机一般选择工作在12T模式。

其中SYSclk为11.0592MHz,SMOD=0


串口模式图及相关代码


void UartInit(void)   //波特率设置为9600

{

AUXR = 0x01;

SCON = 0x50; //配置串口工作方式1,REN使能接收

TMOD = 0x01;//16为定时器/计数器

TH1 = 0xFD;

TL1 = 0xFD;//9600波特率的初值

TR1 = 1;//启动定时器

EA = 1;//开启总中断

ES = 1;//开启串口中断

}

I2C通信:

II2C通信是同步通信方式,采用一个同步时钟线,所有的I2C设备的SCL连在一起,SDL连在一起,均要配置成开漏 输出模式,各添加一个上拉电阻4.7k。

两根通信线:SCL(Serial Clock)、SDA(Serial Data)

同步、半双工,带数据应答

开漏输出和上拉电阻的共同作用实现了“线与”的功能,为了解决多机通信互相干扰。



I2C时序结构

起始条件:SCL高电平期间,SDA从高电平切换为低电平

终止条件:SCL高电平期间,SDA从低电平切换为高电平

发送字节:SCL低电平时,主机将数据放到SDA上,数据高位在前、低位在后,从机在SCL高电平时读取数据位

接收字节:SCL低电平时,从机将数据放到SDA上,主机在SCL高电平时读取数据位(在接受前,需要释放SDA)


发送应答(写时序):在接受完一个字节时,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答

接收应答(读时序):在发送完一个字节后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接受之前,需要释放SDA)

写时序:


读时序:


I2C代码

#include


sbit I2C_SCL = P2^1;


sbit I2C_SDA = P2^0;


void I2C_Start(void)


{


I2C_SDA=1;


I2C_SCL=1;


I2C_SDA=0;


I2C_SCL=0;


}


void I2C_Stop(void)


{


I2C_SDA=0;


I2C_SCL=1;


I2C_SDA=1;


}


void I2C_SendByte(unsigned char Byte)


{


unsigned char i;


for(i=0;i<8;i++)


{


I2C_SDA=Byte&(0x80>>i);


I2C_SCL=1;


I2C_SCL=0;


}


}


unsigned char I2C_ReceiveByte(void)


{


unsigned char Byte=0x00,i;


I2C_SDA=1;


for(i=0;i<8;i++)


{


I2C_SCL=1;


if(I2C_SDA){Byte|=(0x80>>i);}


I2C_SCL=0;


}


return Byte;


}


void I2C_SendAck(unsigned char AckBit)


{


I2C_SDA=AckBit;


I2C_SCL=1;


I2C_SCL=0;


}


unsigned char  I2C_ReceiveAck()


{


unsigned char AckBit;


I2C_SDA=1;


I2C_SCL=1;


AckBit = I2C_SDA;


I2C_SCL=0;


return AckBit;


}



 

AT24C02时序代码

 

#define AT24C02_ADDRESS  0xA0


void AT24C02_WriteByte(unsigned char WordAddress,Data)


{


I2C_Start();


I2C_SendByte(AT24C02_ADDRESS);


I2C_ReceiveAck();


I2C_SendByte(WordAddress);


I2C_ReceiveAck();


I2C_SendByte(Data);


I2C_ReceiveAck();


I2C_Stop();


}


unsigned char AT24C02_ReadByte(unsigned char WordAddress)


{


unsigned char Data;


I2C_Start();


I2C_SendByte(AT24C02_ADDRESS);


I2C_ReceiveAck();


I2C_SendByte(WordAddress);


I2C_ReceiveAck();


I2C_Start();


I2C_SendByte(AT24C02_ADDRESS);


I2C_ReceiveAck();


Data = I2C_ReceiveByte();


I2C_ReceiveAck(1);


I2C_Stop();


return Data;


}


问题解答

Q:为什么AT24C02的地址是0xA0?

A:从时序图分析:若对AT24C02执行写操作,则读写位位0,所以8位地址为 1010 0000,为0xA0;反之读写位为1,则地址为0xA1


单总线(1-Wire)

1-Wire由Dallas公司推出

采用单根信号线,既传输时钟又传输数据,而且数据传输是双向的

单总线的数据传输速率一般为16.3kbit/s,最大可达142kbit/s,通常情况下采用100kbps/s以下的速率传输数据

一般需要加上拉电阻,通常选用5k~10k

传输数据的次序是低位到高位,与I2C不同


单总线时序图

初始化:


主机拉低总线480-960us产生复位脉冲,然后释放总线,进入接受模式。

单片机器件检测到上升沿,延时15-60us,拉低总线60-240us产生应答脉冲


写操作:


主机产生一个写0的时序,拉低数据线并保持60us

主机产生一个写1的时序,必须拉低数据线,在开始后的15us内拉高数据线


读操作:


主机拉低总线1us,随后释放总线,若发送1,则保持高电平;若发送0,则拉低总线并在周期结束后释放总线

所有读操作都是在主机拉低总线并保持1us后,再释放总线开始

时序代码

sbit onewire_dq = P3^7;


unsigned char onewire_init(void)


{


unsigned char i;


unsigned char ackbit;


onewire_dq=1;


onewire_dq=0;


i = 247;while (--i);  //delay 500us


onewire_dq=1;


i = 32;while (--i);   //delay 70us


ackbit = onewire_dq;


i = 247;while (--i);  //delay 500us


return ackbit;


}


unsigned char onewire_sendbit(unsigned char Bit)


{


unsigned char i;


onewire_dq=0;


i = 4;while (--i); //delay 14us


onewire_dq  =Bit;


i = 22;while (--i); //delay 50us


onewire_dq=1;


}


unsigned char onewire_receivebit(void)


{


unsigned char i;


unsigned char Bit;


onewire_dq=0;


i = 2;while (--i); //delay 9us


onewire_dq=1;


i = 2;while (--i); //delay 9us


Bit = onewire_dq;


i = 22;while (--i); //delay 50us


return Bit;


}


void onewire_sendbyte(unsigned char byte)


{


unsigned char i;


for(i=0;i<8;i++)


{


onewire_sendbit(byte&(0x01<

}


}


unsigned char onewire_receivebyte(void)


{


unsigned char i;


unsigned char byte=0x00;


for(i=0;i<8;i++)


{


if(onewire_receivebit())


{


byte|=(0x01<

}


}


return byte;


}

功能命令

以DS18B20为例(常用)

跳过ROM——0xcc

启动转换——0x44

读取暂存器——0xbe


推荐阅读

史海拾趣

Arduino公司的发展小趣事

随着Arduino平台的不断发展,为了满足不同项目和应用的需求,Arduino推出了多种不同规格和功能的主板。例如,Arduino Diecimila和Arduino Uno等主板的推出,进一步丰富了Arduino的产品线。这些主板各具特色,适用于各种场景,使得Arduino平台在物联网和嵌入式系统的开发中发挥了越来越重要的作用。

EOREX公司的发展小趣事

在电子行业的早期,EOREX公司由一群热衷于技术创新的工程师创立。他们专注于研发高性能的半导体芯片,以满足当时市场对更快、更稳定电子产品的需求。通过不断的技术创新和产品迭代,EOREX逐渐在半导体领域树立了良好的口碑,吸引了众多合作伙伴和投资者的关注。随着公司规模的扩大,EOREX不断加大对研发的投入,推出了更多具有竞争力的产品,逐渐在电子行业中崭露头角。

Flexxon Pte Ltd公司的发展小趣事

在电子行业日新月异的背景下,Flextronics(Flexxon Pte Ltd)始终将技术创新视为企业发展的核心动力。公司投入巨资于自动化生产线、智能制造系统和物联网技术的研发,实现了生产过程的智能化和数字化。这一举措不仅提升了生产效率,还使得Flextronics在定制化生产、快速响应市场变化方面具备了显著优势。随着5G、物联网等新兴技术的兴起,Flextronics更是积极拥抱变革,与多家科技公司合作,共同推动电子产品的创新与发展。

Compensated Devices Inc公司的发展小趣事

在电子行业竞争激烈的年代,CDI始终坚持品质至上的原则。公司建立了严格的质量控制体系,从原材料采购到生产流程,再到成品检验,每一个环节都严格把关。正是这种对品质的执着追求,使得CDI的产品在客户中赢得了良好的口碑。随着口碑的积累,CDI逐渐发展成为电子元件领域的知名品牌。

Connor-Winfield公司的发展小趣事

随着全球经济的一体化,电子行业也逐渐呈现出全球化的趋势。Connor-Winfield敏锐地把握住了这一机遇,开始实施全球化战略。公司积极拓展海外市场,与多家国际知名企业建立了紧密的合作伙伴关系。这些合作不仅为公司带来了更多的商业机会,也使其在全球化竞争中保持了领先地位。

ASPEED Technology公司的发展小趣事

2018年,ASPEED正式推出Cupola360 360度影像拼接处理芯片暨解决方案。这一创新产品的推出,标志着ASPEED将产品线成功扩展至图像处理相关领域。Cupola360芯片的高性能与广泛应用场景,使其在安防监控、虚拟现实等领域受到广泛关注,为ASPEED带来了新的增长点。

问答坊 | AI 解惑

SPCE061A的IO扩展方案

摘 要:本文以举例的方式从硬件和软件原理上阐述了如何运用SPBA01B对MCU进行IO扩展、总线扩展和级联使用。 关键词:SPBA01B SPEC061A 1 引言 随着数字语音、图像处理技术的飞速发展,其在电子产品中也得到广泛应用,如语音智能玩具、P ...…

查看全部问答>

写给DSP初学者们

数字化的时代已经来临,对DSP专业人才的需求也越来越大,如今DSP技术和DSP应用已经成为当今嵌入式系统应用领域中最热门的技术,是高校、科研院所和高新技术企业的DSP软件、硬件开发人员的新的课题。很多高校开设了DSP专业,很多相关专业也增设了DSP ...…

查看全部问答>

哥们上一个“光时域反射仪”的资料

光时域反射仪,也有人叫它“OTDR”…

查看全部问答>

设想 用水作能源的车

今天突然想起以前的一个设想,能不能用水做能源呢? 这个不是没有根据乱想的,当时是看到了电解水,于是想到了这个。 如果汽车只要加水做燃料那将是一件多么好的事啊,石油都不用采了...是不是有点夸张了。 我是这么想的 水>>电解>>分离成 氢 ...…

查看全部问答>

反激式开关电源漏感吸收

张兴柱博士 电路原理图: 2,不能正常工作原理图如下: 每一个开关周期,开关S导通,2极管截止,激磁电感LM与漏感LP充电;在开关S截止,2级管导通时,激磁电感的能量通过变压器被传递到输出(大家讨论的问题:有多少能量通过RCD电路);但是漏 ...…

查看全部问答>

嵌入式老问题

老问题:究竟在嵌入式中,C语言更有前途还是C++?…

查看全部问答>

C51 位寻址疑问!

我知道, sbit是定义一个可以位寻址的变量如: P00代表了一个可以位寻址的变量P0.0, 疑问,上述定义中,那个尖尖“^ ”,是不是异或运算,还有,尖尖后面的那个数“0”,可不可以用一个变量代替。 如 [code]unsigned char index = 0;   &nbs ...…

查看全部问答>

MSP430驱动SST25VF016B程序

一个版友MSP430驱动SST25VF016B程序一直有问题,特贴出我自己使用无问题的版本。     固件中,自己更改所使用的SPI口和初始化好SPI就行。     固件SST25_Init中, u8 SST25_Init(void) {     u8 m;   &nb ...…

查看全部问答>

求以太网学习资料

最近需要学习一些以太网的知识,但是不知道从哪里入手,需要些什么资料,求大神帮助。…

查看全部问答>