串口通信:
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
相关文章