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

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

        基于51單片機串口通信的實時溫度采集系統主要程序

        作者:huqin   來源:本站原創   點擊數:  更新時間:2014年04月04日   【字體:

        測試環境:Keil μVision4
        測試芯片:STC89C52RC
        所需器件:DS18B20
        //
        //Created by XD on 03/04/14
        //
        #include <AT89X52.h>//調用51單片機的頭文件
        #include <Intrins.h>//這個頭文件里有_nop()_;函數的定義
        //---------------------------------------
        //1602液晶相關I/O設置
        sbit E = P1^2; //液晶E接口位定義,對位操作,要先進行位定義,因為AT89X52.h頭文件里沒有相關的位定義
        sbit RW = P1^1;//液晶RW接口位定義,對位操作,要先進行位定義,因為AT89X52.h頭文件里沒有相關的位定義
        sbit RS = P1^0;//液晶RS接口位定義,對位操作,要先進行位定義,因為AT89X52.h頭文件里沒有相關的位定義
        //---------------------------------------
        sbit DS18B20 = P2^0;//DS18B20接口定義
        sbit LED = P2^7;
        //---------------------------------------
        //串口接收寄存器設置
        unsigned char senddata;
        unsigned char USARTbuf;//定義一個8位的變量來暫存串口接收內容
        //---------------------------------------
        //1602液晶寄存器設置
        unsigned char DISbuf;     //設置8位的unsigend char型寄存器用來暫存1602要顯示的內容
        //---------------------------------------
        //DS18B20相關變量
        unsigned char temp1;//小數部分
        unsigned char temp2;//整數部分
        unsigned char code table[16] = {0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};//小數部分顯示的數組
        //---------------------------------------
        //名稱:延時函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void Delay(unsigned int nTimeDelay)
        {
                unsigned int i;//定義無符號變量i
                /*
                 *nTimeDelay自減一次,執行一次下面語句,直到nTimeDelay為0時,
                 *結束循環,一共執行下面語句nTimeDelay次,while語句的循環體只有一句for循環,其沒有循環體。
                 */
                while (nTimeDelay--)
                for (i = 0;i < 125;i++);
        }

        //---------------------------------------
        //名稱:復位DS18B20函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        bit Reset(void)
        {
                unsigned int i;//定義無符號整型變量,用于下面的時序延時
                bit k;//定義bit型變量k,k=1為復位成功,k=0為復位失敗
                
                /*
                 *在初始化時序中,拉低DQ總線至少保持480μs的低電平信號
                 */
                DS18B20 = 0;
                i = 200;        
                while(i > 0)       
                i--;     
                /*
                 *DS18B20 = 1,DQ總線由10K的上拉電阻拉到高電平,
                 *DS18B20在檢測到總線的上升沿之后,
                 *等待15-60μs
                 */
                DS18B20 = 1;
                i = 18;        
                while(i > 0)     
                i--;      
              
                /*
                 *將DQ總線的狀態賦值給k,為1復位成功,為0復位失敗
                 *發出一個60-240μs低電平信號構成的存在脈沖
                 */  
                k = DS18B20;        
                i = 91;        
                while(i > 0)      
                i--;         
                return k;//返回DS18B20是否復位成功標志
        }
        //---------------------------------------
        //名稱:讀一字節函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        unsigned char ReadByte(void)
        {
                unsigned int i;//定義無符號整型變量,用于下面的時序延時
                unsigned char j,buf = 0;
                for(j = 0;j < 8;j++)   //接收8次還原一個字節數據
                {
                        buf = buf >> 1;//接收前,先將接收緩沖區右移
                        DS18B20 = 0;//將DQ總線拉低并保持1μs-15μs,當總線控制器把數據線從高電平拉到低電平時,讀時序開始。   
                        _nop_(); //保持至少1μs-15μs       
                        _nop_(); //保持至少1μs-15μs        
                        _nop_(); //保持至少1μs-15μs       
                        _nop_(); //保持至少1μs-15μs 
                         
                        DS18B20 = 1;//總線被釋放,被10K的上拉電阻拉高,在總線控制器發出讀時序后,
                        //DS18B20通過拉高或拉低總線上來傳輸1或0。當傳輸邏輯0結束后,總線將被釋放,通過上拉電阻回到上升沿狀態。
                        //從DS18B20輸出的數據在讀時序的下降沿出現后15μs內有效。
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        _nop_();         //保持至少1μs-15μs
                        if(DS18B20 == 1) buf |= 0x80;//如果接收到數據為1,從最高位往右移
                        i = 12; //保持至少60μs
                        while(i > 0)//保持至少60μs
                        i--;      //保持至少60μs
                }
                return buf;  //接收緩沖區參數返回
        }
        //---------------------------------------
        //名稱:寫一字節函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void WriteByte(unsigned char dat)
        {
                unsigned int i;//定義無符號整型變量,用于下面的時序延時
                unsigned char j;//定義一個無符號的字符型變量j
                for(j = 0;j < 8;j++)//一個字節為8位,所以循環八次寫操作
                {       
                        //傳過來的要寫的數據dat(這里的dat為形參,實際調用該函數時會發送來實參)
                        //與0x01做與運算,可以獲得數據的最低位,如果if的表達式為真,說明數據的最低
                        //位為1,則進行寫1操作,否則進行寫0操作。 
                        if(dat & 0x01)//進行寫1操作
                        {    
                                DS18B20 =0;//將DQ總線拉低并保持1μs-15μs  
                                _nop_();   //保持至少1μs-15μs 
                                _nop_();   //保持至少1μs-15μs  
                                _nop_();   //保持至少1μs-15μs  
                                _nop_();   //保持至少1μs-15μs
                                  
                                DS18B20 = 1;//總線被釋放,被10K的上拉電阻拉高     
                                i = 14;     //延時操作,使DQ總線保持至少60μs的低電平
                                while(i > 0)//延時操作,使DQ總線保持至少60μs的低電平
                                i--;      //延時操作,使DQ總線保持至少60μs的低電平
                        }
                        else   //進行寫0操作
                        {          
                                DS18B20 = 0;//將DQ總線拉低并保持至少60μs      
                                i = 14;  //延時操作,使DQ總線保持至少60μs的低電平  
                                while(i > 0)//延時操作,使DQ總線保持至少60μs的低電平  
                                i--;     //延時操作,使DQ總線保持至少60μs的低電平
                                       
                                DS18B20 = 1;//總線被釋放,被10K的上拉電阻拉高       
                                _nop_();    //保持至少1μs
                                _nop_();    //保持至少1μs
                                _nop_();    //保持至少1μs
                                _nop_();    //保持至少1μs
                        }
                        dat = dat >> 1;//傳過來的要寫的數據dat做右移一位運算,
                        //之后循環上面的程序8次,8次之后就可以將一個字節的數據寫入DS18B20中
                }
        }
        //---------------------------------------
        //名稱:DS18B20溫度轉換函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        bit Convert(void)
        {  
                if(Reset() == 1)          //復位DS18B20
                { 
                        WriteByte(0xcc);  //寫入跳過序列號命令字 Skip Rom
                        WriteByte(0x44);  //寫入溫度轉換命令字 Convert T
                        return 1;            //啟動溫度轉換成功
                }
                else
                { 
                        return 0;            //啟動溫度轉換失敗
                }
        }
        //---------------------------------------
        //名稱:轉換結束處理函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void ReadFlash(void)
        {  
                unsigned char Lsb,Msb;
                if(Reset() == 1)          //復位DS18B20
                {
                        WriteByte(0xcc);  //寫入跳過序列號命令字 Skip Rom
                        WriteByte(0xbe);  //寫入讀取數據令字 Read Scratchpad
                        Lsb = ReadByte();  //讀出第一個字節暫存于LSB
                        Msb = ReadByte();  //讀出第二個字節暫存于MSB
                        temp1 = Lsb & 0x0f;  //temp1內裝溫度參數的小數部分
                        temp2 = (Lsb >> 4) | (Msb << 4);//temp2內裝溫度參數的整數部
                }
                else
                {
                        temp1 = 0;     //復位失敗,溫度參數清零
                        temp2 = 0;     //復位失敗,溫度參數清零
                }
        }
        //---------------------------------------
        //名稱:1602液晶忙檢測函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void LCD1602_busy(void)
        {
                P0_7 = 1;              //將P0.7置1,為讀狀態做準備
                RS = 0;                //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入
                RW = 1;                //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入
                E = 1;                 //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入
                while(P0_7 == 1);      //由P0.7讀入1,表示1602液晶忙,需要等待
                E = 0;                 //讀完以后,恢復E的電平
        }
        //---------------------------------------
        //名稱:1602寫命令函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void LCD1602_Write_com(unsigned char combuf)
        {
                RS = 0;                //選擇指令寄存器
                RW = 0;                //選擇寫狀態
                P0 = combuf;           //將命令字通過P0口送至DB
                E = 1;                 //E高電平將命令字寫入1602液晶
                E = 0;                 //寫完以后,恢復E的電平
        }
        //---------------------------------------
        //名稱:1602寫命令函數(帶忙檢測)
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void LCD1602_Write_com_busy(unsigned char combuf)
        {
                LCD1602_busy();            //調用忙檢測函數
                LCD1602_Write_com(combuf); //調用忙檢測函數
        }
        //---------------------------------------
        //名稱:1602寫數據函數(帶忙檢測)
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void LCD1602_Write_data_busy(unsigned char databuf)
        {
                LCD1602_busy();      //調用忙檢測函數
                RS = 1;                //選擇數據寄存器
                RW = 0;                //選擇寫狀態
                P0 = databuf;          //將命令字通過P0口送至DB
                E = 1;                 //E高電平將命令字寫入1602液晶
                E = 0;                 //寫完以后,恢復E的電平
        }
        //---------------------------------------
        //名稱:1602液晶顯示地址寫函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void LCD1602_Write_address(unsigned char x,unsigned char y)
        {
                x &= 0x0f;             //列地址限制在0-15間
                y &= 0x01;             //行地址限制在0-1間
                if(y == 0)             //如果是第一行
                LCD1602_Write_com_busy(x | 0x80);        //將列地址寫入
                else                 //如果是第二行
                LCD1602_Write_com_busy((x + 0x40) | 0x80); //將列地址寫入
        }
        //---------------------------------------
        //名稱:1602液晶初始化函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void LCD1602_init(void)
        {
                Delay(150);               //調用延時函數
                LCD1602_Write_com(0x38);       //8位數據總線,兩行顯示模式,5*7點陣顯示
                Delay(50);                //調用延時函數
                LCD1602_Write_com(0x38);       //8位數據總線,兩行顯示模式,5*7點陣顯示
                Delay(50);                //調用延時函數
                LCD1602_Write_com(0x38);       //8位數據總線,兩行顯示模式,5*7點陣顯示
                LCD1602_Write_com_busy(0x38);  //8位數據總線,兩行顯示模式,5*7點陣顯示
                LCD1602_Write_com_busy(0x08);  //顯示功能關,無光標
                LCD1602_Write_com_busy(0x01);  //清屏
                LCD1602_Write_com_busy(0x06);  //寫入新的數據后,光標右移,顯示屏不移動
                LCD1602_Write_com_busy(0x0C);  //顯示功能開,無光標
        }
        //---------------------------------------
        //名稱:1602液晶指定地址顯示函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
        {
                LCD1602_Write_address(x,y);    //先將地址信息寫入
                LCD1602_Write_data_busy(buf);  //再寫入要顯示的數據
        }
        //---------------------------------------
        //名稱:串口發送函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void UARTSendbyte(unsigned char bytebuf)
        {
                SBUF = bytebuf;//緩沖區裝載要發送的字節
                while(TI == 0);//等待發送完畢,TI標志位會置1
                TI = 0;//清零發送完成標志位
         
        }
        //---------------------------------------
        //名稱:主函數
        //作者:XD
        //日期:2014-04-03
        //---------------------------------------
        void main(void) //主函數,單片機啟動后就是從這個函數開始運行的
        {
                LCD1602_init();        //調用1602液晶初始化函數
                //*****USART串口初始化*****
                /*
                 * 串行口控制寄存器SCON
                 * D7--SM0 = 0;SM0 = 0;SM1 = 1;工作方式1
                 * D6--SM1 = 1;SM0 = 0;SM1 = 1;工作方式1
                 * D5--SM2 = 0;接收到單個字節,RI就置位
                 * D4--REN = 1;允許串行口接收
                 * D3--TB8 = 0;方式2和方式3時,為發送的第9位數據,也可以做奇偶校驗位
                 * D2--RB8 = 0;方式2和方式3時,為發送的第9位數據;方式1時,為接收到的停止位
                 * D1--TI = 0;發送中斷標志位,必須由軟件清零
                 * D0--RI = 0;接收中斷標志位,必須由軟件清零
                 */
                SCON = 0x50;
                TMOD|= 0x20;//定時器工作方式2                 
                PCON|= 0x80;//波特率=定時器1溢出率/16                                                        
                TH1 = 0xFD;//10位異步通信方式、1位起始位0、8位數據位和1位停止位1
                TL1 = 0xF3;//波特率19200、11.0592MHz
                TR1 = 1;                                                           
                //**************************
              
                while(1)//死循環
                {                  
                        if(Convert() == 1)//啟動轉換
                        { 
                                ReadFlash();//讀取溫度    
                                if(temp2 > 99) temp2 = 99;//當溫度超過99℃時,temp2被賦值99,限制最高測量溫度為99攝氏度  
                                if(temp1 > 15) temp1=0;      
                                LCD1602_Disp(0,1,temp2 / 10 + '0');  //溫度整數部分十位   
                                LCD1602_Disp(1,1,temp2 % 10 + '0');  //溫度整數部分個位
                                LCD1602_Disp(2,1,'.');  //. 
                                LCD1602_Disp(3,1,table[temp1] + '0');  //溫度小數A部分
                                LCD1602_Disp(4,1,0xdf);   //.
                                LCD1602_Disp(5,1,0x43);   //C
                        }
                        UARTSendbyte(temp2);   
                }
        }

        關閉窗口

        相關文章

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