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

QQ登錄

只需一步,快速開(kāi)始

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

用1602LCD與DS18B20設(shè)計(jì)的溫度報(bào)警器

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:110638 發(fā)表于 2016-3-24 21:16 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
#include <reg52.h>
#include<intrins.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
sbit RW = P1^1;          //定義LCD的讀、寫(xiě)選擇端
sbit RS = P1^0;           //定義LCD的數(shù)據(jù)、命令選擇端
sbit EN = P1^2;                 //定義LCD的使能信號(hào)端
sbit DS = P3^5;                 //定義DS18B20的IO口
sbit L=P1^3;                 //綠燈
sbit H=P1^4;                 //紅燈
sbit LS=P3^4;                 //蜂鳴器
sbit k1=P2^4;                 //顯示64位的ROM
sbit k2=P2^3;                 //顯示當(dāng)前溫度
sbit k3=P2^0;                 //顯示溫度上限及下線,并支持調(diào)節(jié)
sbit k4=P2^1;                 //        上限加
sbit k5=P2^2;                  //        下限減
uchar k=2;                         //當(dāng)前溫度顯示標(biāo)志位
uchar table0[] = " Current Temp : ";         //當(dāng)前溫度
uchar table1[] = " -- ROM CODE -- ";         //顯示DS18B20的ROM
uchar table2[] = "ALARM TEMP Hi Lo";         //顯示上下限溫度
uchar table3[] = "Hi:    Lo:      ";
uchar table4[] = {0,0,0,0,0,0,0,0};
uchar tempHL[] = { 20, 1};                                 //上下限溫度的初始值                                                                                  
void delayms(uint a)     //延時(shí)函數(shù)
{
    uint i,j;
    for(i = a; i > 0; i--) for(j = 100; j > 0; j--);
}
void writecom(uchar com)  //寫(xiě)地址,也就是顯示的數(shù)據(jù)的位置
{
        RS = 0;                
        P0 = com;
        EN = 1;
        delayms(1);
        EN = 0;
}
void writedata(uchar dat) //寫(xiě)數(shù)據(jù),也就是顯示的數(shù)據(jù)
{
        RS = 1;
        P0 = dat;
        EN = 1;
        delayms(1);
        EN = 0;
}
void init()                   //LCD初始化
{
        RW = 0;
        writecom(0x38);          //16*2顯示,5*7點(diǎn)陣
        writecom(0x0c);
        writecom(0x06);
        writecom(0x01);   //清除LCD的顯示內(nèi)容
}

void writestring(uchar * str, uchar length)           //寫(xiě)數(shù)據(jù)的過(guò)度函數(shù)。length:長(zhǎng)度
{
    uchar i;
    for(i = 0; i < length; i++)
    {
         writedata(str[i]);
     }
}
void delay(uint num)        //延時(shí)函數(shù)
{
  while( --num );
}

DSinit(void)        //初始化ds1820  
{  
     DS= 1;      //DS復(fù)位
     delay(8);    //稍做延時(shí)
     DS= 0;      //將DS拉低
     delay(90);   //精確延時(shí) 大于 480u
     DS= 1;       //拉高總線
     delay(110);
     DS= 1;

}

uchar read_bit(void)     //讀一位(bit)
{
uchar i;
DS= 0;                      //將DS拉低開(kāi)始讀時(shí)間隙
DS= 1;                         // then return high
for (i=0; i<3; i++);         // 延時(shí)15μs
return(DS);                         // 返回 DS線上的電平值
}

uchar readbyte()        // 讀一個(gè)字節(jié)  
{
uchar i = 0;
uchar dat = 0;
for (i=0;i<8;i++)
{                                  // 讀取字節(jié),每次讀取一個(gè)字節(jié)
if(read_bit()) dat|=0x01<<i;           // 然后將其左移
    delay(4);
  }
    return (dat);
}

void write_bit(char bitval)       //寫(xiě)一位  
{
DS= 0;                                        // 將DS拉低開(kāi)始寫(xiě)時(shí)間隙
if(bitval==1) DS=1;          // 如果寫(xiě)1,DS返回高電平
delay(5);                                       // 在時(shí)間隙內(nèi)保持電平值,
DS= 1;                      // delay函數(shù)每次循環(huán)延時(shí)16μs,因此delay(5) = 104μs
}       

