IIC总线
//程序
#include <REG51.h>
#include <intrins.h>
#define uc unsigned char
uc a;
//IIC总线串行数据线
sbit SDA=P1^0;
//IIC总线串行时钟线
sbit SCL=P1^1;
sbit AS=P1^2;
sbit AB=P1^3;
bit NackFlag;
//延时子程序,大约延时5us
void delay()
{
_nop_();
_nop_();
_nop_();
_nop_();
}
//延时子程序,延时大约count ms
void DelayX1ms(uc count)
{
uc i,j;
for(i=0;i<count;i++)
{
for(j=0;j<120;j++);
}
}
//启动IIC总线
void start(void)
{
SDA=1;
SCL=1;
delay();
SDA=0;
delay();
SCL=0;
}
//停止IIC总线
void stop(void)
{
SDA=0;
SCL=1;
delay();
SDA=1;
delay();
SCL=0;
}
//检查应答位子函数
void chkAck(void)
{
SDA=1;
SCL=1;
NackFlag=0;
if(SDA==1) //SDA==1表示器件没有应答
NackFlag=1; //置位非应答标志NackFlag
SCL=0;
}
//发送8bit(1字节)数据子函数
void send8bit(uc num)
{
uc i=8;
uc temp;
temp=num;
for(i=8;i>0;i--) //根据IIC协议应从最高位开始发
{
SDA=temp&0x80;
SCL=1;
delay();
SDA=temp&0x80;
SCL=1;
delay();
SCL=0;
temp=temp<<1; //待发数据左移,准备发送下一位
}
}
//发送1字节数据到从器件子程序
void sendbyte(uc num,uc addr,uc N)
{
//启动IIC总线
start();
//发送从器件地址
send8bit(N);
//检查应答位,每发送一字节都要检查应答位
chkAck();
//发送数据地址
send8bit(addr);
chkAck();
//发送待发数据
send8bit(num);
chkAck();
stop();
//全部发送完毕后停止
DelayX1ms(10);
}
unsigned char IIC_read_byte()
{//从IIC总线读取一个字节的数据函数
uc i;
uc Data; //定义一个缓冲寄存器。
for(i=0;i<8;i++)//有8位数据
{
SCL=1;//拉高时钟线,为读取下一位数据做准备。
delay();
Data=Data<<1;//将缓冲字节的数据左移一位,准备读取数据。
delay();
if(SDA)//如果数据线为高平电平。
Data=Data|0x1;//则给缓冲字节的最低位写1。
SCL=0;//拉低时钟线,为读取下一位数据做准备。
delay();
}
return Data;//返回读取的一个字节数据。
}
uc IIC_single_byte_read(uc Daddr,uc Waddr)
{//从任意地址读取一个字节数据函数
uc Data;//定义一个缓冲寄存器。
start();//产生起始信号
send8bit(Daddr);//写入设备地址(写)
chkAck();//等待设备的应答
send8bit(Waddr);//写入要操作的单元地址。
chkAck();//等待设备的应答。
start();//产生起始信号
send8bit(Daddr+1);//写入设备地址(读)。之所以加1,见24c02资料,最后一位为R/(/w),从24c02读,最后一位为1;向24c02写,最后一位为0
chkAck();//等待设备的应答。
Data=IIC_read_byte();//写入数据。
stop();//产生停止符号。
//-------------------返回读取的数据--------------------
return Data;//返回读取的一个字节数据。
}
//初始化串口
void serial_port_initial()//
{
PCON=0x00; //波特率bu加倍
SCON = 0x50; //0101,0000 8位可变波特率,无奇偶校验位
TMOD = 0x20; //0011,0001 设置定时器1为8位自动重装计数器
TH1 = 0xfd; //设置定时器1自动重装数 9600bps@11.0592MHz
TL1 = 0xfd;
ES = 0; //串口中断关闭
ET1 = 0; //定时器1中断关闭
TR1 = 1; //打开串口
EA = 0; //关总中断
}
//主函数,实现IIC总线的数据发送
void main(void)
{
unsigned char i,Da,d=0xff;
serial_port_initial();//初始化串口
//按要求产生并循环发送所有待发送的数据
for(i=0;i<0xff;i++)
{
//向从器件发送一字节数据
sendbyte(0xff,i,0xae);
DelayX1ms(5);
}
//按要求产生并循环发送所有待发送的数据
for(i=0;i<0xff;i++)
{
//向从器件发送一字节数据
sendbyte(0x05,i,0xa0);
DelayX1ms(5);
}
for(i=0;i<0xff;i++)
{
Da=IIC_single_byte_read(0xa0 , i);
SBUF=Da;
if((Da&0x01)!=0x01)
AS=1;
else
AS=0;
}
while(1)
{;}//发送完毕,停止等待
}