1、采用串行总线技术可以使系统的硬件设计大大简化、系统的体积减小、可靠性提高。同时,系统的更改和扩充极为容易。常用的串行扩展总线有: I2C (Inter IC BUS)总线、单总线(1-WIRE BUS)、SPI(Serial Peripheral Interface)总线及Microwire/PLUS等。
2、I2C串行总线概述:I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。
3、I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。
4、每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。在多主机系统中,可能同时有几个主机企图启动总线传送数据。为了避免混乱, I2C总线要通过总线仲裁,以决定由哪一台主机控制总线。在80C51单片机应用系统的串行总线扩展中,我们经常遇到的是以80C51单片机为主机,其它接口器件为从机的单主机情况。
5、数据位的有效性规定
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
6、起始和终止信号:SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
7、起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。接收器件收到一个完整的数据字节后,有可能需要完成一些其它工作,如处理内部中断服务等,可能无法立刻接收下一个字节,这时接收器件可以将SCL线拉成低电平,从而使主机处于等待状态。直到接收器件准备好接收下一个字节时,再释放SCL线使之为高电平,从而使数据传送可以继续进行。
8、字节传送与应答:每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。
9、数据帧格式:I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。每次数据传送总是由主机产生的终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。
10、总线的寻址:I2C总线协议有明确的规定:采用7位的寻址字节(寻址字节是起始信号后的第一个字节)。寻址字节的位定义:
11、D7~D1位组成从机的地址。D0位是数据传送方向位,为“0”时表示主机向从机写数据,为“1”时表示主机由从机读数据。
12、主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同,则认为自己正被主机寻址,根据R/T位将自己确定为发送器或接收器。
从机的地址由固定部分和可编程部分组成。在一个系统中可能希望接入多个相同的从机,从机地址中可编程部分决定了可接入总线该类器件的最大数目。如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件,即可以有8个同样的器件接入到该I2C总线系统中。
13、单片机的反应时间是微秒级的。
14、串行E2PROM:(Electrically Erasable Programmable Read-Only Memory),电可擦可编程只读存储器--一种掉电后数据不丢失的存储芯片。 EEPROM 可以在电脑上或专用设备上擦除已有信息,重新编程。一般用在即插即用。
15、WP,write protect,写保护。NC,no-connect,未连接。Output Actknowledge,输出应答。
16、Datasheet需要的数据
EEPROM24c02程序:
1 #include
2 #include
3 #include "shumaguan.h"
4
5 #define uchar unsigned char
6 #define uint unsigned int
7
8 #define addwr 0xae//0x90 //读入地址,需要参考24c02文档
9 #define addrd 0xaf//0x91 //写入地址
10
11 sbit sda = P1^2;
12 sbit scl = P1^1;
13 sbit wp = P1^0;
14
15 void delay1(uint x) //uint防止数据溢出
16 {
17 uint i,k;
18 for(i=0;i
20 }
21
22 void start() //开始信号
23 {
24 sda = 1;
25 _nop_();
26 scl = 1;
27 _nop_();
28 sda = 0;
29 _nop_();
30 scl = 0;
31 }
32
33 void stop() //停止信号
34 {
35 sda = 0;
36 _nop_();
37 scl = 1;
38 _nop_();
39 sda = 1;
40 _nop_();
41 scl = 0;
42 }
43
44 void respons()
45 {
46 uchar i;
47 scl=1;
48 _nop_();
49 while((sda==1)&&(i<250))i++;
50 scl=0;
51 _nop_();
52 }
53
54 void init() //初始化
55 {
56 wp = 0;
57 sda = 1;
58 _nop_();
59 scl = 1;
60 _nop_();
61 }
62
63 void write_byte(uchar date)
64 {
65 uchar i,temp;
66 temp = date;
67
68 for(i=0;i<8;i++)
69 {
70 temp = temp << 1; //最高位左移的CY(标志寄存器)中
71 scl = 0;
72 _nop_();
73 sda = CY; //数据传输
74 _nop_();
75 scl = 1;
76 _nop_();
77 }
78 scl = 0;
79 _nop_();
80 sda = 1; //总线释放,为读取应答信号做准备
81 _nop_();
82 }
83
84 uchar read_byte()
85 {
86 uchar i,j,k;
87 scl = 0;
88 _nop_();
89 sda = 1; //释放数据总线
90 _nop_();
91 for(i=0;i<8;i++)
92 {
93 scl = 1;
94 _nop_();
95 j = sda; //读取数据
96 k = (k<<1)|j; //将数据放到最低位上
97 scl = 0;
98 _nop_();
99 }
100 return k;
101 }
102
103 void write_add(uchar data1) //看时序写
104 {
105 start(); //开始
106 write_byte(addwr); //写入芯片地址
107 respons();
108 write_byte(0x40);
109 respons();
110 write_byte(data1); //写数据
111 respons();
112 stop();
113 }
114
115 uchar read_add()
116 {
117 uchar date;
118 start();
119 write_byte(addwr);
120 respons();
121 write_byte(0x40);
122 respons();
123 start();
124 write_byte(addrd);
125 respons();
126 date = read_byte();
127 stop();
128 return date;
129 }
130
131 void write_rom(uchar Data[],uchar address,uchar num)
132 {
133 uchar i;
134 uchar *Pdata;
135 Pdata = Data;
136 for(i=0;i
138 start();
139 write_byte(addwr); //写入芯片地址
140 respons();
141 write_byte(address+i); //写入存储地址
142 respons();
143 write_byte(*(Pdata+i)); //写数据
144 respons();
145 stop();
146 delay1(30);
147 }
148 }
149
150 void read_rom(uchar Data[],uchar address,uchar num)
151 {
152 uchar i;
153 uchar *Pdata;
154 Pdata = Data;
155 for(i=0;i
157 start();
158 write_byte(addwr); //写入芯片地址
159 respons();
160 write_byte(address+i); //写入存储地址
161 respons();
162 start();
163 write_byte(addrd);
164 respons();
165 *(Pdata+i) = read_byte(); //读数据
166 scl = 0;
167 respons();
168 stop();
169 //delay1(20);
170 }
171 }
172
173 void main()
174 {
175 uchar temp;
176 uchar i=0,j;
177 uchar number[5]={0x00,0x01,0x02,0x03,0x04}; //0,1,2,3,4
178 init(); //初始化
179
180 write_rom(number,5,5);
181 delay1(20);
182 for(i=0;i<5;i++)
183 number[i]=0;
184 read_rom(number,5,5);
185
186 i = 0;
187 while(1)
188 {
189 display(3,number[i]);
190 delay1(500);
191 i++;
192 if(5 == i)i = 0;
193 }
194 // write_add(0xfe);
195 // delay1(100);
196 // temp = read_add();
197 // P1 = temp;
198 // while(1);
199 }