1 #include "reg52.h"
2 #include <intrins.h>
3
4 #define USE_T2
5 #define FOSC 12000000
6 #define BAUD 9600
7
8 //端口位定义,可修改
9 sbit SDA=P1^0;
10 sbit SCL=P1^1;
11
12 //内部数据定义
13 #define IIC_Add 0xB8 //器件地址
14 #define IIC_RX_Length 15
15
16 unsigned char IIC_TX_Buffer[]={0x03,0x00,0x04}; //读温湿度命令(无CRC校验)
17 unsigned char IIC_RX_Buffer[IIC_RX_Length] = {0x00};//读回的温湿度
18
19 unsigned char Uart_RX_Buffer[30] = {0x00};
20 unsigned char *String;
21 unsigned char WR_Flag;
22
23 //字符串定义
24 #define S_Function "Function: 03 04"
25 #define S_Temp "Temp:"
26 #define S_RH "RH:"
27 #define S_CRCT "CRC: True"
28 #define S_CRCF "CRC: Wrong"
29 #define S_Data "Data: "
30 #define S_NotS "Sensor Not Connected"
31
32 void Ack(void);
33 void NoAck(void);
34
35 void delay10us(void) //这个延时函数 要大于5US以上
36 {
37 _nop_(); _nop_(); _nop_();
38 _nop_(); _nop_(); _nop_();
39 }
40
41 void delay1ms(unsigned int t)
42 {
43 unsigned int i;
44 unsigned int j;
45 for(j=t;j>0;j--)
46 for(i=124;i>0;i--);
47 }
48
49 void InitUART(void)
50 {
51 unsigned int iTmpBaud;
52 unsigned long lTmpBaud;
53 iTmpBaud = 0;
54 //首先选定定时器2作为波特率发生器,16位定时器,自动装载
55 SCON = 0x50; //SM0 SM1 SM2 REN TB8 RB8 TI RI //0 1 0 1 0 0 0 0
56 PCON = 0x00; //PCON的地址是87H,这里SMOD =0
57
58 T2CON = 0x30; //TF2 EXF2 RCLK TCLK EXEN2 TR2 C(/T2) CP(/RL2) //0 0 1 1 0 0 0 0
59 T2MOD = 0x00; // / / / / / / T2OE DCEN //0 0 0 0 0 0 0 0
60
61 //fosc = 22.1184M,6T: 144,设置波特率
62 //(RCAP2H,RCAP2L) = 65536- fosc/(n*Baud)。n:32(12T-mode),16:(6T-mode)
63 lTmpBaud = FOSC/BAUD;
64 lTmpBaud /= 32; //12T-mode
65 iTmpBaud = lTmpBaud & 0xFFFF;
66 iTmpBaud = 65536 - iTmpBaud;
67 RCAP2H = (iTmpBaud>>8) & 0x0FF;
68 RCAP2L = iTmpBaud & 0x0FF;
69
70 RI = 0; //清除接收中断标志
71 REN = 1; //允许串行接收
72 ES = 1; //允许串行中断
73 TR2 = 1; //启动定时器1
74
75 EA=1;//开总中断
76 }
77
78 //串口发送
79 void UARTSend(char UCHAR)
80 {
81 SBUF=UCHAR;
82 while(TI==0);
83 TI=0;
84 }
85
86 void UARTRead(void) interrupt 4
87 {
88 char temp;
89 if(RI)
90 {
91 RI=0;
92 temp = SBUF;
93 }
94 }
95
96 //**********************************************
97 //送起始位 sda=1->0
98 void I2C_Start()
99 {
100 SDA=1;
101 SCL=1;
102 delay10us();
103 SDA=0;
104 delay10us();
105 SCL=0;
106 }
107 //************************************************
108 //送停止位 sda=0->1
109 void I2C_Stop()
110 {
111 SDA=0;
112 delay10us();
113 SCL=1;
114 delay10us();
115 SDA=1;
116 }
117 //************************************************
118 //主应答(包含ack:sda=0和no_ack:sda=0)
119 void Ack(void)
120 { //设置SDA 口为输出
121 SDA=0;
122 SCL=0;
123 delay10us();
124 SCL=1;
125 delay10us();
126 SCL=0;
127 SDA=1;
128 }
129
130 void NoAck(void)
131 { //设置SDA 口为输出
132 SDA=1;
133 SCL=0;
134 delay10us();
135 SCL=1;
136 delay10us();
137 SDA=1;
138 SCL=0;
139 }
140
141 // 检测 SDA是否回ACK
142 bit Test_Ack()
143 { //设置SDA 口为输入
144 bit ACK_Flag=0;
145 SCL=0;
146 SDA=1;
147 delay10us();
148 SCL=1;
149 delay10us();
150 if(SDA==0)
151 ACK_Flag = 1;
152 else
153 ACK_Flag = 0;
154 SCL=0;
155 return ACK_Flag;
156 }
157
158 //*************************************************
159 //字节发送程序
160 //发送c(可以是数据也可是地址),送完后接收从应答
161 //不考虑从应答位
162 void SendData(unsigned char buffer)
163 {
164 unsigned char BitCnt=8;//一字节8位
165 //设置SDA 口为输出
166 do
167 {
168 SCL=0;
169 delay10us();
170 if((buffer&0x80)==0) //判断最高位是0还是1
171 SDA=0;
172 else
173 SDA=1;
174 SCL=1;
175 delay10us();
176 buffer=buffer<<1;//将buffer中的数据左移一位
177 BitCnt--;
178 }
179 while(BitCnt);
180 SCL=0;
181 }
182 //**************************************************
183 //字节接收程序
184 //接收器件传来的数据,此程序应配合|主应答函数|i2c_ack_main()使用
185 //return: uchar型1字节
186 unsigned char ReceiveData()
187 {
188 unsigned char BitCnt=8,IIC_RX_Data=0;
189 unsigned char temp=0;
190 SDA=1; //读入数据 设置SDA 口为输入
191 do
192 {
193 SCL=0;
194 delay10us();
195 IIC_RX_Data=_crol_(IIC_RX_Data,1); //数据左移一位
196 BitCnt--;
197 SCL=1;
198 delay10us();
199 if(SDA==1)
200 IIC_RX_Data = IIC_RX_Data|0x01; //低位置1
201 else
202 IIC_RX_Data = IIC_RX_Data&0x0fe; //低位清0
203 }
204 while(BitCnt);
205 SCL=0;
206 return IIC_RX_Data;
207 }
208 //***************************************************
209 bit WriteNByte(unsigned char sla,unsigned char *s,unsigned char n)
210 {
211 unsigned char i;
212
213 I2C_Start(); //启动I2C
214 SendData(sla);//发送器件地址
215 if(!Test_Ack())
216 {
217 WR_Flag = 1;
218 return(0);
219 }
220 for(i=0;i<n;i++)//写入8字节数据
221 {
222 SendData(*(s+i));
223 if(!Test_Ack())
224 {
225 WR_Flag = 1;
226 return(0);
227 }
228 }
229 I2C_Stop();
230 return(1);
231 }
232 bit ReadNByte(unsigned char Sal, unsigned char *p,unsigned char n)
233 {
234 unsigned char i;
235 I2C_Start(); // 启动I2C
236 SendData((Sal)| 0x01); //发送器件地址
237 if(!Test_Ack())
238 {
239 WR_Flag = 1;
240 return(0);
241 }
242 delay10us();
243 delay10us();
244 delay10us(); // 延时时间必须大于30us 只要大于 30us 以上的值都可以 但是最好不要太长 ,测试时,试过25MS都OK!
245
246 for(i=0;i<n-1;i++) //读取字节数据
247 {
248 *(p+i)=ReceiveData(); //读取数据
249 Ack();
250 }
251 *(p+n-1)=ReceiveData();
252 NoAck();
253 I2C_Stop();
254 return(1);
255 }
256 ///计算CRC校验码
257 unsigned int CRC16(unsigned char *ptr, unsigned char len)
258 {
259 unsigned int crc=0xffff;
260 unsigned char i;
261 while(len--)
262 {
263 crc ^=*ptr++;
264 for(i=0;i<8;i++)
265 {
266 if(crc & 0x1)
267 {
268 crc>>=1;
269 crc^=0xa001;
270 }
271 else
272 {
273 crc>>=1;
274 }
275 }
276 }
277 return crc;
278 }
279 ///检测CRC校验码是否正确
280 unsigned char CheckCRC(unsigned char *ptr,unsigned char len)
281 {
282 unsigned int crc;
283 crc=(unsigned int)CRC16(ptr,len-2);
284 if(ptr[len-1]==(crc>>8) && ptr[len-2]==(crc & 0x00ff))
285 {
286 return 0xff;
287 }
288 else
289 {
290 return 0x0;
291 }
292 }
293 void Waken(void)
294 {
295 I2C_Start(); // 启动I2C
296 SendData(IIC_Add); // 发送器件地址
297 Test_Ack(); // 唤醒指令时 传感器不会回ACK 但是第一定要发检测ACK的时钟 否则会出错
298 delay1ms(2); // 至少延时1个Ms 说明书里,有个最大值 ,实际当中 你只要大于1MS
299 I2C_Stop();
300 }
301
302 void UART_PutString(unsigned char *buf )
303 {
304 while(*buf)
305 UARTSend(*buf++);
306 }
307
308 void UART_PutStringAndNum(unsigned char *buf ,unsigned int num)
309 {
310 unsigned char a[3],i;
311 a[3] = '0'+num%10;
312 a[2] = '.';
313 a[1] = '0'+num/10%10;
314 a[0] = '0'+num/100%10;
315 while(*buf)
316 UARTSend(*buf++);
317 UARTSend(' ');
318 for(i=0;i<4;i++)
319 {
320 UARTSend(a[i]);
321 }
322 }
323 void UART_PutStringAnd_Data(unsigned char *buf ,unsigned char *bufdata)
324 {
325 unsigned char a[2],i,j;
326 while(*buf)
327 UARTSend(*buf++);
328 UARTSend(' ');
329 for(i=0;i<8;i++)
330 {
331 a[0] = bufdata[i]/16;
332 a[1] = bufdata[i]%16;
333 for(j=0;j<2;j++)
334 {
335 if(a[j]>9)
336 {
337 a[j] = (a[j]-10)+'A';
338 }
339 else
340 {
341 a[j] = a[j]+'0';
342 }
343 UARTSend(a[j]);
344 }
345 UARTSend(' ');
346 }
347 }
348
349 void UARTSend_Nbyte(void)
350 {
351 int Tmp;
352 if(WR_Flag == 0)
353 {
354 if(CheckCRC(IIC_RX_Buffer,8))
355 {
356 String = S_Function; // "Function: 03 04"
357 UART_PutString(String);
358 UARTSend(' ');
359 UARTSend(' ');
360
361 String = S_RH;//"RH:"
362 Tmp = IIC_RX_Buffer[2]*256+IIC_RX_Buffer[3];
363 UART_PutStringAndNum(String,Tmp);
364
365 UARTSend(' ');
366 UARTSend(' ');
367 String = S_Temp; //"Temp:"
368
369 Tmp = IIC_RX_Buffer[4]*256+IIC_RX_Buffer[5];
370 UART_PutStringAndNum(String,Tmp);
371
372 UARTSend(' ');
373 UARTSend(' ');
374
375 String = S_CRCT;//"CRC: True";
376 UART_PutString(String);
377
378 }else
379 {
380 String = S_Data;//"Data: ";
381
382 UART_PutStringAnd_Data(String,IIC_RX_Buffer);
383 UARTSend(' ');
384 UARTSend(' ');
385 String = S_CRCF;//"CRC: Wrong";
386 UART_PutString(String);
387 }
388 }
389 else
390 {
391 String = S_NotS;//"Sensor Not Connected";
392 UART_PutString(String);
393 }
394 UARTSend(0x0A);
395
396 }
397 void Clear_Data (void)
398 {
399 int i;
400 for(i=0;i<IIC_RX_Length;i++)
401 {
402 IIC_RX_Buffer[i] = 0x00;
403 }//接收数据清零
404 }
405
406 void main(void)
407 {
408 SCL = 1;
409 SDA = 1; //上电时保证两总线为高
410 InitUART();
411 Clear_Data();
412 while(1)
413 {
414 Clear_Data(); // 清除收到数据
415 WR_Flag = 0;
416 Waken(); // 唤醒传感器
417 //发送读指令
418 WriteNByte(IIC_Add,IIC_TX_Buffer,3);
419 //发送读取或写数据命令后,至少等待2MS(给探头返回数据作时间准备)
420 delay1ms(2);
421 //读返回数据
422 ReadNByte(IIC_Add,IIC_RX_Buffer,8);
423
424 SCL = 1; SDA = 1; //确认释放总线
425 //通过串口向上发送传感器数据
426 UARTSend_Nbyte();
427
428 delay1ms(2000); //延时 2S (两次读取间隔至少2S)
429 }
430 }
实物图
![](https://static.oschina.net/uploads/space/2018/0201/095411_heLB_3776585.png)
引脚图
![](https://static.oschina.net/uploads/space/2018/0201/095420_Alzs_3776585.png)
接线图
![](https://static.oschina.net/uploads/space/2018/0201/095436_E781_3776585.jpg)
效果图
![](https://static.oschina.net/uploads/space/2018/0201/095450_23fr_3776585.png)
编译图
![](https://static.oschina.net/uploads/space/2018/0201/095512_a0rQ_3776585.png)