|
采用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);
}
|
評分
-
查看全部評分
|