>_<:i2c.c
1 /*-----------------------------------------------
2 名称:IIC协议
3 内容:函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作 一定的修改....(本例是1us机器
4 周期,即晶振频率要小于12MHZ)
5 ------------------------------------------------*/
6 #include "i2c.h"
7 #define _Nop() _nop_() //定义空指令
8 bit ack; //应答标志位
9 sbit SDA=P2^1;
10 sbit SCL=P2^0;
11 /*------------------------------------------------
12 uS延时函数,含有输入参数 unsigned char t,无返回值
13 unsigned char 是定义无符号字符变量,其值的范围是
14 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
15 长度如下 T=tx2+5 uS
16 ------------------------------------------------*/
17 void DelayUs2x(unsigned char t)
18 {
19 while(--t);
20 }
21 /*------------------------------------------------
22 mS延时函数,含有输入参数 unsigned char t,无返回值
23 unsigned char 是定义无符号字符变量,其值的范围是
24 0~255 这里使用晶振12M,精确延时请使用汇编
25 ------------------------------------------------*/
26 void DelayMs(unsigned char t)
27 {
28 while(t--)
29 {
30 //大致延时1mS
31 DelayUs2x(245);
32 DelayUs2x(245);
33 }
34 }
35 /*------------------------------------------------
36 启动总线
37 ------------------------------------------------*/
38 void Start_I2c()
39 {
40 SDA=1; //发送起始条件的数据信号
41 _Nop();
42 SCL=1;
43 _Nop(); //起始条件建立时间大于4.7us,延时
44 _Nop();
45 _Nop();
46 _Nop();
47 _Nop();
48 SDA=0; //发送起始信号
49 _Nop(); //起始条件锁定时间大于4μ
50 _Nop();
51 _Nop();
52 _Nop();
53 _Nop();
54 SCL=0; //钳住I2C总线,准备发送或接收数据
55 _Nop();
56 _Nop();
57 }
58 /*------------------------------------------------
59 结束总线
60 ------------------------------------------------*/
61 void Stop_I2c()
62 {
63 SDA=0; //发送结束条件的数据信号
64 _Nop(); //发送结束条件的时钟信号
65 SCL=1; //结束条件建立时间大于4μ
66 _Nop();
67 _Nop();
68 _Nop();
69 _Nop();
70 _Nop();
71 SDA=1; //发送I2C总线结束信号
72 _Nop();
73 _Nop();
74 _Nop();
75 _Nop();
76 }
77 /*----------------------------------------------------------------
78 字节数据传送函数
79 函数原型: void SendByte(unsigned char c);
80 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
81 此状态位进行操作.(不应答或非应答都使ack=0 假)
82 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
83 ------------------------------------------------------------------*/
84 void SendByte(unsigned char c)
85 {
86 unsigned char BitCnt;
87 for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
88 {
89 if((c<<bitcnt)&0x80)sda=1; ="" 判断发送位<="" p="">
90 else SDA=0;
91 _Nop();
92 SCL=1; //置时钟线为高,通知被控器开始接收数据位
93 _Nop();
94 _Nop(); //保证时钟高电平周期大于4μ
95 _Nop();
96 _Nop();
97 _Nop();
98 SCL=0;
99 }
100 _Nop();
101 _Nop();
102 SDA=1; //8位发送完后释放数据线,准备接收应答位
103 _Nop();
104 _Nop();
105 SCL=1;
106 _Nop();
107 _Nop();
108 _Nop();
109 if(SDA==1)ack=0;
110 else ack=1; //判断是否接收到应答信号
111 SCL=0;
112 _Nop();
113 _Nop();
114 }
115 /*----------------------------------------------------------------
116 字节数据传送函数
117 函数原型: unsigned char RcvByte();
118 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
119 发完后请用应答函数。
120 ------------------------------------------------------------------*/
121 unsigned char RcvByte()
122 {
123 unsigned char retc;
124 unsigned char BitCnt;
125
126 retc=0;
127 SDA=1; //置数据线为输入方式
128 for(BitCnt=0;BitCnt<8;BitCnt++)
129 {
130 _Nop();
131 SCL=0; //置时钟线为低,准备接收数据位
132 _Nop();
133 _Nop(); //时钟低电平周期大于4.7us
134 _Nop();
135 _Nop();
136 _Nop();
137 SCL=1; //置时钟线为高使数据线上数据有效
138 _Nop();
139 _Nop();
140 retc=retc<<1;
141 if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中
142 _Nop();
143 _Nop();
144 }
145 SCL=0;
146 _Nop();
147 _Nop();
148 return(retc);
149 }
150 /*----------------------------------------------------------------
151 应答子函数
152 原型: void Ack_I2c(void);
153 ----------------------------------------------------------------*/
154 void Ack_I2c(void)
155 {
156 SDA=0;
157 _Nop();
158 _Nop();
159 _Nop();
160 SCL=1;
161 _Nop();
162 _Nop(); //时钟低电平周期大于4μ
163 _Nop();
164 _Nop();
165 _Nop();
166 SCL=0; //清时钟线,钳住I2C总线以便继续接收
167 _Nop();
168 _Nop();
169 }
170 /*----------------------------------------------------------------
171 非应答子函数
172 原型: void NoAck_I2c(void);
173 ----------------------------------------------------------------*/
174 void NoAck_I2c(void)
175 {
176 SDA=1;
177 _Nop();
178 _Nop();
179 _Nop();
180 SCL=1;
181 _Nop();
182 _Nop(); //时钟低电平周期大于4μ
183 _Nop();
184 _Nop();
185 _Nop();
186 SCL=0; //清时钟线,钳住I2C总线以便继续接收
187 _Nop();
188 _Nop();
189 }
190 /*----------------------------------------------------------------
191 向无子地址器件发送字节数据函数
192 函数原型: bit ISendByte(unsigned char sla,ucahr c);
193 功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
194 如果返回1表示操作成功,否则操作有误。
195 注意: 使用前必须已结束总线。
196 ----------------------------------------------------------------*/
197 /*bit ISendByte(unsigned char sla,unsigned char c)
198 {
199 Start_I2c(); //启动总线
200 SendByte(sla); //发送器件地址
201 if(ack==0)return(0);
202 SendByte(c); //发送数据
203 if(ack==0)return(0);
204 Stop_I2c(); //结束总线
205 return(1);
206 }
207 */
208 /*----------------------------------------------------------------
209 向有子地址器件发送多字节数据函数
210 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
211 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
212 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
213 如果返回1表示操作成功,否则操作有误。
214 注意: 使用前必须已结束总线。
215 ----------------------------------------------------------------*/
216 bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
217 {
218 unsigned char i;
219 for(i=0;i<no;i++)< p="">
220 {
221 Start_I2c(); //启动总线
222 SendByte(sla); //发送器件地址
223 if(ack==0)return(0);
224 SendByte(suba); //发送器件子地址
225 if(ack==0)return(0);
226
227 SendByte(*s); //发送数据
228
229 if(ack==0)return(0);
230 Stop_I2c(); //结束总线
231 DelayMs(2); //必须延时等待芯片内部自动处理数据完毕
232 s++;
233 suba++;
234 }
235 return(1);
236 }
237
238 /*----------------------------------------------------------------
239 向无子地址器件读字节数据函数
240 函数原型: bit IRcvByte(unsigned char sla,ucahr *c);
241 功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地
242 址sla,返回值在c.
243 如果返回1表示操作成功,否则操作有误。
244 注意: 使用前必须已结束总线。
245 ----------------------------------------------------------------*/
246 /*bit IRcvByte(unsigned char sla,unsigned char *c)
247 {
248 Start_I2c(); //启动总线
249 SendByte(sla+1); //发送器件地址
250 if(ack==0)return(0);
251 *c=RcvByte(); //读取数据
252 NoAck_I2c(); //发送非就答位
253 Stop_I2c(); //结束总线
254 return(1);
255 }
256 */
257 /*----------------------------------------------------------------
258 向有子地址器件读取多字节数据函数
259 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
260 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
261 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
262 如果返回1表示操作成功,否则操作有误。
263 注意: 使用前必须已结束总线。
264 ----------------------------------------------------------------*/
265 bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
266 {
267 unsigned char i;
268
269 Start_I2c(); //启动总线
270 SendByte(sla); //发送器件地址
271 if(ack==0)return(0);
272 SendByte(suba); //发送器件子地址
273 if(ack==0)return(0);
274
275 Start_I2c();
276 SendByte(sla+1);
277 if(ack==0)return(0);
278
279 for(i=0;i<no-1;i++)< p="">
280 {
281 *s=RcvByte(); //发送数据
282 Ack_I2c(); //发送就答位
283 s++;
284 }
285 *s=RcvByte();
286 NoAck_I2c(); //发送非应位
287 Stop_I2c(); //结束总线
288 return(1);
289 }
>_<:i2c.h
1 /*-----------------------------------------------
2 名称:IIC协议 头文件
3 ------------------------------------------------*/
4 #ifndef __I2C_H__
5 #define __I2C_H__
6 #include //头文件的包含
7 #include
8 #define _Nop() _nop_() //定义空指令
9 /*-----------------------------------------------
10 uS延时函数,含有输入参数 unsigned char t,无返回值
11 unsigned char 是定义无符号字符变量,其值的范围是
12 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
13 长度如下 T=tx2+5 uS
14 ------------------------------------------------*/
15 void DelayUs2x(unsigned char t);
16 /*------------------------------------------------
17 mS延时函数,含有输入参数 unsigned char t,无返回值
18 unsigned char 是定义无符号字符变量,其值的范围是
19 0~255 这里使用晶振12M,精确延时请使用汇编
20 ------------------------------------------------*/
21 void DelayMs(unsigned char t);
22 /*------------------------------------------------
23 启动总线
24 ------------------------------------------------*/
25 void Start_I2c();
26 /*------------------------------------------------
27 结束总线
28 ------------------------------------------------*/
29 void Stop_I2c();
30 /*----------------------------------------------------------------
31 字节数据传送函数
32 函数原型: void SendByte(unsigned char c);
33 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
34 此状态位进行操作.(不应答或非应答都使ack=0 假)
35 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
36 ------------------------------------------------------------------*/
37 void SendByte(unsigned char c);
38 /*----------------------------------------------------------------
39 字节数据传送函数
40 函数原型: unsigned char RcvByte();
41 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
42 发完后请用应答函数。
43 ------------------------------------------------------------------*/
44 unsigned char RcvByte();
45 /*----------------------------------------------------------------
46 应答子函数
47 原型: void Ack_I2c(void);
48 ----------------------------------------------------------------*/
49 void Ack_I2c(void);
50 /*----------------------------------------------------------------
51 非应答子函数
52 原型: void NoAck_I2c(void);
53 ----------------------------------------------------------------*/
54 void NoAck_I2c(void);
55 /*----------------------------------------------------------------
56 向无子地址器件发送字节数据函数
57 函数原型: bit ISendByte(unsigned char sla,ucahr c);
58 功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
59 如果返回1表示操作成功,否则操作有误。
60 注意: 使用前必须已结束总线。
61 ----------------------------------------------------------------*/
62 bit ISendByte(unsigned char sla,unsigned char c);
63
64 /*----------------------------------------------------------------
65 向有子地址器件发送多字节数据函数
66 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
67 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
68 地址sla,子地址suba,发送内容是s指
68 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
69 如果返回1表示操作成功,否则操作有误。
70 注意: 使用前必须已结束总线。
71 ----------------------------------------------------------------*/
72 bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
73 /*----------------------------------------------------------------
74 向无子地址器件读字节数据函数
75 函数原型: bit IRcvByte(unsigned char sla,ucahr *c);
76 功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地
77 址sla,返回值在c.
78 如果返回1表示操作成功,否则操作有误。
79 注意: 使用前必须已结束总线。
80 ----------------------------------------------------------------*/
81 bit IRcvByte(unsigned char sla,unsigned char *c);
82 /*----------------------------------------------------------------
83 向有子地址器件读取多字节数据函数
84 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
85 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
86 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
87 如果返回1表示操作成功,否则操作有误。
88 注意: 使用前必须已结束总线。
89 ----------------------------------------------------------------*/
90 bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
91 #endif
>_<:下面是main函数中如何调用封装好的函数来实现流水灯的效果的:
>_<:流水灯8个的连线这里用的是P1
1 /*-----------------------------------------------
2 名称:IIC协议 24c02存储花样灯程序
3 内容:将表格内容写入24c02,然后批量删除这些数据,
4 并从24c02中读取数据并显示
5 ------------------------------------------------*/
6 #include
7 #include "i2c.h"
8 /*------------------------------------------------
9 花样灯表格
10 ------------------------------------------------*/
11 unsigned char dat[]={0x7f,0xbf,0xdf,0xef,
12 0xf7,0xfb,0xfd,0xfe,
13 0xff,0xff,0x00,0x00,
14 0x55,0x55,0xaa,0xaa
15 };//ram允许情况可以无限添加
16 /*------------------------------------------------
17 主函数
18 ------------------------------------------------*/
19 main()
20 {
21 //bit flag;
22 unsigned char i;
23 ISendStr(0xae,80,dat,16); //写入24c02
24 DelayMs(1); //写入后必须延时等待24c02内部
25 //烧录数据处理完毕方可继续其他操作
26 for(i=0;i<16;i++) //清除数据
27 dat[i]=0;
28 IRcvStr(0xae,80,dat,16); //从24c02读出数据
29 while(1)
30 {
31 for(i=0;i<16;i++) //查表
32 {
33 DelayMs(200);
34 P1=dat[i];
35 }
36 }
37 }