|
采用STC89C52芯片,12MHZ晶振。
欢迎大家交流,并提出意见。
程序:
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit we=P2^7; //数码管位选
sbit du=P2^6; //数码管段选
sbit scl=P2^1; //scl
sbit sda=P2^0; //sda
uchar n; //定义读取AT24C02里面的数据
/*共阴极数码管段选信号和位选信号*/
uchar code table[ ]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //数字0-9段选码
uchar code smgwe[ ]={0xfe,0xfd,0xfb}; //位选码
/*毫秒级延时函数*/
void delay(uint z)
{
uint x,y;
for(x=100;x>0;x--)
for(y=z;y>0;y--);
}
/*数码管显示*/
void display(uchar n)
{
while(1)
{
P0 = 0xff; // 清除断码
we = 1;//打开位选
P0 =smgwe[0] ;//1111 1110 只选通第一位数码管
we = 0; //关闭位选
du = 1; //打开段选
P0 = table[n/100]; //显示百位
du = 0; //关闭段选
delay(5);//延时5毫秒
P0 = 0xff; // 清除断码
we = 1; //打开位选
P0 =smgwe[1] ;//1111 1101 只选通第二位数码管
we = 0; //关闭位选
du = 1;//打开段选
P0 = table[(n/10)%10]; //显示十位
du = 0; //关闭段选
delay(5);//延时5毫秒
P0 = 0xff; // 清除断码
we = 1; //打开位选
P0 = smgwe[2];//1111 1011 只选通第二位数码管
we = 0; //关闭位选
du = 1;//打开段选
P0 = table[n%10]; //显示个位
du = 0; //关闭段选
delay(5);//延时5毫秒
}
}
/*5微秒延时函数*/
void delay5us()
{
_nop_();
}
/*IIC开始信号*/
void I2cstart()
{
scl=1;
_nop_(); //延时一个机器周期稳定一下
sda=1;
delay5us();
sda=0;
delay5us();
}
/*IIC停止信号*/
void I2cstop()
{
sda=0;
_nop_();
scl=1;
delay5us();
sda=1;
delay5us();
}
/*检测从机应答*/
bit readback()
{
//scl=0;
scl=1;
delay5us();
if(sda)//非应答
{
scl=0;//拉低时钟总线
_nop_();
//sda=0;
return(0); //非应答,返回0
}
else //应答
{
scl=0;//拉低时钟总线,以便后面数据传输,SCl为低,允许SDA数据变化
_nop_();
return(1);//应答,返回1
}
}
/*主机发送应答和非应答*/
void sendback(bit i)
{
scl=0; //拉低时钟总线允许SDA数据总线上的数据变化
_nop_();// 让总线稳定
if(i)
sda=0;
else
sda=1;
_nop_(); //让sda稳定一下
scl=1; //拉高时钟总线,让从机从SDA上读取数据
delay5us();
scl=0; //拉低时钟总线, 占用总线继续通信,因为scl为低,sda才可以变化,才可以发送数据
//如果scl为高,sda就不能变化,一变化就成了开始和停止信号了
_nop_(); //稳定延时一下
sda=1; //释放sda数据总线
_nop_(); //稳定延时一下
}
/*发送一个字节*/
void I2csendbite(uchar m)
{
uchar i;
for(i=0;i<8;i++)
{
scl=0;
_nop_();
if(m&0x80)//如果最高为为1
{
sda=1; //sda置1,即发送数据1
_nop_();
}
else
{
sda=0; //sda为0,发送数据0
_nop_();
}
scl=1;//scl置1,从机可以读取总线sda上的数据
_nop_();
m=m<<1; //左移一位,于是传输一字节数据中的下一位数据
}
scl=0; //拉低时钟总线, 使总线继续通信
_nop_();
sda=1; //释放SDA数据总线。
_nop_();
}
/*I2C 读一字节*/
uchar I2creadbite()
{
uchar i,DAT;
// bit a;
scl = 0;
_nop_();
sda= 1;
_nop_();
for(i=0;i<8;i++)
{
scl = 1;
_nop_();
if (sda)
{
DAT |= 0x01; //
}
else
{
DAT &= 0xfe; //1111 1110
}
_nop_();
scl = 0 ;
_nop_();
if(i < 7)
{
DAT = DAT << 1;
}
}
return(DAT);
}
bit I2c24c02write(uchar ADDR, DAT)
{
I2cstart();
I2csendbite(0xa0+0); //器件地址+0,表示写
if( !readback( ))
{
return(0);
}
I2csendbite(ADDR); //从哪个地址写入数据
if( !readback( ))
{
return(0);
}
I2csendbite(DAT);
if( !readback( ))
{
return(0);
}
I2cstop();
return(1);
}
uchar I2c24c02read(uchar ADDR)
{
uchar DAT;
I2cstart();
I2csendbite(0xa0+0);//I2c发送一个字节
if( !readback( ))
{
return(0);
}
I2csendbite(ADDR); //从哪个存储单元读取数据,例如AT24C02的话,有256个字节存储单元(256*8=2048位。)ADDR可以是0-255之间的数。
//如果是PCF8591的话,ADDR就是控制字,控制字假如为0000 0010.则读取通道2上的模拟量转化为的数字量。
sendback(0);
I2cstart();
I2csendbite(0xa0+1);
if( !readback( ))
{
return(0);
}
DAT=I2creadbite();
sendback(0);//发送一个非应答
I2cstop();
return(DAT);
}
void main()
{
I2cstart();
I2c24c02write(3, 122);
delay(100);//等从机处理好
n=I2c24c02read(3);
display(n);
}
|
评分
-
查看全部评分
|