找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 3645|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

AT89C51單片機(jī)DS18B20溫度檢測(cè)應(yīng)用設(shè)計(jì) Proteus仿真

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:623141 發(fā)表于 2020-6-23 16:51 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
一、設(shè)計(jì)目的
1、學(xué)習(xí)并掌握One-Wire總線的工作原理
2、學(xué)習(xí)并掌握DS18B20溫度傳感器工作原理;
3、學(xué)習(xí)并掌握溫度采集程序設(shè)計(jì)方法;
4、學(xué)習(xí)并掌握串行通信程序設(shè)計(jì);
二、實(shí)驗(yàn)設(shè)備
1、計(jì)算機(jī);
2、單片機(jī)開發(fā)板;
3、Keil C51編程軟件;
4、Proteus仿真軟件;
三、設(shè)計(jì)內(nèi)容
1、完成功能
(1)檢測(cè)溫度并顯示一位小數(shù)(XX.X),
(2)將溫度值通過(guò)串口發(fā)送到上位機(jī)串口調(diào)試助手,
(3)上位機(jī)串口調(diào)試助手顯示(文本形式顯示):“T:XX.X”回車(XX.X是溫度值,逐行顯示)
2、硬件電路原理圖
3、設(shè)計(jì)程序(5號(hào)、宋體、單倍行距、分兩欄,要求程序設(shè)計(jì)規(guī)范化,添加必要的說(shuō)明和注釋)


