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