IIC总线协议
II2C C总线的简单的概述
1.( 总线(Inter Integrated Circuit Bus Inter Integrated Circuit Bus):是 ):是Philips Philips公司 公司 推出的串行总线标准(为二线制)。总线上扩展的外围器件及外设接 推出的串行总线标准(为二线制)。
2.总线上扩展的外围器件及外设接 口通过总线寻址,是具备总线仲裁和高低速设备同步等功能的高性能 口通过总线寻址,是具备总线仲裁和高低速设备同步等功能的高性能 多主机总线。
3.特点:组成系统结构简单,占用空间小,芯片管脚的数量少,无需片 选信号,价格低。允许若干兼容器件共享总线,应用比较广泛。总线 选信号,价格低。允许若干兼容器件共享总线,应用比较广泛。总线 的长度可达 的长度可达7.6m 7.6m,传送速度可达 ,传送速度可达400kbps 400kbps,标准速率为 ,标准速率为 100kbps 100kbps。支持多个组件。支持多主控器件(某时刻只能有一个主 。支持多个组件。支持多主控器件(某时刻只能有一个主 控器件),
这是一种比较常用的总线协议,简单,易动。如下图所示:
在单片机芯片的传输系统中,和很多的外围器件的信息传输用的往往都是IIC,目前我所接触的C52单片机芯片主要用的都是这个,EEROM存储,A/D转换,之类都是。
IIC协议(状态规定)
(1).IIC总线其实说的再多也就是两根线而已,SDA(数据传输线)和SCL(时钟信号线),利用两种的线的不同状态去表示信息传送的时候的一些关系,对了忘了说了IIC总线是半双工的,就是双向传送不能同时的。
(2).在学习IIC时,要明白一个概念,那就是主设备,和从设备。此时就会有两种状态,主发从收,主收从发。其实如果反过来理解也就是一种状态。在设备发送一个信息的时候就是主设备,反之就是从设备。
(3).在上面的(1),讲过两种线的不同状态去表示传送中的关系,总结一下就以下几种:
a. 开始信号:这个是IIC使用时,第一个必须发的信号状态,在SCL为高电平的时候,SDA从低电平上升到高电平,同时上升后保持5us以上(单片机中就是使用_nop_()4个以上,其实你也可以自己去算一下,但是个人觉得没有必要,除非你的很严格)。
b.结束信号:在SCL是高电平的同时,SDA一开始也是高电平,将SDA=0,保持的时间和上面的一样,最后注意将SCL拉低。
c.应答信号:在每次信息传输结束后,都要有主设备将SDA=1,保持一段时间以后(和上面一样),从设备拉低SDA,则表示信息已经接收到了;如果从设备不在接收信息了,一定不要给出SDA=0;给出SDA=1,我测试过,这个必须做。
控制字
由于图片原因不要介意,这个就是IIC总线的控制字的规定。
前四位就是确定使用的是那个设备,EEROM还是A/D,或者别的,这个所谓器件类型识别符,网上都可以搜到,后面的器件片选信号就是设备本身的A2.A1.A0的值,就是硬件地址,我使用的时候一般接地了。最后一位就是判定传输的方向到底是发送还是接收,发送0,接收1.。这个就是比较容易弄了,大家记住就行了。
实际的传输方向和总结:
我目前用过的就是A/D和EEROM,这个两种,所以我就这个两种给大家做一下总结:
A/D(接收):
start信号---------》 发送地址-----------》 发送控制字------------》 start信号 ------------》 发送地址 ----------》 receive 数据----------》 给出不应答的信号就是(SDA=1)-------》stop信号(结束);
EEROM (接收)
start信号---------》发送发送数据控制字------------》 发送地址 ----------》start信号 ------------》发送接收数据的控制字------------》 receive 数据------------》stop信号(结束);
我目前编程的顺序就是这样,给大家做一个思路上的参考;
代码:
这是关于的A/D的输出控制电压转化的数字信号,输出在一排发光二极管显示的代码,仅供参考。
#include <reg52.h>
#include <intrins.h>
#define nops() do {_nop_();_nop_();_nop_();_nop_();}while(0);
unsigned char LSAVE=0x90;
sbit SDA=P2^0;
sbit SCL=P2^1;
sbit DS1302 = P2^4;
sbit WE=P2^7;
sbit DU=P2^6;//¹²ÒõLED
//º¯ÊýÉùÃ÷
bit ACK();
void doACK(bit b);
void LEDstart();
void LEDend();
unsigned char Recieve();
void Senddata(unsigned char y);
void doACK(bit b){
if(b){
SDA=0;
SCL=1;
nops();
}
else
{ SDA=1;
SCL=1;
nops();
}
SCL=0;
}
bit ACK(){
SCL=1;
SDA=1;
nops();
if(SDA)
{
SCL=0;
LEDend();
return 1;
}
else{
SCL=0;
return 0;
}
}
void LEDstart(){
SDA=1;
SCL=1;
nops();
SDA=0;
nops();
SCL=0;
}
void LEDend(){
SDA=0;
SCL=1;
nops();
SDA=1;
nops();
SDA=0;
}
unsigned char Recieve(){
unsigned char i,dee;
dee=0x00;
for(i=0;i<8;i++){
dee<<=1;
dee|=(unsigned char)SDA;
SCL=1;
nops();
SCL=0;
}
return dee;
}
void Senddata(unsigned char y){
unsigned char i;
for(i=0;i<8;i++){
if (y & 0x80)
SDA = 1;
else
SDA = 0;
SCL=1;
y<<=1;
nops();
SCL=0;
}
}
bit ADdata(unsigned char com,unsigned char *dat){
unsigned char dee;
LEDstart();
Senddata(LSAVE);
if(ACK())
return 1;
Senddata(com);
if(ACK())
return 1;
LEDstart();
Senddata(LSAVE+1);
if(ACK())
return 1;
dee=Recieve();
doACK(0);//±ØÐëÒª²»¸ø»ØÓ¦
LEDend();
nops();
*dat=dee;
}
void Serial(){//´®¿ÚͨÐÅËùÐèµÄ¼Ä´æÆ÷
SCON=0x50;
PCON=0x00;
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
TR1=1;
}
void send(unsigned char ans){//·¢ËÍÐÅÏ¢
SBUF=ans;
while(TI==0);
TI=0;
}
void main(){
unsigned char i=0;
unsigned char ans=0;
//Serial();
DS1302 = 0;
while(1){
i=ans;//¼ÇסansÖµ×öÅжÏ
ADdata(0x42,&ans);//»ñµÃеÄansÖµ
if(i!=ans)//Èç¹ûansÖµ¸Ä±äʱ²ÅÄܸıäP1µÄÖµ
P1=ans;
}
}
(有编码错误请原谅)
作者辛勤劳动,如有转载请标明出处,尊重劳动,人人有责。(标明我的博客ID+网址就行了);欢迎大家挑刺!!!