void writebyte(uchar dat)  //寫(xiě)一個(gè)字節(jié)
{
  uchar i = 0;
  uchar temp;
   for (i=0; i<8; i++)         // 寫(xiě)入字節(jié), 每次寫(xiě)入一位
   {

   temp = dat>>i;                
   temp &= 0x01;                
   write_bit(temp);

  }
  delay(5);
}         
void sendchangecmd()           //DS18B20?開(kāi)始獲取溫度并轉(zhuǎn)換
{
    DSinit();                         //DS18B20復(fù)位
    delayms(1);                      
    writebyte(0xcc);           //寫(xiě)跳過(guò)讀ROM指令
    writebyte(0x44);           //寫(xiě)溫度轉(zhuǎn)換指令
}

void sendreadcmd()                   //讀取寄存器中存儲(chǔ)的溫度數(shù)據(jù)
{
    DSinit();                           //DS18B20復(fù)位
    delayms(1);
    writebyte(0xcc);            //寫(xiě)跳過(guò)讀ROM指令
    writebyte(0xbe);            //讀取暫存器的內(nèi)容
}         

int gettmpvalue()
{
    uint tmpvalue;
    float t;
    uchar low, high;
    sendreadcmd();                   //讀取寄存器中存儲(chǔ)的溫度數(shù)據(jù)
    low = readbyte();            //讀取低八位
    high = readbyte();           //讀取高八位
    tmpvalue = high;
    tmpvalue <<= 8;                   //高八位左移八位
    tmpvalue |= low;       //兩個(gè)字節(jié)組合為1個(gè)字
    t = tmpvalue * 0.0625 * 100;   //分辨率為0.0625,在此將值擴(kuò)大100倍
    return t;
}

void display(int v)            //顯示子函數(shù)
{
    uchar i;
    uchar datas[] = {0, 0, 0, 0, 0, 0, 0, 0};  //定義緩存數(shù)組datas
    uint tmp = abs(v);                                                   //abs是求絕對(duì)值函數(shù)
    datas[0] = tmp % 10000 / 1000;
    datas[1] = tmp % 1000 / 100;
    datas[2] = tmp % 100 / 10;
    datas[3] = tmp % 10;
        datas[4] = 80;                                                //空格的前30的ASCALL碼
        datas[5] = 175;                                                //溫度符號(hào)的前30的ASCALL碼
        datas[6] = 19;                                                //C的前30的ASCALL碼
    writecom(0xc0+3);
    if(v < 0)                                  //當(dāng)V小于0則輸出負(fù)號(hào)
    {
        writestring("- ", 2);
   }
    else
    {
       writestring("+ ", 2);          //當(dāng)V大于0則輸出正號(hào)
    }
    for(i = 0; i != 7; i++)
    {
        writedata('0'+datas[i]);   //顯示溫度
        if(i == 1)
        {
           writedata('.');                  //顯示溫度的小數(shù)點(diǎn)
        }
    }

}

void Read_RomCord()                   //讀取64位序列碼
{
     unsigned char j;
     DSinit();
     writebyte(0x33);      // 讀序列碼的操作
     for (j = 0; j < 8; j++)
         {
          table4[j] = readbyte();
         }
}

void Disp_RomCode()                           //數(shù)據(jù)轉(zhuǎn)換與顯示
{
   uchar j,i;
   writecom(0xc0);         //LCD第二行初始位置
   for(j=0;j<8;j++)
   {
    i=((table4[j]&0xf0)>>4);
    if(i>9)
     { i=i+0x37;}
    else{i=i+0x30;}         
    writedata(i);        //高位數(shù)顯示
    i=(table4[j]&0x0f);
    if(i>9)
     {i=i+0x37;}
    else {i=i+0x30;}         
    writedata(i);        //低位數(shù)顯示
   }
}