/****************************************************************
* 實(shí) 驗(yàn) 名 :DS18B20溫度實(shí)驗(yàn)
* 實(shí)驗(yàn)說(shuō)明 :數(shù)碼管顯示當(dāng)前溫度
* 連接方式 :將DS18B20插到數(shù)字溫度檢測(cè)模塊的U5上(注意方向),DS_RD接P2.2
*****************************************************************/
//包含文件
#include<reg52.h>
#include<intrins.h>
//宏定義
#defineBAUD 9600        //波特率設(shè)置,bps
#defineFOSC 11059200L //晶振設(shè)置,默認(rèn)使用11.0592MHz
//#defineFOSC 12000000L //晶振設(shè)置,使用12M Hz
//#defineFOSC 24000000L //晶振設(shè)置,使用24M Hz
//IO接口定義
#defineLED_PORT P0
sbitwela_1 = P2^4;
sbitwela_2 = P2^5;
sbitwela_3 = P2^6;
sbitwela_4 = P2^7;
sbitDQ = P2^2;              //定義DS18B20端口DQ
//全局變量定義
unsignedchar temperature;
unsignedchar temperature_dec;
unsignedchar qian,bai,shi,ge;
//LED顯示字模 0-F 共陽(yáng)模式
unsignedcode table[]={0Xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsignedchar RomCode[8];   //DS18B20中的RomCode
/*******************************************************************************
* 函 數(shù) 名 :Delayms
* 函數(shù)功能 :實(shí)現(xiàn) ms級(jí)的延時(shí)
* 輸    入:ms
* 輸    出:無(wú)
*******************************************************************************/
voidDelayms(unsigned int ms)
{
    unsigned int i,j;
    for(i=0;i<ms;i++)
    #if FOSC == 11059200L
       for(j=0;j<114;j++);
    #elif FOSC == 12000000L
     for(j=0;j<123;j++);
    #elif FOSC == 24000000L
       for(j=0;j<249;j++);
    #else
       for(j=0;j<114;j++);
    #endif
}
/*******************************************************************************
* 函 數(shù) 名 :LEDdisplay
* 函數(shù)功能 :循環(huán)顯示各個(gè)位上的數(shù)據(jù)
* 輸    入:num要顯示的數(shù)據(jù)
* 輸    出:無(wú)
*******************************************************************************/
voidLEDdisplay()
{   
    wela_1 = 1;   //關(guān)閉所有數(shù)碼管
    wela_2 = 1;
    wela_3 = 1;
    wela_4 = 1;
    wela_4=0; //顯示千位
    LED_PORT=table[qian];
    Delayms(1);
    LED_PORT = 0xff;
    wela_4=1;
   
    wela_3=0; //顯示百位
    LED_PORT=table[bai];
    Delayms(1);
    LED_PORT = 0xff;
    wela_3=1;
   
    wela_2=0; //顯示十位
    LED_PORT=table[shi] & 0x7F;
    Delayms(1);
    LED_PORT = 0xff;
    wela_2=1;
   
    wela_1=0; //顯示個(gè)位
    LED_PORT=table[ge];
    Delayms(1);
    LED_PORT = 0xff;
}
/*******************************************************************/
/*us級(jí)延時(shí)函數(shù)  執(zhí)行一次US--所需6.5us進(jìn)入一次函數(shù)需要11.95us                                    */
/*******************************************************************/
voidDelay(unsigned int num)
{
    while( --num ) ;
}
/*******************************************************************/
/*初始化ds1820                                                    */
/*******************************************************************/
bitInit_DS18B20(void)
{
    bit presence;
    DQ = 1;     //DQ復(fù)位
    Delay(8);   //稍做延時(shí)
    DQ = 0;     //單片機(jī)將DQ拉低
    Delay(90);  //精確延時(shí) 大于 480us
    DQ = 1;     //拉高總線
    Delay(4);   //稍做延時(shí)   
    presence = DQ; //如果=0則初始化成功 =1則初始化失敗
    Delay(20); //稍做延時(shí)
    DQ = 1;
    return(presence); //返信號(hào),0=presence,1= no presence
}
/*******************************************************************/
/* 讀一個(gè)字節(jié)                                                     */
/*******************************************************************/
unsignedchar ReadOneChar(void)
{
    unsigned char i = 0;
    unsigned char dat = 0;
    for (i = 8; i > 0; i--)//循環(huán)8次,通過(guò)dat變量的依次右移裝入8位數(shù)據(jù)
    {
       DQ = 0;        //單片機(jī)將DQ拉低
       dat >>= 1;     //dat右移1位,準(zhǔn)備讀取1位數(shù)據(jù)
       DQ = 1;        //單片機(jī)將DQ拉高      
       if(DQ)        //判斷DQ狀態(tài),DQ=1則dat的最高位為1,DQ=0則dat的最高位為0
           dat |= 0x80;//dat或10000000,控制dat的最高位:DQ=1則為1,DQ=0則為0
       //proteus仿真設(shè)置為Delay(40)
       Delay(40);     //延時(shí)
       //Delay(4);
    }
    return (dat);      //返回值dat即為讀到的一字節(jié)數(shù)據(jù)
}
/*******************************************************************/
/* 寫一個(gè)字節(jié)                                                     */
/*******************************************************************/
void  WriteOneChar(unsigned char dat)
{
    unsigned char i = 0;
    for (i = 8; i > 0; i--)//循環(huán)8次,通過(guò)dat變量的依次右移發(fā)出8位數(shù)據(jù)
    {
       DQ = 0;        //單片機(jī)將DQ拉低
       DQ = dat&0x01; //DQ=dat與00000001,則DQ=dat的最低位(0或1)
       Delay(5);      //延時(shí)     
       DQ = 1;        //單片機(jī)將DQ拉高
       dat>>=1;       //dat右移1位,準(zhǔn)備取下一位數(shù)據(jù)
    }
}
/*******************************************************************/
/* 溫度報(bào)警值寫入DS18B20                                           */
/*******************************************************************/
voidWrite_Temperature_alarm(unsigned char Temp_h , unsigned char Temp_l)
{
    Init_DS18B20();           //初始化
    WriteOneChar(0xCC);       //跳過(guò)讀序列號(hào)的操作
    WriteOneChar(0x4e);       //將設(shè)定的溫度報(bào)警值寫入DS18B20
    WriteOneChar(Temp_h);      //寫TH
    WriteOneChar(Temp_l);      //寫TL
    WriteOneChar(0x7f);       //12位精確度
    Init_DS18B20();           //初始化
    WriteOneChar(0xCC);       //跳過(guò)讀序號(hào)列號(hào)的操作
    WriteOneChar(0x48);       //把暫存器里的溫度報(bào)警值拷貝到EEROM
}
/*******************************************************************/
/* 讀取64位序列碼                                                 */
/*******************************************************************/
voidRead_RomCord(void)
{
    unsigned char j;
    Init_DS18B20();           //初始化
    WriteOneChar(0x33);       // 讀序列碼的操作命令
    for (j = 0; j < 8; j++)
    {
       RomCode[j] = ReadOneChar() ;
    }
}
/*******************************************************************/
/*DS18B20的CRC8校驗(yàn)程序                                            */
/*******************************************************************/
unsignedchar CRC8()
{
    unsigned char i,x;
    unsigned char crcbuff,crc;
    crc=0;
    for(x = 0; x <8; x++)
    {
       crcbuff=RomCode[x];
       for(i = 0; i < 8; i++)
       {
           if(((crc ^ crcbuff)&0x01)==0)
              crc >>= 1;
           else
           {
              crc ^= 0x18;   //CRC=X8+X5+X4+1
              crc >>= 1;
              crc |= 0x80;
           }         
           crcbuff >>= 1;      
       }
    }
    return crc;
}   
/*******************************************************************/
/* 讀取溫度                                                       */
/*******************************************************************/
unsignedchar* Read_Temperature(void)
{
    //unsigned char  i;
    unsigned char temp_comp[2];
    unsigned char temp_data[2];
    unsigned char temp_alarm[2];   
    //unsigned int t;
    Init_DS18B20();           //初始化   
    WriteOneChar(0xCC);       //跳過(guò)讀序列號(hào)的操作
    WriteOneChar(0x44);       //啟動(dòng)溫度轉(zhuǎn)換
    Init_DS18B20();           //初始化
    //實(shí)際器件:匹配ROM或跳過(guò)序列號(hào)均可   
    //WriteOneChar(0x55);         //匹配ROM命令
    //for(i=0;i<8;i++)
    //  WriteOneChar(RomCode);
    //proteus仿真:跳過(guò)序列號(hào)
    WriteOneChar(0xCC);           //跳過(guò)讀序列號(hào)的操作   
    WriteOneChar(0xBE);           //讀取溫度寄存器
      
    temp_data[0] = ReadOneChar();   //溫度低8位
    temp_data[1] = ReadOneChar();   //溫度高8位
    temp_alarm[0] = ReadOneChar();  //溫度報(bào)警TH
    temp_alarm[1] = ReadOneChar();  //溫度報(bào)警TL  
    temp_comp[0]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//取溫度整數(shù)值
    temp_comp[1] = temp_data[0]&0x0f;//讀取小數(shù)
    //課件程序:
    //t=temp_data[1];
    //t<<=8;
    //t=t|temp_data[0];
    //temp_comp=t*0.0625;  
    return &temp_comp;                                                   
}
/*******************************************************************************
* 函 數(shù) 名 :UsartConfiguration
* 函數(shù)功能 :串口設(shè)置
* 輸    入:無(wú)
* 輸    出:無(wú)
*******************************************************************************/
voidUsartConfiguration()
{
    SCON = 0X50;   //設(shè)置為工作方式1:10位異步收發(fā)器
    TMOD |= 0x20;  //設(shè)置計(jì)數(shù)器工作方式2:8位自動(dòng)重裝計(jì)數(shù)器  
    PCON = 0X80;   //波特率加倍:SMOD = 1
    TH1 = 256 -(FOSC/12/32/(BAUD/2)); //計(jì)算定時(shí)器1初值
    TL1 = 256 -(FOSC/12/32/(BAUD/2));
    TR1 = 1;//啟動(dòng)定時(shí)器T1
    ES=1;  //開串口中斷
    EA = 1; //開總中斷
}
/*******************************************************************************
* 函 數(shù) 名 :UsartSendTemper
* 函數(shù)功能 :串口發(fā)送溫度
* 輸    入:無(wú)
* 輸    出:無(wú)
*******************************************************************************/
voidUsartSendTemper()
{
    //發(fā)送 T
       TI = 0;          //清除發(fā)送中斷標(biāo)志位TI
       SBUF='T';      //收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動(dòng)串口發(fā)送
       while(!TI);      //等待發(fā)送數(shù)據(jù)完成   
    //發(fā)送 :
       TI = 0;          //清除發(fā)送中斷標(biāo)志位TI
       SBUF=':';      //收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動(dòng)串口發(fā)送
       while(!TI);      //等待發(fā)送數(shù)據(jù)完成
    //發(fā)送溫度十位
       TI = 0;          //清除發(fā)送中斷標(biāo)志位TI
       SBUF=temperature/10+'0';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動(dòng)串口發(fā)送
       while(!TI);      //等待發(fā)送數(shù)據(jù)完成
    //發(fā)送溫度個(gè)位
       TI = 0;          //清除發(fā)送中斷標(biāo)志位TI
       SBUF=temperature%10+'0';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動(dòng)串口發(fā)送
       while(!TI);      //等待發(fā)送數(shù)據(jù)完成
    //發(fā)送小數(shù)點(diǎn)
       TI = 0;          //清除發(fā)送中斷標(biāo)志位TI
       SBUF='.';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動(dòng)串口發(fā)送
       while(!TI);      //等待發(fā)送數(shù)據(jù)完成
   
    //發(fā)送溫度小數(shù)位
       TI = 0;          //清除發(fā)送中斷標(biāo)志位TI
       SBUF=temperature_dec+'0';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動(dòng)串口發(fā)送
       while(!TI);      //等待發(fā)送數(shù)據(jù)完成
      
    //發(fā)送換行符
       TI = 0;          //清除發(fā)送中斷標(biāo)志位TI
       SBUF='\n'; //收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動(dòng)串口發(fā)送
       while(!TI);      //等待發(fā)送數(shù)據(jù)完成
       TI=0;   
           
}
/*******************************************************************/
/* 主函數(shù)                                                         */
/*******************************************************************/
voidmain(void)
{
    unsigned char* temp;
    int count = 0;
    temperature = 0;
    //proteus仿真:不讀取64位序列碼   
    //Read_RomCord();   //讀取64位序列碼
    UsartConfiguration();//串口配置
    while(1)
    {
       if(count >= 200)//采集周期1s
       {
           temp = Read_Temperature();  //讀取溫度
           temperature = temp[0];
           temperature_dec = temp[1]*0.625;
           count= 0;
           UsartSendTemper();//串口發(fā)送溫度      
       }
       qian=temperature/100;
       bai=temperature%100/10;
       shi=temperature%10;
       ge=temperature_dec;           
       LEDdisplay();//顯示溫度
      
       count++;
    }
}


四、本任務(wù)中的幾個(gè)功能如何實(shí)現(xiàn)?(說(shuō)明設(shè)計(jì)思路)
設(shè)計(jì)思路:
1.       溫度讀取和數(shù)碼管顯示套用DS18B20溫度讀取例程改寫,
2.       串口發(fā)送程序采用查詢法。
功能實(shí)現(xiàn):
溫度讀。
核心為OneWire總線的使用,嚴(yán)格對(duì)應(yīng)時(shí)序圖編程,實(shí)現(xiàn)初始化、讀、寫一個(gè)字節(jié),要注意延時(shí)函數(shù)的控制。
顯示小數(shù):
將原來(lái)的讀函數(shù)改為usigned char*類型,返回一個(gè)長(zhǎng)度為2的數(shù)組,分別存儲(chǔ)溫度的整數(shù)值和小數(shù)值。
將原來(lái)的數(shù)碼管顯示函數(shù)前三個(gè)顯示整數(shù)、最后一個(gè)數(shù)碼管顯示小數(shù)。小數(shù)處理和整數(shù)取完對(duì)應(yīng)位之后的下一步處理有區(qū)別(小數(shù)需要乘0.625)
發(fā)送溫度:
發(fā)送時(shí)候要一字節(jié)一字節(jié)地發(fā)送。溫度處理之后,還要加‘0’將數(shù)字轉(zhuǎn)化為對(duì)應(yīng)ASCII值。

DS18B20溫度檢測(cè)應(yīng)用設(shè)計(jì).rar

5.14 MB, 下載次數(shù): 93, 下載積分: 黑幣 -5

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:843576 發(fā)表于 2020-11-16 20:44 | 只看該作者
我想請(qǐng)問一下,如果吧AC89C51換成STC89C51程序可以照樣使用嗎?
回復(fù)

使用道具 舉報(bào)

板凳
ID:839551 發(fā)表于 2020-12-29 00:32 | 只看該作者
不對(duì)啊 負(fù)數(shù)
回復(fù)

使用道具 舉報(bào)

地板
ID:800086 發(fā)表于 2020-12-29 08:59 | 只看該作者
這個(gè)簡(jiǎn)單也,實(shí)用。剛?cè)腴T的可以學(xué)習(xí)一下
回復(fù)

使用道具 舉報(bào)

5#
ID:863465 發(fā)表于 2020-12-31 10:29 來(lái)自觸屏版 | 只看該作者
你好,我想問一下我接收不到數(shù)據(jù),是怎么回事?
回復(fù)

使用道具 舉報(bào)

6#
ID:863465 發(fā)表于 2020-12-31 10:29 來(lái)自觸屏版 | 只看該作者
不顯示小數(shù)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表