久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計實例 >> 瀏覽文章

溫度控制led燈灰度變化c51

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時間:2011年02月17日   【字體:

18b20時序要求比較嚴(yán)格。
所遇問題:測出溫度值不準(zhǔn)確,不停的從255于實際溫度值跳變。
解決方法:在讀取溫度值時,關(guān)掉中斷。不過燈有一些閃。
該程序所測溫度的精度不能達(dá)到0.5,需要稍微改動。
不知道1602穩(wěn)定了沒,明天再試一次。
反應(yīng)好像還不夠靈敏。

#include "reg52.h"   
#include<intrins.h> 
#define uchar unsigned char 
//溫度傳感器與單片機(jī)接口為 P0.1 
sbit DQ=P1^5; 
// 
sbit E=P0^7; 
sbit RW=P0^6; 
sbit RS=P0^5; 
sbit LED=P3^5; 
//sbit lcd_flag=P2^7;             //定義是lcd否忙標(biāo)志 
sbit P1_7 = P3 ^ 7;                              // 控制LED11               
sbit P1_6 = P3 ^ 6;                              // 控制LED10   
sbit P1_2 = P3 ^ 4;   
// 
uchar timer=0x00; //字節(jié)變量timer用于計時,每計數(shù)器記滿100次,就采樣一次溫度 
uchar chars[]={"GYRGB.Liuzhou^_^"};      // 液晶顯示第一行 
uchar chars2[]={"Welcome!"};            //液晶顯示第二行         
             
uchar  scale_0;                         //燈光灰度 
/////////////////////////////// 
//各個功能子函數(shù) 
/////////////////////////////// 
void delay(void);       //18b20溫度轉(zhuǎn)換后所需的延時 
void delay1(void);      //動態(tài)數(shù)碼管顯示所需的較短的延時 
unsigned char Read18B20(void);  //讀18b20子函數(shù)   
void Write18B20(uchar ch);       //寫18b20子函數(shù) 
void Delay15(uchar n);     //讀寫所需的最基本單位時間的延時 
void Init18B20(void);     //初始化18b20函數(shù) 

///////////////////////////// 
//新增的液晶顯示程序 
///////////////////////////// 
void WriteLCDcom(uchar ch); 
void WriteLCDdat(uchar ch); 
void main(void) 
{ 
uchar i,tl,th;     //變量i用于循環(huán)計數(shù),tl和th用于獲得二進(jìn)制溫度值 
uchar temp;      //變量temp用于存放有效的溫度值 
uchar bith,bitt,biti,bitz;  //將要顯示在數(shù)碼管上的百位、十位、個位和十分位的碼值 
unsigned  int   n; 

RCAP2H =0xFE;                                  // 賦T2的預(yù)置值,溢出1次是1/2000秒鐘 
    RCAP2L =0x0C; 
    ET2=1;                                         // 打開定時器2中斷 
EA=1; //總中斷允許 
    TR2=1;                                      // 啟動定時器2 

WriteLCDcom(0x01);        //清屏 
WriteLCDcom(0x38);       
WriteLCDcom(0x0c); 
WriteLCDcom(0x06);   
WriteLCDcom(0x80); 
for(i=0;i<16;i++) 
  WriteLCDdat(chars); 
WriteLCDcom(0xc0); 
for(i=0;i<8;i++) 
  WriteLCDdat(chars2); 
WriteLCDcom(0xce); 
WriteLCDdat(0xdf); 
WriteLCDdat(0x43); 

//////////////////////////////// 
//12M晶振,16位計數(shù)器 
//溢出時間 65536us約等于65.5ms 
//溢出100次采樣溫度一次,采樣周期6.5秒 
//////////////////////////////// 
while(1) 
{ 

   LED=1; 
   Init18B20(); //復(fù)位18b20,每次復(fù)位18b20都是默認(rèn)的12位轉(zhuǎn)換精度 
   Write18B20(0xcc);//向18b20寫入跳過激光rom操作 
   _nop_();   //稍等片刻 
   Write18B20(0x44);//命令18b20開始溫度的測量以及模數(shù)轉(zhuǎn)換 
   
   delay();   //18b20轉(zhuǎn)換時間較長應(yīng)該等待稍長時間 
   
   Init18B20();  //每一次對18b20的讀寫都要先復(fù)位 
   TR2=0;           //18b20對時序要求比較嚴(yán)格,因此在讀取溫度時要關(guān)中斷,否則測的溫度值會出錯 
   Write18B20(0xcc);//照例跳過ROM的操作 
   _nop_();   //等 
   Write18B20(0xbe); //讀18b20的溫度數(shù)據(jù),可以連續(xù)讀5個字節(jié) 
   _nop_();    //等 
   tl=Read18B20();   //讀第一個字節(jié),里面是12位有效數(shù)字的低八位 
   th=Read18B20();   //讀第二個字節(jié),是擴(kuò)展的符號位和有效值的高四位 
   TR2=1; 
   Init18B20(); 
   temp=(th<<4)+(tl>>4); 
//實際上,temp=(th<<4)+(tl>>4)這個式子得到的是只包含了數(shù)整值的溫度值 
//th向左移4位,拋棄了擴(kuò)展的符號位;tl向右移4位,拋棄了4位小數(shù)位 
   bith=temp/100;  //得到百位數(shù)字 
   bitt=(temp%100)/10; //得到十位數(shù)字 
   biti=temp%10;  //得到個位數(shù)字,由于要顯示小數(shù)點(diǎn),所以要減去一個0x80 
   bitz=0;    //只是作為好看的位數(shù),實際我們在計算temp的時候已經(jīng)將小數(shù)位舍去了 
   
/*****************************************/ 
// 液晶的顯示 
/*****************************************/ 
     WriteLCDcom(0xc8); 
     WriteLCDdat(bith+0x30); 
     WriteLCDdat(bitt+0x30); 
     WriteLCDdat(biti+0x30); 
     WriteLCDdat(0x2e); 
     WriteLCDdat(bitz+0x30); 
     LED=1; 

     
     for(n=0;n<50000;n++);                    // 每過一會兒就自動加一個檔次的亮度 
     if(temp==26)  scale_0=0; 
       else if(temp==27)  scale_0=1; 
      else if(temp==28)  scale_0=2; 
       else if(temp==29)  scale_0=3; 
     else if(temp==30)  scale_0=4; 
      else if(temp==31)  scale_0=5; 
       else if(temp==32)  scale_0=6; 
        else if(temp==33)  scale_0=7; 
      else if(temp==34)  scale_0=8; 
       else   scale_0=9; 
         
               
} 
} 

  /******************************************************************************************** 
* 函數(shù)名稱:Timer2_Server() 
* 功    能:定時器2溢出中斷服務(wù)程序。1/2000 秒中斷1次。 
* 入口參數(shù):無   
* 出口參數(shù):無   
*********************************************************************************************/ 
void Timer2_Server(void) interrupt 5   
{ 
  static uchar tt;                               // tt用來保存當(dāng)前時間在1秒中的比例位置 
   
  TF2=0; 
   
  tt++; 
  if(tt==10)                                     // 每1/200秒整開始輸出低電平 
   { 
     tt=0; 
  if(scale_0!=0)                              // 加入該句的目的是避免滅燈時發(fā)生閃爍 
   { 
     P1_7=0; 
     P1_6=0; 
     P1_2=0; 
   } 
   } 
  if(scale_0==tt)                                // 按照當(dāng)前占空比切換輸出高電平 
   { 
     P1_7=1; 
     P1_6=1; 
     P1_2=1; 
   } 
} 