void lcd_display()                 //按鍵掃描
{
  uchar i,m;
  uchar hl[]={0, 0, 0, 0, 0};
  if(k1 == 0) k = 1;
  if(k2 == 0) k = 2;                                                                                                                                                                                          
  if(k3 == 0) k = 3;
  if(tempHL[0]<=gettmpvalue()/100)
       delayms(100),LS=!LS,H=~H;
  else
       LS=1,H=1;
  if(m==1)
{
          if(tempHL[1]>=gettmpvalue()/100)
               delayms(100),LS=!LS,L=~L;
          else
               LS=1,L=1;
  }
  switch(k)
  {
        case 1:                                                       //顯示64位的ROM
                   writecom(0x01);
                   writecom(0x80);
                   writestring(table1, 16);
                   Read_RomCord();           //讀取64位序列碼
                   Disp_RomCode();                 //顯示64位序列
           delayms(500);                         //溫度轉(zhuǎn)換時(shí)間需要750ms以上
                   break;
        case 2:                                                 //顯示當(dāng)前溫度
                   delayms(750);                         //溫度轉(zhuǎn)換時(shí)間需要750ms以上
                   sendchangecmd();
                   writecom(0x01);
                   writecom(0x80);
                   writestring(table0, 16);
                   display(gettmpvalue());
                   break;
        case 3:                                                     //顯示溫度上限及下線,并支持調(diào)節(jié)
                   writecom(0x80);
                   writestring(table2, 16);
                   writecom(0xC0);
                   writestring(table3, 16);
                   if(k4==0) {tempHL[0]++;if(m==1) tempHL[1]++;if(m==0){tempHL[1]--;if(tempHL[1]==0)m=1;}delayms(100);}
                   if(k5==0) {tempHL[0]--;if(m==0) tempHL[1]++;if(m==1){tempHL[1]--;if(tempHL[1]==0)m=0;}delayms(100);}
                   hl[0] = tempHL[0] / 10;
                   hl[1] = tempHL[0] % 10;
                   if(m==1) hl[2] = 80;
                   if(m==0) hl[2] = 128;
                   hl[3] = tempHL[1] / 10;
                   hl[4] = tempHL[1] % 10;
                   writecom(0xC0+4);
                   for(i = 0; i != 2; i++)
                    {
                        writedata('0'+hl[i]);        //顯示上限溫度
                         }
                   writecom(0xC0+11);
                   for(i = 2; i != 5; i++)
                    {
                        writedata('0'+hl[i]);         //顯示下限溫度
                         }
                   break;
  }
}
void main()
{
        sendchangecmd();                        //讀取寄存器中存儲(chǔ)的溫度數(shù)據(jù)
    init();                                                //LCD初始化
    writecom(0x80);                                //選擇LCD第一行
    writestring(table0, 16);        //顯示當(dāng)前溫度的英文字母
    while(1)
    {
        lcd_display();                         //掃描按鍵
    }
}


評(píng)分

參與人數(shù) 2黑幣 +60 收起 理由
send + 10 贊一個(gè)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

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

使用道具 舉報(bào)

沙發(fā)
ID:1 發(fā)表于 2016-3-27 19:44 | 只看該作者
樓主能分享個(gè)電路圖嗎?
回復(fù)

使用道具 舉報(bào)

板凳
ID:121641 發(fā)表于 2016-5-24 22:33 | 只看該作者
樓主棒!我已經(jīng)仿真好了,坐等焊板子
回復(fù)

使用道具 舉報(bào)

地板
ID:97714 發(fā)表于 2016-5-28 09:33 | 只看該作者
感謝樓主,正需要這類資料
回復(fù)

使用道具 舉報(bào)

5#
ID:125111 發(fā)表于 2016-6-4 20:32 | 只看該作者
分地區(qū)二姐夫脾氣額閥門(mén)哦我去
回復(fù)

使用道具 舉報(bào)

6#
ID:184584 發(fā)表于 2017-4-19 19:48 | 只看該作者
能不能把仿真電路圖發(fā)一下??
回復(fù)

使用道具 舉報(bào)

7#
ID:184584 發(fā)表于 2017-4-19 19:48 | 只看該作者
能不能把仿真電路圖發(fā)一下??
回復(fù)

使用道具 舉報(bào)

8#
ID:170098 發(fā)表于 2017-5-16 15:27 | 只看該作者
我覺(jué)得還是發(fā)個(gè)圖,這樣學(xué)習(xí)起來(lái)也比較快
回復(fù)

使用道具 舉報(bào)

9#
ID:830316 發(fā)表于 2020-11-6 18:54 | 只看該作者
15966025623 發(fā)表于 2016-5-28 09:33
感謝樓主,正需要這類資料

求分享一下。謝謝
回復(fù)

使用道具 舉報(bào)

10#
ID:312000 發(fā)表于 2020-12-1 10:25 | 只看該作者
有沒(méi)有原理圖
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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