本篇分两部分:1.i²c总线和EEPROOM相关 2.DSB1820温度传感器的使用
第一部分:
1.i²c总线与UART比较
i²c总显示是一种通信协议,与串口通信不同,串口通信一般用于板件通信, UART的发送接受时间受到单片机晶振你的严格控制。i²c总线多用于板上读取写入信息,常见于读取传感器采集的信息之类;
适配与i²c总线的器件有很多,这里用EEPROM来举例说明
2.i²c总线简介
I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL;
i²c总线的数据传输:
早SCL高电平时要求数据稳定,在低电平时可以发生变化
i²c总线的数据传输要求
i²c总线的起始信号和中止
i²c总线的起始信号
起始信号和终止信号一般由单片机主机发出,若主机上挂在了i²c总线协议的器件,则能轻易识别出该信号
时序图
对应时间
//i2c起始信号
SCL=1;
SDA=1;
delay1ms(); //起始信号建立时间
SDA=0;
delay1ms();//起始信号保持时间
SCL=0;//拉低为下一次准备
//i2c终止信号
SCL=1;
SDA=0;
delay1ms();//停止信号建立时间
SDA=1;
delay1ms();//新的发送开始前总线的空闲时间
字节的传送与应答
每一个字节必须保证时8位,数据传送时先发送最高位
第9位位应答位,若为应答为,则SDA被置为,若无应答,则SDA为高电平
单片机进行写操作时,首先发送该器件的7位地址码和写方向位“0”(共8位,即一个字节),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为相应,单片机收到应答后就可以传送数据了。
字节的传送
读操做
单片机先发送该器件的7位地址码和写方向位“0”(“伪写”),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为回应。
然后,再发一个字节的要读出器件的存储区的首地址,收到应答后,单片机要重复一次起始信号并发出器件地址和读方向位(“1”),收到器件应答后就可以读出数据字节,每读出一个字节,单片机都要回复应答信号。当最后一个字节数据读完后,单片机应返回以“非应答”(高电平),并发出终止信号以结束读出操作。
读操作
//写一个字节的数据
int I,a;
for(i=0;i<8;i++)
{
SDA=dat>>7;//先发送最高位 1100 0011
dat<<1;//次高位为做高位
SCL=1;//拉高,发送数据
delay1ms();//时钟高电平周期
}
while(SDA)
{
a++;
if(a>500)
{
a=0;
SCL=0;
return -1;
}
}
SCL=0;
delay1ms();//为下次做准备
//读一个字节的数据
int i;
char dat,num=0;
SCL=0;
delay1ms();
for(i=7;i>=0;i--)
{
SCL=1;
delay1ms();
dat=SDA;
dat>>i;//dat 中的最高位移到最后一位
num|=dat;
SCL=0;
delay1ms();
//缺少应答
}
实现用数码管显示AT24C02的所存功能:
任务:当使用独立按键K1,单片机向ATC02写入数据; 使用独立按键K2, 单片机读取AT24C02的数据;3.使用独立按键K3,数码管显示数据加1;4使用独立按键K4,数码管清零
程序
//main 函数
#include <reg51.h>
#include "EEPROM.H"
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;//74h138段选
sbit K1= P3^1;
sbit K2= P3^0;
sbit K3= P3^2;
sbit K4= P3^3;
char ch[]={};//显示字符
char keyfun(char dat);
void shumaguan();
int main()
{
char dat;
while(1)
{
dat=keyfun();//返回dat
shumaguan(dat);//调用数码管函数
}
return 0;
}
char keyfun(char dat)
{
if(K1==0)
{
delay5ms();
if(K1==0)
{
ATwrite(dat);
}
if(K2==0)
{
read(0x00,dat);
}
if(K3==0)
{
dat++;
}
if(K4=0)
{
dat=0;
}
return dat;
}
void shumaguan()
{
int i,j,k,a=0;
P0=0x00;//消隐
i= dat/100;//百位
j= dat%100/10;// 十位
k= dat%100%10;//个位
while()
{
switch(a++)
{
case[0]:LSA=0;LSB=0;LSC=0;P0=ch[i],delay1ms();break;
case[1]:LSA=1;LSB=0;LSC=0;P0=ch[j];delay1ms();break;
case[2]:LSA=0;LSB=1;LSC=0;P0=ch[k]; delay1ms(); break;
default: a=0;break;
}
}
}
\\AT24C02程序
void delay1ms()//延时程序
{
}
void IICStart()
{
SCL=1;
SDA=1;
delay1ms(); //起始信号建立时间
SDA=0;
delay1ms();//起始信号保持时间
SCL=0;//拉低为下一次准备
}
void IICStop()
{
SCL=1;
SDA=0;
delay1ms();//停止信号建立时间
SDA=1;
delay1ms();//新的发送开始前总线的空闲时间
}
void IICSendbyte(dat)
{
int i;
for(i=0;i<8;i++)
{
SDA=dat>>7;//先发送最高位 1100 0011
dat<<1;//次高位为做高位
SCL=1;//拉高,发送数据
delay1ms();//时钟高电平周期
SCL=0;//拉低为下次准备
delay1ms();//时钟低电平周期
}
while(SDA)
{
a++;
if(a>500)
{
a=0;
SCL=0;
return -1;
}
}
SCL=0;
a=0;
}
}
void IICReadbyte()
{
int i;
char dat,num=0;
SCL=0;
delay1ms();
for(i=7;i>=0;i--)
{
SCL=1;
delay1ms();
dat=SDA;
dat>>i;//dat 中的最高位移到最后一位
num|=dat;
SCL=0;
delay1ms()
}
while(SDA)
{
a++;
if(a>500)
{
a=0;
SCL=0;
return -1;
}
}
SCL=0;
a=0;
return 0;
}
void AT24C02Write()
{
IICStart();
IICSendbyte(0x00);//器件地址和写
IICSendbyte(dat);
IICStop();
}
char AT24C02Read(char addr,char dat)
{
IICStart();
IICSendbyte(0x00);//器件地址和写
IICSendbyte(addr);//读取AT24C02首地址
IICStart();
IICSendbyte(0x01);
dat=IICReadbyte();
IICStop();
}
//增加IIC.h
void delay1ms();
void AT24C02Write();
char AT24C02Read(char addr,char dat);
网友评论