void delay(void)  //長延時,18b20在執(zhí)行溫度轉(zhuǎn)換操作的時候需要耗費(fèi)較長時間 
{      //在這段時間里18b20需要測溫,做模數(shù)轉(zhuǎn)換,并將轉(zhuǎn)換的二進(jìn)制數(shù)值存儲到自帶的臨時寄存區(qū)里去 
  uchar i,j; 
for(i=0;i<200;i++)   //具體需要多長時間芯片手冊上有介紹,這個要繼續(xù)深入了解 /*************************??******/ 
  for(j=0;j<100;j++) 
  ; 
} 

unsigned char Read18B20(void)  //最基本的讀18b20的函數(shù),并向主函數(shù)返回讀到的那個字節(jié) 
{ 
unsigned char ch; //相當(dāng)于串行緩存器 
    unsigned char q ; //循環(huán)計數(shù)器 
    for(q=0;q<8;q++)   //循環(huán)8次,讀出串行的8位數(shù)據(jù),先讀到的是數(shù)據(jù)的最低位 
        //因此要從ch的最高位存起,然后依次將ch向右移,就像火車進(jìn)站那樣 
    {       //    7 6 5 4 3 2 1 0   (ch) 
        // MSB-6-5-4-3-2-1-LSB  ---->      (數(shù)據(jù)) 
  ch=ch>>1;   //先移位再賦值,出現(xiàn)賦值8次但是只移位7次的效果 
      DQ=0;    //單線總線的要求,要讀器件,就要產(chǎn)生一個上升沿,然后釋放總線,現(xiàn)在要回到低電平 
      _nop_();   // 稍微停頓,讓器件探測到電平已經(jīng)變低了 

      DQ=1;    //拉高總線產(chǎn)生上升沿,同時,在某種意義上,對單片機(jī)的端口寫1,也就是讓端口處于待讀的狀態(tài),一舉兩得 
      _nop_();_nop_(); //4個空操作函數(shù),等待,給18b20響充分的時間響應(yīng),具體需要多久的時間要看器件手冊 
  _nop_();_nop_();  // 讀響應(yīng)是多久,需要繼續(xù)深入了解        /********************??*****/     
       //而且這個-nop-()函數(shù)到底會延時多長時間,要深入了解 /****************??***/ 
      if(DQ==1)      //開始讀端口,如果為1,則將ch最高位寫為1 
        { ch=ch|0x80;}  //ch|0x80就是 XXXX XXXX | 1000 0000 每一位相或的結(jié)果就是得到 1XXX XXXX,火車開始進(jìn)站了 
     else      //如果讀到的數(shù)是0,那么就把ch的最高位置為0 
  { ch=ch&0x7f;}  // ch & 0x7f 就是 XXXX XXXX & 0111 1111 ,結(jié)果自然就是 0XXX XXXX,數(shù)字最低位就進(jìn)站好了 
      Delay15(3);    //延時少少,延時多長要繼續(xù)深入了解    /****************??*****/ 
    DQ=1;     //讀完之后再次置端口為1,好為下一次讀做準(zhǔn)備,其實很關(guān)鍵的一步 
     }   
  return (ch);  //將讀到的數(shù)據(jù)返回給主函數(shù),這就我們想要的結(jié)果了 
} 
void Write18B20(uchar ch)  //寫18b20的函數(shù) 
{   
uchar i;     //一個循環(huán)計數(shù)變量 
for(i=0;i<8;i++)   //循環(huán)8次,每次一位二進(jìn)制 
{ 
  DQ=0;   //從讀和寫函數(shù)的比較可以得知,產(chǎn)生讀/寫的條件都是要先產(chǎn)生低電平,只是低電平的維持時間長短不一 
    Delay15(1);  //寫操作需要的低電平持續(xù)時間比讀操作要長的多 
    DQ=ch &0x01; //向總線上寫ch的最低位,跟讀的操作類似,只是這時“車站”是18b20,而“列車”是ch 
    Delay15(3);  //           7 6 5 4 3 2 1 0  (18b20) 
      // MSB-6-5-4-3-2-1-LSB  ---->      (ch) 
      // ch & 0x01 就是 xxxx xxxx & 0000 0001,結(jié)果是0000 000x 
      //為什么可以用一個位變量  DQ= 0000 000x,這個問題需要繼續(xù)深入了解 /*************??****/ 
    DQ=1;   //寫完一位后,將總線抬高,為下一次拉低做準(zhǔn)備 
    ch=ch >>1;  //將ch第二低位推到最低位,等待發(fā)射出去 
    _nop_();  //等待一段時間 
} 
} 
void Init18B20(void) //初始化18b20 
{ 
DQ=0;    //初始化操作同樣是由低電平開始,但是這個初始化低電平要持續(xù)得最久 
    Delay15(30);//至少延時480us,到底是多少,要找到-nop-()函數(shù)源碼,反匯編之后才知道/*******************??****/ 
    DQ=1;    //抬高總線,一舉兩得,可以準(zhǔn)備接受18b20的存在低電平 
    Delay15(10);//至少延時100us 
} 
void Delay15(uchar n)  //貌似滿精確的延時程序 
{         //具體要在 intrins.h頭文件中找到它,那么首先就要找到intrins.h /****************??*****/ 
  do 
{ 
  _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); 
        _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); 
        _nop_(); _nop_(); _nop_(); 
   
    n--; 
   
    }while(n); 
} 
/* 
bit LCDbusy() 
{ 
  bit flag; 
  RS=0;         //寄存器為LOW 
  RW=1;         //是否讀寫為high 
  E=1;          //使能端為high 
  if(lcd_flag==1) flag=1; 
  E=0; 
  return flag; 
} 
*/ 
void WriteLCDcom(uchar ch) 
{ 
   // while(LCDbusy()); 
RS=0; 
RW=0; 
E=0; 
P2=ch; 
delay(); 
E=1; 
E=0; 
} 
void WriteLCDdat(uchar ch) 
{ 
   // while(LCDbusy()); 
RS=1; 
RW=0; 
E=0; 
P2=ch; 
delay(); 
E=1; 
E=0; 
} 

