• 单片机温湿度传感器


      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 }

    实物图

    引脚图

    接线图

    效果图

    编译图

  • 相关阅读:
    tomcat安装apr优化
    mysql配置主从同步
    hadoop分布式安装
    SSH端口转发详解及实例-转载
    Jmeter实现简单web负载测试
    使用Jmeter进行http接口测试
    Jmeter如何使用数据库返回值实践
    学习使用Jmeter做压力测试(一)--压力测试基本概念
    Jmeter建立一个扩展LDAP测试计划
    Jmeter服务器监控插件使用
  • 原文地址:https://www.cnblogs.com/kwkk978113/p/14152838.html
Copyright © 2020-2023  润新知