赞
踩
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
数据传送格式
字节传送与应答
每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。
数据帧格式
在总线的一次数据传送过程中,可以有以下几种组合方式:
主机向从机发送数据,数据传送方向在整个传送过程中不变:
主机在第一个字节后,立即从从机读数据:
在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相。
总线的寻址
I2C总线协议有明确的规定:采用7位的寻址字节(寻址字节是起始信号后的第一个字节)。
寻址字节的位定义
主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同,则认为自己正被主机寻址,根据R/T位将自己确定为发送器或接收器。
从机的地址由固定部分和可编程部分组成。在一个系统中可能希望接入多个相同的从机,从机地址中可编程部分决定了可接入总线该类器件的最大数目。如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件,即可以有8个同样的器件接入到该I2C总线系统中。
典型信号模拟
单片机进行写操作时,首先发送该器件的7位地址码和写方向位“0”(共8位,即一个字节),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为相应,单片机收到应答后就可以传送数据了。传送数据时,单片机首先发送一个字节的被写入器件的存储区的首地址,收到存储器器件的应答后,单片机就逐个发送各数据字节,但每发送一个字节后都要等待应答。当要写入的数据传送完后,单片机应发出终止信号以结束写入操作。写入n个字节的数据格式 :
单片机先发送该器件的7位地址码和写方向位“0”(“伪写”),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为回应。然后,再发一个字节的要读出器件的存储区的首地址,收到应答后,单片机要重复一次起始信号并发出器件地址和读方向位(“1”),收到器件应答后就可以读出数据字节,每读出一个字节,单片机都要回复应答信号。当最后一个字节数据读完后,单片机应返回以“非应答”(高电平),并发出终止信号以结束读出操作。
i2c.h
#ifndef _I2C_H
#define _I2C_H
#include "reg52.h"
sbit SCL=P2^1;
sbit SDA=P2^0;
void At24c02Write(unsigned char addr, unsigned char dat);
unsigned char At24c02Read(unsigned char addr);
#endif
i2c.c
#include "i2c.h" void Delay10us(void) { unsigned char a,b; for(b=1;b>0;b--) for(a=2;a>0;a--); } void I2cStart() { SDA=1; Delay10us(); SCL=1; Delay10us(); SDA=0; Delay10us(); SCL=0; Delay10us(); } void I2cStop() { SDA=0; Delay10us(); SCL=1; Delay10us(); SDA=1; Delay10us(); } unsigned char I2cSendByte(unsigned char dat) { unsigned char a; unsigned char t=1; unsigned char b=1; for(a=0;a<8;a++) { SDA=dat>>7; dat<<=1; Delay10us(); SCL=1; Delay10us(); SCL=0; Delay10us(); } SDA=1; Delay10us(); SCL=1; Delay10us(); while(SDA) { b++; if(b>200) { SCL=0; Delay10us(); t=0; return b; } } SCL=0; Delay10us(); return t; } unsigned char I2cReadByte() { unsigned char a=0,dat=0; SDA=1; Delay10us(); for(a=0;a<8;a++) { SCL=1; Delay10us(); dat<<=1; dat|=SDA; Delay10us(); SCL=0; Delay10us(); } return dat; } void At24c02Write(unsigned char addr, unsigned char dat) { I2cStart(); I2cSendByte(0xA0); I2cSendByte(addr); I2cSendByte(dat); I2cStop(); } unsigned char At24c02Read(unsigned char addr) { unsigned char num; I2cStart(); I2cSendByte(0xA0); I2cSendByte(addr); I2cStart(); I2cSendByte(0xA1); num=I2cReadByte(); I2cStop(); return num; }
main.c
#include "reg52.h" #include "i2c.h" typedef unsigned char u8; typedef unsigned int u16; sbit k1=P3^1; sbit k2=P3^0; sbit k3=P3^2; sbit k4=P3^3; sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; u8 code smgduan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; u8 num=0; u8 disp[4]; void delay(u16 i) { while(i--); } void datapros() { disp[0]=smgduan[num/1000]; disp[1]=smgduan[num/100%10]; disp[2]=smgduan[num/10%100%10]; disp[3]=smgduan[num%1000%100%10]; } void Keypros() { if(k1==0) { delay(1000); if(k1==0) { At24c02Write(1,num); } while(!k1); } if(k2==0) { delay(1000); if(k2==0) { num=At24c02Read(1); } while(!k2); } if(k3==0) { delay(1000); if(k3==0) { num++; if(num>255) { num=0; } } while(!k3); } if(k4==0) { delay(1000); if(k4==0) { num=0; } while(!k4); } } void DigDisplay() { u8 i; for(i=0;i<4;i++) { switch(i) { case(0): LSA=0;LSB=0;LSC=0;break; case(1): LSA=1;LSB=0;LSC=0;break; case(2): LSA=0;LSB=1;LSC=0;break; case(3): LSA=1;LSB=1;LSC=0;break; } P0=disp[3-i]; delay(100); P0=0x00; } } void main(){ while(1) { Keypros(); datapros(); DigDisplay(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。