不明白為什么加了檢測1602是否忙的程序進(jìn)去,為什么P2口就沒有數(shù)據(jù)了呢?液晶就不能顯示了呢?  
關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 人人爱干 | 国产露脸对白88av | 99精品99| 色天天综合 | 日韩欧美中文字幕在线视频 | 国产一区免费 | 欧美日韩亚 | 亚洲热在线视频 | 伊人伊人伊人 | 羞羞免费网站 | 一区二区在线不卡 | 这里有精品 | 在线观看视频你懂得 | 91视频在线| 三级特黄特色视频 | 2019天天操| 国产一区二区在线视频 | 色av一区二区 | 在线观看国产精品一区二区 | 欧美激情一区二区 | 黄色三级在线播放 | 欧美精品久久久久久久久久 | 精品91久久 | 日韩福利在线观看 | 91精品国产91久久久久久不卞 | 亚洲 欧美 另类 综合 偷拍 | 亚洲一区二区三区在线视频 | 精品九九 | 日韩免费一区二区 | 日韩不卡一区二区三区 | 欧美一级欧美三级在线观看 | 欧美中文在线 | 日韩av第一页 | 天天碰日日操 | 国产线视频精品免费观看视频 | www.婷婷亚洲基地 | 日韩中文字幕一区二区 | 91在线资源 | 成人黄视频在线观看 | 99久久精品国产毛片 | 欧美黑人一级爽快片淫片高清 |