51单片机普通IO口模拟IIC总线的程序实现
2014-05-16 15:02
525 查看
http://blog.csdn.net/sdwuyulunbi/article/details/6654469
IIC是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA)。
IIC是总线结构,1个Master,1个或多个Slave,各Slave设备以7位地址区分,地址后面再跟1位读写位,表示读(=1)或者写(=0),所以我们有时也可看到8位形式的设备地址,此时每个设备有读、写两个地址,高7位地址其实是相同的。
IIC数据格式如下:
无数据:SCL=1,SDA=1;
开始位(Start):当SCL=1时,SDA由1向0跳变;
停止位(Stop):当SCL=1时,SDA由0向1跳变;
数据位:当SCL由0向1跳变时,由发送方控制SDA,此时SDA为有效数据,不可随意改变SDA;
当SCL保持为0时,SDA上的数据可随意改变;
地址位:定义同数据位,但只由Master发给Slave;
应答位(ACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=0;
否应答位(NACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=1。
当数据为单字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,停止位。
当数据为一串字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,8位数据,应答,……,8位数据,应答,停止位。
需要注意的是:
1、SCL一直由Master控制,SDA依照数据传送的方向,读数据时由Slave控制SDA,写数据时由Master控制SDA。当8位数据传送完毕之后,应答位或者否应答位的SDA控制权与数据位传送时相反。
2、开始位“Start”和停止位“Stop”,只能由Master来发出。
3、地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”。
4、当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”,Slave设备如果没有空间接受更多的字节应该回答“NACK”,Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”。
5、当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
6、当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生“线与”)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。
下面是本人编写的单片机普通IO口模拟IIC总线的程序源代码:
[cpp] view
plaincopy
/*
************************************************************************************
Fuction:GPIO模拟iic bus,实现与AT24C02的数据通信
PS:该源代码是以STC89C52为平台编写的,可通过修改包含的头文件以适用于所有51系列单片机
SD:Jason
************************************************************************************
*/
#include <reg52.h>
#include <string.h>
sbit sda = P2^0;
sbit scl = P2^1;
unsigned char table1[11]={0,1,2,3,4,5,6,7,8,9};
unsigned char table2[11];
void init();
void somenop();
void delay(unsigned char);
void start();
void stop();
void send_ack(unsigned char);
unsigned char rec_ack();
void write_byte(unsigned char);
unsigned char read_byte();
unsigned char write_add(unsigned char,unsigned char *,unsigned char);
unsigned char read_add(unsigned char,unsigned char *,unsigned char);
void main()
{
init();
write_add(0x10,table1,10);
delay(100);
read_add(0x10,table2,10);
while(1);
}
//端口初始化
void init()
{
memset(table2,0,sizeof(table2));
sda = 1;
scl = 1;
somenop();
}
//起始信号
void start()
{
sda = 1;
somenop();
scl = 1;
somenop();
sda = 0;
somenop();
}
//终止信号
void stop()
{
sda = 0;
somenop();
scl = 1;
somenop();
sda = 1;
somenop();
}
//主机发送应答信号
void send_ack(unsigned char ack)
{
scl = 0;
somenop();
sda = ack;
somenop();
scl = 1;
somenop();
scl = 0;
somenop();
sda = 1;
somenop();
}
//主机接收应答信号
unsigned char rec_ack()
{
scl = 1;
somenop();
if(sda == 1)
{
scl = 0;
delay(1);
scl = 1;
if(sda == 1)
return 1;
}
else
return 0;
}
//写一个字节
void write_byte(unsigned char dat)
{
unsigned char i,a;
a = dat;
for(i=0;i<8;i++)
{
a = a<<1;
scl = 0;
somenop();
sda = CY;
somenop();
scl = 1;
somenop();
}
scl = 0;
somenop();
sda = 1;
somenop();
}
//读一个字节
unsigned char read_byte()
{
unsigned char i,a;
scl = 0;
somenop();
sda = 1;
somenop();
for(i=0;i<8;i++)
{
scl = 1;
somenop();
a = (a<<1)|sda;
scl = 0;
somenop();
}
return a;
}
//向add地址写入len长度的dat数据
unsigned char write_add(unsigned char add,unsigned char *dat,unsigned char len)
{
unsigned char flag,i;
start();
write_byte(0xa0);
if(rec_ack() == 0)
{
write_byte(add);
if(rec_ack() == 0)
{
for(i=0;i<len;i++)
{
write_byte(dat[i]);
if(rec_ack() == 1)
{
i = 0;
break;
}
}
if(i == len)
flag = 1;
}
}
stop();
return flag;
}
//从add地址读出len长度的数据给dat
unsigned char read_add(unsigned char add,unsigned char *dat,unsigned char len)
{
unsigned char flag,i;
start();
write_byte(0xa0);
if(rec_ack() == 0)
{
write_byte(add);
if(rec_ack() == 0)
{
start();
write_byte(0xa1);
if(rec_ack() == 0)
{
for(i=0;i<len;i++)
{
dat[i] = read_byte();
send_ack(0);
}
flag = 1;
send_ack(1);
somenop();
}
}
}
stop();
return flag;
}
//delay 5us
void somenop()
{;;}
//delay x ms
void delay(unsigned char x)
{
unsigned char y,z;
for(y=x;y>0;y--)
for(z=110;z>0;z--);
}
IIC是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA)。
IIC是总线结构,1个Master,1个或多个Slave,各Slave设备以7位地址区分,地址后面再跟1位读写位,表示读(=1)或者写(=0),所以我们有时也可看到8位形式的设备地址,此时每个设备有读、写两个地址,高7位地址其实是相同的。
IIC数据格式如下:
无数据:SCL=1,SDA=1;
开始位(Start):当SCL=1时,SDA由1向0跳变;
停止位(Stop):当SCL=1时,SDA由0向1跳变;
数据位:当SCL由0向1跳变时,由发送方控制SDA,此时SDA为有效数据,不可随意改变SDA;
当SCL保持为0时,SDA上的数据可随意改变;
地址位:定义同数据位,但只由Master发给Slave;
应答位(ACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=0;
否应答位(NACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=1。
当数据为单字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,停止位。
当数据为一串字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,8位数据,应答,……,8位数据,应答,停止位。
需要注意的是:
1、SCL一直由Master控制,SDA依照数据传送的方向,读数据时由Slave控制SDA,写数据时由Master控制SDA。当8位数据传送完毕之后,应答位或者否应答位的SDA控制权与数据位传送时相反。
2、开始位“Start”和停止位“Stop”,只能由Master来发出。
3、地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”。
4、当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”,Slave设备如果没有空间接受更多的字节应该回答“NACK”,Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”。
5、当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
6、当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生“线与”)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。
下面是本人编写的单片机普通IO口模拟IIC总线的程序源代码:
[cpp] view
plaincopy
/*
************************************************************************************
Fuction:GPIO模拟iic bus,实现与AT24C02的数据通信
PS:该源代码是以STC89C52为平台编写的,可通过修改包含的头文件以适用于所有51系列单片机
SD:Jason
************************************************************************************
*/
#include <reg52.h>
#include <string.h>
sbit sda = P2^0;
sbit scl = P2^1;
unsigned char table1[11]={0,1,2,3,4,5,6,7,8,9};
unsigned char table2[11];
void init();
void somenop();
void delay(unsigned char);
void start();
void stop();
void send_ack(unsigned char);
unsigned char rec_ack();
void write_byte(unsigned char);
unsigned char read_byte();
unsigned char write_add(unsigned char,unsigned char *,unsigned char);
unsigned char read_add(unsigned char,unsigned char *,unsigned char);
void main()
{
init();
write_add(0x10,table1,10);
delay(100);
read_add(0x10,table2,10);
while(1);
}
//端口初始化
void init()
{
memset(table2,0,sizeof(table2));
sda = 1;
scl = 1;
somenop();
}
//起始信号
void start()
{
sda = 1;
somenop();
scl = 1;
somenop();
sda = 0;
somenop();
}
//终止信号
void stop()
{
sda = 0;
somenop();
scl = 1;
somenop();
sda = 1;
somenop();
}
//主机发送应答信号
void send_ack(unsigned char ack)
{
scl = 0;
somenop();
sda = ack;
somenop();
scl = 1;
somenop();
scl = 0;
somenop();
sda = 1;
somenop();
}
//主机接收应答信号
unsigned char rec_ack()
{
scl = 1;
somenop();
if(sda == 1)
{
scl = 0;
delay(1);
scl = 1;
if(sda == 1)
return 1;
}
else
return 0;
}
//写一个字节
void write_byte(unsigned char dat)
{
unsigned char i,a;
a = dat;
for(i=0;i<8;i++)
{
a = a<<1;
scl = 0;
somenop();
sda = CY;
somenop();
scl = 1;
somenop();
}
scl = 0;
somenop();
sda = 1;
somenop();
}
//读一个字节
unsigned char read_byte()
{
unsigned char i,a;
scl = 0;
somenop();
sda = 1;
somenop();
for(i=0;i<8;i++)
{
scl = 1;
somenop();
a = (a<<1)|sda;
scl = 0;
somenop();
}
return a;
}
//向add地址写入len长度的dat数据
unsigned char write_add(unsigned char add,unsigned char *dat,unsigned char len)
{
unsigned char flag,i;
start();
write_byte(0xa0);
if(rec_ack() == 0)
{
write_byte(add);
if(rec_ack() == 0)
{
for(i=0;i<len;i++)
{
write_byte(dat[i]);
if(rec_ack() == 1)
{
i = 0;
break;
}
}
if(i == len)
flag = 1;
}
}
stop();
return flag;
}
//从add地址读出len长度的数据给dat
unsigned char read_add(unsigned char add,unsigned char *dat,unsigned char len)
{
unsigned char flag,i;
start();
write_byte(0xa0);
if(rec_ack() == 0)
{
write_byte(add);
if(rec_ack() == 0)
{
start();
write_byte(0xa1);
if(rec_ack() == 0)
{
for(i=0;i<len;i++)
{
dat[i] = read_byte();
send_ack(0);
}
flag = 1;
send_ack(1);
somenop();
}
}
}
stop();
return flag;
}
//delay 5us
void somenop()
{;;}
//delay x ms
void delay(unsigned char x)
{
unsigned char y,z;
for(y=x;y>0;y--)
for(z=110;z>0;z--);
}
相关文章推荐
- 51单片机普通IO口模拟IIC总线的程序实现
- 51单片机普通IO口模拟IIC总线的程序实
- 基于51单片机实现模拟IIC总线时序
- 基于51单片机实现模拟IIC总线时序
- 基于51单片机实现模拟IIC总线时序
- 模拟IIC总线汇编程序软件包
- 00025-----GPIO模拟IIC总线程序
- 普通IO口模拟实现I2C通信及应用解析
- 关于温湿度SHT20传感器,用普通GPIO口来模拟IIC实现驱动
- gec210 i2c程序io模拟方式实现
- TX2平台下can总线收发功能的实现(三)——发送队列异步io接收程序
- 学习笔记——51通过IO口模拟IIC实现AT24C02的读写
- 00025-----GPIO模拟IIC总线程序
- 普通IO口模拟实现SPI通信及应用解析
- PB程序中在普通激光打印机上实现条码打印
- 用程序来模拟Alt+PrtSc的键盘事件,实现截屏功能
- IO服用实现linux socket聊天程序(select)
- 实现邮储柜台模拟程序杂感(一)
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于WS-MEX的实现](提供模拟程序)
- QQ 静态截图程序模拟实现