<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        實時時鐘+紅外+溫度傳感器+LCD1602顯示

        作者:寒竹子   來源:本站原創   點擊數:  更新時間:2014年05月02日   【字體:

         此程序是在51hei單片機開發板上面做的,如需要移植到自己的電路上,修改相應的端口即可,開發板完整的電路圖下載:  點這里 (注意:只需要看相關部分的連線如液晶屏 等和單片機的連接方式,其他部分可以忽略)

        /**
          ****************************************************************************
          * @file      main.c
          * @author    xr
          * @date      2014年4月10日22:21:56
          * @version   V1.2.3
          * @brief     在LCD1602上顯示時鐘,當前溫度值,和NEC協議的紅外解碼值
          * @note      單片機STC89C52RC MCU  晶振 11.0592MHZ
          ****************************************************************************
          */

        #include <reg52.h>
        #include "mytype.h"
        bit fack = 0;//接收到溫度數據標志位
        bit flag1s = 0;//1s時間標志位
        bit flag200ms = 0;//200ms標志
        uint8 thr0, tlr0;
        uint8 counter = 0, i = 0;
        //數碼管編碼
        uint8 code LedTable[] = { 
            0xC0,  //"0"
                        0xF9,  //"1"
                        0xA4,  //"2"
                        0xB0,  //"3"
                        0x99,  //"4"
                        0x92,  //"5"
                        0x82,  //"6"
                        0xF8,  //"7"
                        0x80,  //"8"
                        0x90,  //"9"
                        0x88,  //"A"
                        0x83,  //"B"
                        0xC6,  //"C"
                        0xA1,  //"D"
                        0x86,  //"E"
                        0x8E   //"F"
           };
        extern void InitLcd1602();
        extern void LcdShowStr(uint8 x, uint8 y, uint8 * str);
        extern bit StartDs18B20();
        extern bit ReadDs18B20Temp(int * temp);
        extern void InitDS1302();
        extern void DS1302BurstRead(uint8 * time);
        extern void InitInfrared();
        //外部變量只是聲明,不可以重新賦值
        extern bit Irflag;//紅外遙控器解碼數據接收完成標志
        extern uint8 Ircode[4];//存放遙控器解碼值(用戶碼, 用戶碼反碼,鍵碼,鍵碼反碼)

        void ConfigTimer0(uint16 xms);
        uint8 IntToString(uint8 * str, int dat);
        void main(void)
        {
         uint8 buf[4];
         uint8 len = 0;
         int temp;//溫度
         int intT, decT;//整數部分,小數部分
         uint8 str[20];
         uint8 time[20];//保存時間(BCD碼值)
         uint8 psec = 0xFF;//sec最大是59,所以一定能刷新顯示
         
         InitLcd1602();
         InitDS1302();
         ConfigTimer0(10);//定時10ms
         StartDs18B20();
         InitInfrared();
         
         while (1)
         {
          if (Irflag) //紅外解碼
          {
           Irflag = 0;
           
           buf[0] = Ircode[2] / 10 % 10;//按鍵碼的十位數
           buf[1] = Ircode[2] % 10;//按鍵碼的個位數
           str[0] = buf[0] + '0';
           str[1] = buf[1] + '0';
           str[2] = '\0';
           
           LcdShowStr(14, 1, str);
          }
          
          if (flag200ms) //200ms刷新時鐘顯示
          {
           flag200ms = 0;
           
           DS1302BurstRead(time);
           if (psec != time[0]) //time[0]保存的是sec寄存器的BCD碼值
           {
            //刷新顯示
            //日期
            str[0] = '2';
            str[1] = '0';
            str[2] = (time[6] >> 4) + '0';//取年十位
            str[3] = (time[6] & 0x0F) + '0';//取年個位轉字符
            str[4] = '-';
            str[5] = (time[4] >> 4) + '0'; //月十位
            str[6] = (time[4] & 0x0F) + '0'; //月個位
            str[7] = '-';
            str[8] = (time[3] >> 4) + '0'; //日十位
            str[9] = (time[3] & 0x0F) + '0'; //日個位
            str[10] = '\0';
            
            LcdShowStr(0, 0, str);
            
            //時間
            str[0] = (time[2] >> 4) + '0';//時十位
            str[1] = (time[2] & 0x0F) + '0';//時個位
            str[2] = ':';
            str[3] = (time[1] >> 4) + '0';
            str[4] = (time[1] & 0x0F) + '0';
            str[5] = ':';
            str[6] = (time[0] >> 4) + '0';
            str[7] = (time[0] & 0x0F) + '0';
            str[8] = '\0';
            
            LcdShowStr(0, 1, str);
            
            //星期
            str[0] = (time[5] & 0x0F) + '0';//星期只有一位數字
            str[1] = '\0';
            
            LcdShowStr(11, 0, "Week");
            LcdShowStr(15, 0, str);
            
            psec = time[0];
           }
          }
          
          if (flag1s) //1s刷新溫度顯示
          {
           flag1s = 0;
           
           fack = ReadDs18B20Temp(&temp);//讀取溫度
           if (fack) //讀取成功
           {
            intT = (temp >> 4);//整數部分,將小數部分移出
            decT = (temp & 0x000F);//小數部分
            len = IntToString(str, intT);//將intT整數部分轉換成字符存入str中,并返回有效字符個數
            str[len++] = '.';//小數點
            decT = decT * 10 / 16 % 10;//小數部分轉換
            str[len++] = decT + '0';
            str[len] = '\0';
            
            LcdShowStr(8, 1, "T:");
            LcdShowStr(10, 1, str);    
           }
           else
           {
            LcdShowStr(0, 0, "error!");
           }
          }
          StartDs18B20();//重新啟動溫度轉換
         }
        }
        //定時器T0配置
        void ConfigTimer0(uint16 xms)
        {
         uint16 tmp;
         tmp = 65536-xms*11059200/12/1000;
         thr0 = (uint8)(tmp >> 8);//取高字節
         tlr0 = (uint8)(tmp & 0x00FF);//取低字節
         TMOD &= 0xF0;//清零T0控制位
         TMOD |= 0x01;//T0方式1
         TH0 = thr0;
         TL0 = tlr0;//裝入定時初值
         TR0 = 1;//啟動T0定時器
         EA  = 1;//開總中斷
         ET0 = 1;//開定時器T0中斷
         
         //PT0 = 1;//設置T0中斷優先級為最高級
        }
        //整數轉換成str
        unsigned char IntToString(unsigned char * str, signed int dat)
        {
         unsigned char len = 0;//統計有效字符的個數
         signed char i = 0;//計數器
         unsigned char buff[6];//數據分解緩沖區
         
         if (dat < 0) //負數
         {
          dat = -dat;//取絕對值
          *str++ = '-';//前面加上-
          len++;//長度++
         }
         
         //分解整數dat到buff中
         do
         {
          buff[i++] = dat % 10;
          dat /= 10;
         } while (dat > 0);//分解到dat==0為止
         len += i;//長度+i,有效字符個數
         while (i-- > 0) //拷貝轉換后的ASIIC碼字符到str接收指針中
         {
          *str++ = buff[i] + '0';//轉換成ASCII字符
         }
         *str = '\0';//加上串結束符
         
         return len;//返回有效字符個數
        }
        //定時器T0中斷服務
        void timer0_ISP() interrupt 1

         TH0 = thr0;
         TL0 = tlr0;
         counter++;
         if (counter >= 20)
         {
          counter = 0;
          flag200ms = 1;
          i++;
          if (i >= 5)
          {
           i = 0;
           flag1s = 1;
          }
         }
        }


         /**********自定義頭文件************/
        #ifndef _MYTYPE_H_H
        #define _MYTYPE_H_H
        typedef unsigned int uint16;
        typedef unsigned char uint8;
        typedef unsigned long uint32;
        #endif //_MYTYPE_H_H

         /***************LCD1602.c*********************/
        #include <reg52.h>
        #include "mytype.h"
        //LCD1602
        sbit LCD1602_RS = P1^0;
        sbit LCD1602_RW = P1^1;
        sbit LCD1602_EN = P1^5;
        #define LCD1602_DB P0
        //液晶忙碌等待
        void WaitLcd1602()
        {
         uint8 sta;
         
         LCD1602_DB = 0xFF;//拉高P0口
         
         LCD1602_RS = 0;
         LCD1602_RW = 1;
         do
         {
          LCD1602_EN = 1;
          sta = LCD1602_DB;
          LCD1602_EN = 0;//關閉液晶的數據輸出
         } while (sta & 0x80);
        }
        //寫命令
        void WriteLcd1602Cmd(uint8 cmd)
        {
         WaitLcd1602();
         
         LCD1602_RS = 0;
         LCD1602_RW = 0;
         LCD1602_DB = cmd;
         LCD1602_EN = 1;//高脈沖
         LCD1602_EN = 0;
        }
        //寫數據
        void WriteLcd1602Data(uint8 dat)
        {
         WaitLcd1602();
         
         LCD1602_RS = 1;
         LCD1602_RW = 0;
         LCD1602_DB = dat;
         LCD1602_EN = 1;//高脈沖
         LCD1602_EN = 0;
        }
        //液晶初始化
        void InitLcd1602()
        {
         WriteLcd1602Cmd(0x38);//設置16*2顯示 5*7點陣 8位數據口
         WriteLcd1602Cmd(0x0C);//開顯示不顯示光標
         WriteLcd1602Cmd(0x06);//寫入一個字符時字符指針++且地址++
         WriteLcd1602Cmd(0x01);//清屏
        }
        //寫str到LCD1602
        void LcdShowStr(uint8 x, uint8 y, uint8 * str)
        {
         uint8 addr;
         
         if (y == 0)
         { //第一行
          addr = 0x00 + x;
         }
         else
         { //第二行
          addr = 0x40 + x;
         }
         
         WriteLcd1602Cmd(0x80 | addr);
         while (*str != '\0')
         {
          WriteLcd1602Data(*str++);
         }
        }

        /**
          *********************************************************************
          * @file     infrared.c
          * @author   xr
          * @date     2014年4月11日08:25:04
          * @version  V1.2.3
          * @brief    紅外通信-NEC協議紅外遙控器解碼驅動
          * @note     單片機STC89C52RC MCU 晶振 11.0592MHZ
          *********************************************************************
          */
         
        #include <reg52.h>
        #include "mytype.h"
        //紅外通信接口位聲明
        sbit IRD = P3^3;
        bit Irflag = 0;//紅外遙控器解碼數據接收完成標志
        uint8 Ircode[4];//存放遙控器解碼值(用戶碼, 用戶碼反碼,鍵碼,鍵碼反碼)
        extern void LcdShowStr(uint8 x, uint8 y, uint8 * str);
        /**
          * @brief     紅外通信配置
          * @param     無
          * @retval    無
          */
        void InitInfrared()
        {
         //使用定時器T1作為計數,不定時也不進入T1中斷
         TMOD &= 0x0F;//清零T1控制位
         TMOD |= 0x10;//設置T1方式1
         ET1 = 0;//禁止T1中斷
         TR1 = 0;//在外部中斷引腳即紅外通信引腳沒有載波(低電平)和空閑(高電平)時,先關閉T1計數
         TH1 = 0;
         TL1 = 0;//清零T1計數值
         
         //使能外部中斷1
         IT1 = 1;//設置INT1中斷觸發方式為負邊沿觸發
         EX1 = 1;//開啟外部中斷1
         EA  = 1;//開啟總中斷
         PX1 = 1;
        }
        /**
          * @brief     獲取紅外通信引腳載波(低電平)計數值
          * @param     無
          * @retval    載波計數值(即T1計數值)
          */
        uint16 GetLowCounter() //計數值*(12/11059200)即是載波時間,計數值=TH1*256+TL1
        {
         IRD = 1;//在檢測IRD引腳電平時要將此引腳拉高釋放
         TH1 = 0;
         TL1 = 0;//清零T1計數值
         TR1 = 1;//開啟T1計數
         
         while (!IRD) //若IRD=0,T1開始計數
         {
          //超時判斷,因為引導碼的載波時間是9ms,所以不能等待太長時間
          if (TH1 > 0x40) //超過20ms就強制退出 (TH1*256*(12/11059200)s)
          {
           break;
          }
         }
         TR1 = 0;//關閉T1計數
         
         return (TH1*256 + TL1);//返回計數值(TL1加滿到256向TH1進1)
        }
        /**
          * @brief     獲取空閑時間計數值(高電平)
          * @param     無
          * @retval    空閑計數值
          */
        uint16 GetHeighCounter()
        {
         IRD = 1;//拉高釋放引腳,以檢測IRD引腳的電平
         TH1 = 0;
         TL1 = 0;//清零T1計數值
         TR1 = 1;//開啟計數
         
         while (IRD)
         {
          if (TH1 > 0x40) //等待超出20ms,則認為是錯誤,強制退出
          {
           break;
          }
         }
         TR1 = 0;//關閉T1計數
         
         return (TH1*256 + TL1);//返回T1計數值
        }
        /**
          * @brief      外部中斷1服務程序(判斷解碼)
          * @param      無
          * @retval     無
          */
        void EXINT1_ISP() interrupt 2 //INT1中斷標號:2
        {
         //NEC協議:引導碼(9ms載波+4.5ms的空閑) 用戶碼-用戶反碼-鍵碼-鍵碼反碼-停止位
         //   比特值0:(560us的載波+560us的空閑) 比特值1:(560us的載波+1.68ms的空閑)
         uint8 i, j;
         uint8 byte;//接收字節
         uint16 time;//獲取時間
         
         //首先判斷引導碼
         time = GetLowCounter();//time*12/11059200*1000ms
         if ((time < 7834) || (time > 8755)) //如果不在8.5ms-9.5ms的范圍就清零外部中斷1標志位,退出中斷
         {
          IE1 = 0;//清零中斷標志
          return;//退出中斷函數
         }
         time = GetHeighCounter();//空閑
         if ((time < 3686) || (time > 4608)) //如果不在4ms-5ms的范圍就退出中斷
         {
          IE1 = 0;//中斷標志硬件置位,軟件清零
          return;
         }
         //引導碼正確,開始接收解碼數據
         
         for (i = 0; i < 4; i++) //接收4個字節數據
         {
          for (j = 0; j < 8; j++) //每個字節8bit
          {
           time = GetLowCounter();//載波時間計數
           if ((time < 424) || (time > 608)) //如果載波時間不在460-660us的范圍則認為是誤碼,退出中斷
           {
            IE1 = 0;
            return;
           }
           //檢測到560us的載波,開始判斷是560us的空閑還是1.68ms的空閑
           time = GetHeighCounter();//空閑
           if ((time > 424) && (time < 608)) //560us的空閑(即比特0)
           {
            //低位在先,逐位右移
            byte >>= 1;//右移一位0
           }
           else if ((time > 1198) && (time < 1659)) //1.68ms的空閑 1.3-1.8ms
           {
            byte >>= 1;//低位在先,先右移出一位
            byte |= 0x80;//再將這一位置1
           }
           else
           {
            //誤碼
            IE1 = 0;
            return;
           }
          }
          Ircode[i] = byte;//循環接收解碼字節數據
          
         }
         //4個字節全部接收完成
         Irflag = 1;
         IE1 = 0;
        }

         /**
          *******************************************************************
          * @file     ds1302.c
          * @author   xr
          * @date     2014年4月10日17:31:07
          * @version  V1.2.3
          * @brief    DS1302底層驅動   單片機STC89C52RC MCU  晶振11.0592MHZ
          *******************************************************************
          */
         
        #include <reg52.h>
        #include "mytype.h"
        //DS1302時鐘線,數據線,和使能引腳位聲明
        sbit DS1302_SCK = P3^5;
        sbit DS1302_SIO = P3^4;
        sbit DS1302_CE  = P1^7;
        /**
          * @brief    DS1302寫一個字節數據
          * @param    待寫入的字節
          * @retval   無
          */
        void DS1302WriteByte(uint8 byte)
        {
         uint8 mask = 0x01;//發送掩碼(低位在前,逐位發送)
         DS1302_SCK = 0;
         
         for (mask = 0x01; mask != 0; mask <<= 1) ////發送掩碼(低位在前,逐位發送)
         {
          if ((mask & byte) == 0)
          {
           DS1302_SIO = 0;
          }
          else
          {
           DS1302_SIO = 1;
          } //將數據準備好
          DS1302_SCK = 1;//先來一個上升沿,從機DS1302進行數據的采樣鎖存
          DS1302_SCK = 0;//再來一個下降沿,主機進行數據的輸出
         }
         //當一個字節的數據發送完成后,主機(即單片機)釋放SIO數據總線,由DS1302進行數據的發送
         DS1302_SIO = 1;
        }
        /**
          * @brief     DS1302讀一個字節的數據
          * @param     無
          * @retval    返回讀取到的數據
          */
        uint8 DS1302ReadByte()
        {
         uint8 byte = 0;//存放待讀取的字節
         uint8 mask = 0x01;//接收掩碼(低位在先,逐位接收)
         DS1302_SCK = 0;
         
         for (mask = 0x01; mask != 0; mask <<= 1) //(低位在先,逐位接收)
         {
          if (DS1302_SIO == 1)
          {
           byte |= mask;//字節byte的相應位置1
          }
          else
          {
           byte &= ~mask;//字節byte的相應位清零
          }
          DS1302_SCK = 1;//先來一個上升沿,主機進行數據采樣接收
          DS1302_SCK = 0;//再來一個下降沿,從機DS1302進行數據輸出
         }
         
         return (byte);
        }
        /**
          * @brief     向DS1302寄存器中寫入數據
          * @param     待寫入數據的寄存器地址reg和待寫入的數據dat
          * @retval    無
        */
        void WriteDS1302(uint8 reg, uint8 dat)
        {
         DS1302_CE = 1;//使能DS1302
         DS1302WriteByte((reg << 1) | 0x80);//寄存器的最高位固定位1第二位為RAM/CLK選擇位,A5-A1為寄存器地址位
                  //且有效位為A3-A1,A0位為讀寫方向位
         DS1302WriteByte(dat);//寫入數據
         DS1302_CE = 0;//關閉片選
         
         DS1302_SIO = 0;//由于本版本的開發板上的DS1302的SIO口沒有加上拉電阻,在釋放SIO后SIO處于
             //非0非1的不穩定狀態,由于IO口的內部輸出通過反相器輸出,給SIO=0則SIO口
             //會輸出一個高電平1,從而保持SIO數據口的穩定!
        }
        /**
          * @brief     讀DS1302寄存器
          * @param     待讀取的寄存器地址reg
          * @retval    讀取到的數據dat
          */
        uint8 ReadDS1302(uint8 reg)
        {
         uint8 dat = 0;
         
         DS1302_CE = 1;//使能片選
         DS1302WriteByte((reg << 1) | 0x81);//左移出一位存放讀寫位,這里選擇讀
         dat = DS1302ReadByte();
         DS1302_CE = 0;
         
         DS1302_SIO = 0;
         
         return (dat);
        }
        /**
          * @brief      DS1302 Burst觸發模式連續寫八個寄存器
          * @param      待寫入數據指針*dat
          * @retval     無
          */
        void DS1302BurstWrite(uint8 * dat)
        {
         uint8 i = 0;
         
         DS1302_CE = 1;//使能片選
         DS1302WriteByte(0xBE);//A5-A1寫入1,觸發DS1302的突發模式連續讀寫八次
         for (i = 0; i < 8; i++)
         {
          DS1302WriteByte(dat[i]);//寫Sec-WP八個寄存器
         }
         DS1302_CE = 0;//關閉片選
         
         DS1302_SIO = 0;//通過反相器SIO口輸出1,保持穩定
        }
        /**
          * @brief     DS1302 Burst模式連續讀取八個寄存器
          * @param     待接收讀取的數據的指針*time
          * @retval    無
          */
        void DS1302BurstRead(uint8 * time)
        {
         uint8 i = 0;
         
         DS1302_CE = 1;//使能片選
         DS1302WriteByte(0xBF);//觸發突發模式讀操作
         for (i = 0; i < 8; i++)
         {
          time[i] = DS1302ReadByte();//讀取Sec-WP八個寄存器
         }
         DS1302_CE = 0;//關閉片選
         
         DS1302_SIO = 0;//使SIO口處于穩定
        }
        /**
          * @brief      DS1302初始化
          * @param      無
          * @retval     無
          */
        void InitDS1302()
        {
         uint8 ch = 0;//用于檢測DS1302停止狀態
         uint8 InitTime[] = {0x56, 0x59, 0x23, 0x10, 0x04, 0x04, 0x14, 0x00};//2014年4月10日23:59:56 WP=0
         
         //讀取秒寄存器
         ch = ReadDS1302(0);
         if ((ch & 0x80) != 0) //檢測秒寄存器的最高位CH,CH為1標志DS1302已經停止運行,要去除寫保護,寫入初始時間
         {
          DS1302BurstWrite(InitTime);//突發模式寫
         }
        }

        /**
          ******************************************************************
          * @file     ds18b20.c
          * @author   xr
          * @date     2014年4月1日21:03:47
          * @version  V1.2.3
          * @brief    溫度傳感器DS18B20檢測溫度值程序
          * @note     單片機STC89C52RC MCU   晶振 11.0592MHZ
          ******************************************************************
          */
         
        #include <reg52.h>
        #include <intrins.h>
        //溫度傳感器引腳
        sbit IO_DS18B20 = P3^2;
        /**
          * @brief    軟件延時xus
          * @param    無
          * @retval   無
          */
        void delayx10us(unsigned int xus)

         do
         {
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
         } while (xus--); //8個_nop_()和函數的進棧出棧時間大約10us
        }
        /**
          * @brief    DS18B20溫度傳感器初始化檢測存在脈沖
          * @param    無
          * @retval   無
          */
        bit ReadDs18B20Ack()
        {
         bit ack; //存放檢測到的DS18B20的存在脈沖
         
         EA = 0;//由于DS18B20的時序時間的要求很高,進出中斷需要十幾個us會影響時序時間
         IO_DS18B20 = 0;//復位脈沖
         delayx10us(60);//持續600us
         IO_DS18B20 = 1;//釋放總線,來檢測DS18B20的存在脈沖
         delayx10us(6);//延時60us后來讀取DS18B20的存在脈沖,這個時候肯定可以讀取到
         ack = IO_DS18B20;
         while (!IO_DS18B20);//等待存在脈沖的結束
         EA = 1;//重新開啟中斷
         
         return ack;//返回存在脈沖
        }
        /**
          * @brief    DS18B20寫一個字節數據
          * @param    待寫入數據 dat
          * @retval   無
          */
        void WriteDs18B20(unsigned char dat)
        {
         unsigned char mask = 0x01;//低位在前,逐位發送
         
         EA = 0;//在發送每一位時必須將總中斷關閉,避免進出中斷時間影響DS18B20的讀寫
         
         for (mask = 0x01; mask != 0; mask <<= 1)
         {
          IO_DS18B20 = 0;//主機拉低
          _nop_();
          _nop_();//延時2us,寫1或0時延時>1us
          if ((mask & dat) == 0)
          {
           IO_DS18B20 = 0;
          }
          else
          {
           IO_DS18B20 = 1;
          }
          delayx10us(6); //延時60-120us等待DS18B20來讀取數據
          IO_DS18B20 = 1;//釋放總線,這時DS18B20會來采樣數據進行寫入
         }
         EA = 1;//寫入一個字節數據完畢,打開總中斷
        }
        /**
          * @brief    讀DS18B20一個字節
          * @param    無
          * @retval   讀取的數據
          */
        unsigned char ReadDs18B20()
        {
         unsigned char mask = 0x01;//低位在前,逐位接收
         unsigned char dat = 0;
         
         EA = 0;//DS18B20在讀取數據前要關閉中斷,避免進出中斷時間,影響讀取
         for (mask = 0x01; mask != 0; mask <<= 1)
         {
          IO_DS18B20 = 0;//讀0或讀1時主機要先拉低>1us再拉高釋放>1us時間,然后主機對DS18B20進行數據的采樣讀取
          _nop_();
          _nop_();
          IO_DS18B20 = 1;
          _nop_();
          _nop_();
          if (IO_DS18B20 == 0)
          {
           dat &= ~mask;//相應位置1
          }
          else
          {
           dat |= mask;//相應位清零
          }
          delayx10us(6);//延時60-120us,等待主機數據的采樣
         }
         EA = 1;//開總中斷
         
         return dat;
        }
        /**
          * @brief    啟動DS18B20溫度轉換,啟動成功則返回應答ack
          * @param    無
          * @retval   返回復位存在脈沖
          */
        bit StartDs18B20()
        {
         bit ack;
         
         ack = ReadDs18B20Ack();//進行DS18B20復位,并讀取DS18B20的存在脈沖
         if (ack == 0)
         {
          WriteDs18B20(0xCC);//跳過ROM的器件地址尋址,因為只有一個DS18B20
          WriteDs18B20(0x44);//啟動溫度轉換
         }
         
         return ~ack;//ack==0則轉換成功
        }
        /**
          * @brief    讀取DS18B20的溫度值
          * @param    無
          * @retval   返回復位存在脈沖的取反值
          */
        bit ReadDs18B20Temp(int * temp) //溫度值保存到temp指針指向的變量中
        {
         bit ack;//保存復位的存在脈沖
         unsigned char lsb, msb;//溫度值的低字節和高字節
         
         ack = ReadDs18B20Ack();//DS18B20復位,并讀取DS18B20的存在脈沖
         if (ack == 0) //復位成功
         {
          WriteDs18B20(0xCC);//跳過ROM多個DS18B20的尋址
          WriteDs18B20(0xBE);//讀暫存寄存器中的數據
          lsb = ReadDs18B20();//因為讀取是從低位向高位讀取的,所以先讀取的是低字節數據
          msb = ReadDs18B20();//讀取高字節數據
          //將溫度值的低字節和高字節數據進行合并成16bit數據,易于計算
          *temp = ((int)(msb) << 8) + lsb;//先將高字節強制轉換成16為數據,將高字節移到高八位,再將低字節放到低八位即可
         }
         
         return ~ack;//ack == 0表示讀取成功
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