分享单片机常用通信协议的原理(上)

 vx【嵌入式工程师成长日记】

https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484134&idx=1&sn=b779ccf07e88a56cce83a33f08bf9fd6&chksm=cf4307bef8348ea846497fe037377eb9727c7865c1582fdab51acfb6019a3bad967f6c06a2c5&token=1733680428&lang=zh_CN#rdhttps://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484134&idx=1&sn=b779ccf07e88a56cce83a33f08bf9fd6&chksm=cf4307bef8348ea846497fe037377eb9727c7865c1582fdab51acfb6019a3bad967f6c06a2c5&token=1733680428&lang=zh_CN#rd

串口通信:

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 <REGX52.H>

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<<i));

}

}

unsigned char onewire_receivebyte(void)

{

unsigned char i;

unsigned char byte=0x00;

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

{

if(onewire_receivebit())

{

byte|=(0x01<<i);

}

}

return byte;

}

功能命令

以DS18B20为例(常用)

跳过ROM——0xcc

启动转换——0x44

读取暂存器——0xbe

物联沃分享整理
物联沃-IOTWORD物联网 » 分享单片机常用通信协议的原理(上)

发表评论