工程名称: IIC
功能描述: 每按下一次复位键或重新给系统上电,发光二极管表示的数据加1,实现记录开机次数。
硬件连接: 用8位杜邦线将J8与J13连接,2位杜邦线分别将J11_7与J17_SDA、J11_6与J17_SCL连接
维护记录: 2011-8-22
***************************************************************************************************/
#include "reg51.h" //包含头文件
#include"intrins.h" //_nop_();延时函数用
***it sda=P2^7; //数据线
***it scl=P2^6; //时钟线
#define uchar unsigned char
#define uint unsigned int
//**************************************************************************************************
//延时
//**************************************************************************************************
delay(uint time) //int型数据为16位,所以最大值为65535
{
uint i,j; //定义变量i,j,用于循环语句
for(i=0;i
for(j=0;j<50;j++); //for循环,循环50次
}
//**************************************************************************************************
//启动(SCL为高,SDA由高变为低是一个开始条件)
//**************************************************************************************************
void start()
{
sda=1; //数据线置高,
_nop_(); //延时
scl=1; //时钟线置高
_nop_(); //延时
sda=0; //数据线置低,由高变低
_nop_(); //延时
scl=0; //时钟线置低,准备发送或接收数据,总线进入忙状态(I2C总线在空闲状态时,SDA与SCL均被置高)
_nop_(); //延时
}
//**************************************************************************************************
//停止(SCL为高,SDA由低变为高是一个结束条件)
//**************************************************************************************************
void stop()
{
sda=0; //数据线置低
_nop_(); //延时
scl=1; //时钟线置高
_nop_(); //延时
sda=1; //数据线置高,由低变高
_nop_(); //延时
}
//**************************************************************************************************
//检测应答(所有的地址和数据字都是以8bit,在第9个时钟周期,从器件发出"0"信号来作为收到一个字的应答信号)
//**************************************************************************************************
void checkACK() //主器件检测从器件是否返回应答
{
scl=1; //时钟线置高
_nop_(); //延时
while(sda==1); //等待第9个时钟周期器件发出的响应信号"0"
scl=0; //时钟线置低
_nop_(); //延时
}
//**************************************************************************************************
//发送应答(发送方为主器件,接收方为从器件,控制器作为从器件接收完1数据时,发送应答信号
//**************************************************************************************************
void sendACK(bit ACK)
{
if(ACK)sda=1; //如果i位为1则发送1,即发送"非应答信号"
else sda=0; //如果i位为0则发送0,即发送"应答信号"
scl=1; //时钟线置高,给一个脉冲
_nop_(); //延时
scl=0; //时钟线置低
_nop_(); //延时
}
//**************************************************************************************************
//写一字节
//**************************************************************************************************
void send_byte(uchar date) //写一个8位字
{
uchar i,temp; //定义局部变量
temp=date; //待发8位数据赋予temp
for(i=0;i<8;i++) //循环8次,每次写入1位,从最高位开始发送
{
if(temp&0x80)sda=1; //如果temp最高位为1则发送1
else sda=0; //如果temp最高位为0则发送0
_nop_(); //延时
scl=1; //给一个脉冲,发送sda当前这位数据
_nop_(); //延时,需大于4us(参考数据手册时序图)
_nop_();
_nop_();
_nop_();
_nop_();
scl=0; //时钟线置低,准备下一脉冲
_nop_(); //延时,需大于4.7us(参考数据手册时序图)
_nop_();
_nop_();
_nop_();
_nop_();
temp=temp<<1; //左移1位,准备好下1位待发送的数据
}
checkACK(); //查询是否返回应答信号
}
//**************************************************************************************************
//读一字节
//**************************************************************************************************
uchar receive_byte() //读一个8位字
{
uchar i,temp; //定义局部变量
sda=1; //设置数据线为输入
_nop_(); //延时
for(i=0;i<8;i++) //循环8次,每次读取1位,从最高位开始接收
{
scl=1; //给一脉冲,准备发送1位数据
_nop_(); //延时,需大于4us(参考数据手册时序图)
_nop_();
_nop_();
_nop_();
_nop_();
temp=(temp<<1)|sda; //读取1位数据,放在temp最低位
scl=0; //准备给下1个脉冲
_nop_(); //延时,需大于4.7us(参考数据手册时序图)
_nop_();
_nop_();
_nop_();
_nop_();
}
return temp; //返回读取的8位数据
}
//**************************************************************************************************
//向某I2C器件的某字地址写一字节数据
//**************************************************************************************************
void write_word(uchar device_add,uchar word_add,uchar date) //写进去一个存储数据
{
start(); //启动
send_byte(device_add); //选择从器件地址,RW位为0,即选择写命令
send_byte(word_add); //写字地址
send_byte(date); //写数据
stop(); //停止
}
//**************************************************************************************************
//向某I2C器件的某字地址读一字节数据
//**************************************************************************************************
uchar read_word(uchar device_add,uchar word_add) //读出一个存储的数据
{
uchar date;
start(); //启动
send_byte(device_add); //选择从器件地址,RW位为0,即选择写命令
send_byte(word_add); //写字地址
start(); //启动
send_byte(device_add+1); //选择从器件地址,RW位为1,即选择读命令
date=receive_byte(); //读数据
sendACK(1); //发送非应答信号
stop(); //停止
return date; //返回读取结果数据
}
//**************************************************************************************************
//主函数
//**************************************************************************************************
void main()
{
uchar temp; //定义中间变量
temp=read_word(0xa0,0); //从I2C器件a0的第0个地址读出数据赋予temp
write_word(0xa0,0,temp+1); //向I2C器件a0的第0个地址写etmp+1
delay(100); //延时
while(1) //死循环
{
temp=read_word(0xa0,0); //从第0个地址读出一个数据
delay(100); //延时
P1=~temp; //送数据到P1口显示
}
} |