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 }
相关文章:
- STM32 AHT10温湿度传感器数据 机智云传输温湿度 2022-02-15
- AVR---SHT10---温湿度传感器--温度 0XFF---湿度---问题 2021-11-16
- 温湿度传感器AM2302(DH22) 2021-12-16
- 温湿度传感器采集 2021-12-16
- Tiny6410--SHT10温湿度传感器 2021-12-05