📄 i2c.lst
字号:
C51 COMPILER V7.50 I2C 07/20/2007 15:38:41 PAGE 1
C51 COMPILER V7.50, COMPILATION OF MODULE I2C
OBJECT MODULE PLACED IN .\I2C.obj
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE F:\0217\新建文件夹2\I2C.c BROWSE INTVECTOR(0X8000) DEBUG OBJECTEXTEND PRINT
-(.\I2C.lst) OBJECT(.\I2C.obj)
line level source
1 /*
2 I2C.c
3 标准80C51单片机模拟I2C 总线的主机程序
4 Copyright (c) 2005,广州周立功单片机发展有限公司
5 All rights reserved.
6 本程序仅供学习参考,不提供任何可靠性方面的担保;请勿用于商业目的
7 */
8
9 #include "I2C.h"
10
11 //定义延时变量,用于宏I2C_Delay()
12
13 unsigned char data I2C_Delay_t;
14
15 /*
16 宏定义:I2C_Delay()
17 功能:延时,模拟I2C总线专用
18 */
19 #define I2C_Delay()\
20 {\
21 I2C_Delay_t = (I2C_DELAY_VALUE);\
22 while ( --I2C_Delay_t != 0 );\
23 }
24
25 /*
26 函数:I2C_Init()
27 功能:I2C总线初始化,使总线处于空闲状态
28 说明:在main()函数的开始处,通常应当要执行一次本函数
29 */
30 void I2C_Init()
31 {
32 1 I2C_SCL = 1;
33 1 I2C_Delay();
34 1 I2C_SDA = 1;
35 1 I2C_Delay();
36 1 }
37
38 /*
39 函数:I2C_Start()
40 功能:产生I2C总线的起始状态
41 说明:
42 SCL处于高电平期间,当SDA出现下降沿时启动I2C总线
43 不论SDA 和SCL处于什么电平状态,本函数总能正确产生起始状态
44 本函数也可以用来产生重复起始状态
45 本函数执行后,I2C总线处于忙状态
46 */
47 void I2C_Start()
48 {
49 1 I2C_SDA = 1;
50 1 I2C_Delay();
51 1 I2C_SCL = 1;
52 1 I2C_Delay();
53 1 I2C_SDA = 0;
54 1 I2C_Delay();
C51 COMPILER V7.50 I2C 07/20/2007 15:38:41 PAGE 2
55 1 I2C_SCL = 0;
56 1 I2C_Delay();
57 1
58 1 }
59
60 /*
61 函数:I2C_Write()
62 功能:向I2C 总线写1个字节的数据
63 参数:
64 dat:要写到总线上的数据
65 */
66 void I2C_Write(char dat)
67 {
68 1 unsigned char t = 8;
69 1 do
70 1 {
71 2 I2C_SDA = (bit)(dat & 0x80);
72 2 dat <<= 1;
73 2 I2C_SCL = 1;
74 2 I2C_Delay();
75 2 I2C_SCL = 0;
76 2 I2C_Delay();
77 2 } while ( --t != 0 );
78 1 }
79
80 /*
81 函数:I2C_Read()
82 功能:从从机读取1个字节的数据
83 返回:读取的一个字节数据
84 */
85 char I2C_Read()
86 {
87 1 char dat;
88 1 unsigned char t = 8;
89 1 I2C_SDA = 1; //在读取数据之前,要把SDA 拉高
90 1 do
91 1 {
92 2 I2C_SCL = 1;
93 2 I2C_Delay();
94 2 dat <<= 1;
95 2 if ( I2C_SDA ) dat |= 0x01;
96 2 I2C_SCL = 0;
97 2 I2C_Delay();
98 2 } while ( --t != 0 );
99 1 return dat;
100 1 }
101
102
103 /*
104 函数:I2C_GetAck()
105 功能:读取从机应答位
106 返回:
107 0:从机应答
108 1:从机非应答
109 说明:
110 从机在收到每个字节的数据后,要产生应答位
111 从机在收到最后1个字节的数据后,一般要产生非应答位
112 */
113 bit I2C_GetAck()
114 {
115 1 bit ack;
116 1 I2C_SDA = 1;
C51 COMPILER V7.50 I2C 07/20/2007 15:38:41 PAGE 3
117 1 I2C_Delay();
118 1 I2C_SCL = 1;
119 1 I2C_Delay();
120 1 ack = I2C_SDA;
121 1 I2C_SCL = 0;
122 1 I2C_Delay();
123 1 return ack;
124 1 }
125
126 /*
127 函数:I2C_PutAck()
128 功能:主机产生应答位或非应答位
129 参数:
130 ack=0:主机产生应答位
131 ack=1:主机产生非应答位
132 说明:
133 主机在接收完每一个字节的数据后,都应当产生应答位
134 主机在接收完最后一个字节的数据后,应当产生非应答位
135 */
136 void I2C_PutAck(bit ack)
137 {
138 1 I2C_SDA = ack;
139 1 I2C_Delay();
140 1 I2C_SCL = 1;
141 1 I2C_Delay();
142 1 I2C_SCL = 0;
143 1 I2C_Delay();
144 1 }
145
146 /*
147
148 函数:I2C_Stop()
149 功能:产生I2C总线的停止状态
150 说明:
151 SCL处于高电平期间,当SDA出现上升沿时停止I2C总线
152 不论SDA 和SCL处于什么电平状态,本函数总能正确产生停止状态
153 本函数执行后,I2C总线处于空闲状态
154 */
155 void I2C_Stop()
156 {
157 1 unsigned int t = I2C_STOP_WAIT_VALUE;
158 1 I2C_SDA = 0;
159 1 I2C_Delay();
160 1 I2C_SCL = 1;
161 1 I2C_Delay();
162 1 I2C_SDA = 1;
163 1 I2C_Delay();
164 1 while ( --t != 0 ); //在下一次产生Start之前,要加一定的延时
165 1 }
166
167 /*
168 函数:I2C_Puts()
169 功能:I2C总线综合发送函数,向从机发送多个字节的数据
170 参数:
171 SlaveAddr:从机地址(7位纯地址,不含读写位)
172 SubAddr:从机的子地址
173 SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
174 *dat:要发送的数据
175 Size:数据的字节数
176 返回:
177 0:发送成功
178 1:在发送过程中出现异常
C51 COMPILER V7.50 I2C 07/20/2007 15:38:41 PAGE 4
179 说明:
180 本函数能够很好地适应所有常见的I2C器件,不论其是否有子地址
181 当从机没有子地址时,参数SubAddr任意,而SubMod应当为0
182 */
183 bit I2C_Puts
184 (
185 unsigned char SlaveAddr,
186 unsigned int SubAddr,
187 unsigned char SubMod,
188 char *dat,
189 unsigned int Size
190 )
191 {
192 1
193 1 //定义临时变量
194 1 unsigned char i;
195 1 char a[3];
196 1 //检查长度
197 1 if ( Size == 0 ) return 0;
198 1 //准备从机地址
199 1 a[0] = (SlaveAddr << 1);
200 1 //检查子地址模式
201 1 if ( SubMod > 2 ) SubMod = 2;
202 1 //确定子地址
203 1 switch ( SubMod )
204 1 {
205 2 case 0:
206 2 break;
207 2 case 1:
208 2 a[1] = (char)(SubAddr);
209 2 break;
210 2 case 2:
211 2 a[1] = (char)(SubAddr >> 8);
212 2 a[2] = (char)(SubAddr);
213 2 break;
214 2 default:
215 2 break;
216 2 }
217 1 //发送从机地址,接着发送子地址(如果有子地址的话)
218 1 SubMod++;
219 1 I2C_Start();
220 1 for ( i=0; i<SubMod; i++ )
221 1 {
222 2 I2C_Write(a[i]);
223 2 if ( I2C_GetAck() )
224 2 {
225 3 I2C_Stop();
226 3 return 1;
227 3 }
228 2 }
229 1 //发送数据
230 1 do
231 1 {
232 2 I2C_Write(*dat++);
233 2 if ( I2C_GetAck() ) break;
234 2 } while ( --Size != 0 );
235 1 //发送完毕,停止I2C总线,并返回结果
236 1 I2C_Stop();
237 1
238 1 if ( Size == 0 )
239 1 {
240 2 return 0;
C51 COMPILER V7.50 I2C 07/20/2007 15:38:41 PAGE 5
241 2 }
242 1 else
243 1 {
244 2 return 1;
245 2 }
246 1 }
247
248 /*
249 函数:I2C_Gets()
250 功能:I2C总线综合接收函数,从从机接收多个字节的数据
251 参数:
252 SlaveAddr:从机地址(7位纯地址,不含读写位)
253 SubAddr:从机的子地址
254 SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
255 *dat:保存接收到的数据
256 Size:数据的字节数
257 返回:
258 0:接收成功
259 1:在接收过程中出现异常
260 说明:
261 本函数能够很好地适应所有常见的I2C器件,不论其是否有子地址
262 当从机没有子地址时,参数SubAddr任意,而SubMod应当为0
263 */
264 bit I2C_Gets
265 (
266 unsigned char SlaveAddr,
267 unsigned int SubAddr,
268 unsigned char SubMod,
269 char *dat,
270 unsigned int Size
271 )
272 {
273 1 //定义临时变量
274 1 unsigned char i;
275 1 char a[3];
276 1 //检查长度
277 1 if ( Size == 0 ) return 0;
278 1 //准备从机地址
279 1 a[0] = (SlaveAddr << 1);
280 1 //检查子地址模式
281 1 if ( SubMod > 2 ) SubMod = 2;
282 1
283 1 //如果是有子地址的从机,则要先发送从机地址和子地址
284 1 if ( SubMod != 0 )
285 1 {
286 2 //确定子地址
287 2 if ( SubMod == 1 )
288 2 {
289 3 a[1] = (char)(SubAddr);
290 3 }
291 2 else
292 2 {
293 3 a[1] = (char)(SubAddr >> 8);
294 3 a[2] = (char)(SubAddr);
295 3 }
296 2 //发送从机地址,接着发送子地址
297 2 SubMod++;
298 2 I2C_Start();
299 2 for ( i=0; i<SubMod; i++ )
300 2 {
301 3 I2C_Write(a[i]);
302 3 if ( I2C_GetAck() )
C51 COMPILER V7.50 I2C 07/20/2007 15:38:41 PAGE 6
303 3 {
304 4 I2C_Stop();
305 4 return 1;
306 4 }
307 3 }
308 2 }
309 1 //这里的I2C_Start()对于有子地址的从机是重复起始状态
310 1 //对于无子地址的从机则是正常的起始状态
311 1 I2C_Start();
312 1 //发送从机地址
313 1 I2C_Write(a[0]+1);
314 1 if ( I2C_GetAck() )
315 1 {
316 2 I2C_Stop();
317 2 return 1;
318 2 }
319 1 //接收数据
320 1 for (;;)
321 1 {
322 2 *dat++ = I2C_Read();
323 2 if ( --Size == 0 )
324 2 {
325 3 I2C_PutAck(1);
326 3 break;
327 3
328 3 }
329 2 I2C_PutAck(0);
330 2 }
331 1 //接收完毕,停止I2C总线,并返回结果
332 1 I2C_Stop();
333 1 return 0;
334 1 }
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 449 ----
CONSTANT SIZE = ---- ----
XDATA SIZE = ---- ----
PDATA SIZE = ---- ----
DATA SIZE = 1 24
IDATA SIZE = ---- ----
BIT SIZE = ---- 2
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -