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

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

溫度控制led燈灰度變化c51

作者:佚名   來源:本站原創   點擊數:  更新時間:2011年02月17日   【字體:

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

#include "reg52.h"   
#include<intrins.h> 
#define uchar unsigned char 
//溫度傳感器與單片機接口為 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否忙標志 
sbit P1_7 = P3 ^ 7;                              // 控制LED11               
sbit P1_6 = P3 ^ 6;                              // 控制LED10   
sbit P1_2 = P3 ^ 4;   
// 
uchar timer=0x00; //字節變量timer用于計時,每計數器記滿100次,就采樣一次溫度 
uchar chars[]={"GYRGB.Liuzhou^_^"};      // 液晶顯示第一行 
uchar chars2[]={"Welcome!"};            //液晶顯示第二行         
             
uchar  scale_0;                         //燈光灰度 
/////////////////////////////// 
//各個功能子函數 
/////////////////////////////// 
void delay(void);       //18b20溫度轉換后所需的延時 
void delay1(void);      //動態數碼管顯示所需的較短的延時 
unsigned char Read18B20(void);  //讀18b20子函數   
void Write18B20(uchar ch);       //寫18b20子函數 
void Delay15(uchar n);     //讀寫所需的最基本單位時間的延時 
void Init18B20(void);     //初始化18b20函數 

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

RCAP2H =0xFE;                                  // 賦T2的預置值,溢出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位計數器 
//溢出時間 65536us約等于65.5ms 
//溢出100次采樣溫度一次,采樣周期6.5秒 
//////////////////////////////// 
while(1) 
{ 

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

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


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

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

      DQ=1;    //拉高總線產生上升沿,同時,在某種意義上,對單片機的端口寫1,也就是讓端口處于待讀的狀態,一舉兩得 
      _nop_();_nop_(); //4個空操作函數,等待,給18b20響充分的時間響應,具體需要多久的時間要看器件手冊 
  _nop_();_nop_();  // 讀響應是多久,需要繼續深入了解        /********************??*****/     
       //而且這個-nop-()函數到底會延時多長時間,要深入了解 /****************??***/ 
      if(DQ==1)      //開始讀端口,如果為1,則將ch最高位寫為1 
        { ch=ch|0x80;}  //ch|0x80就是 XXXX XXXX | 1000 0000 每一位相或的結果就是得到 1XXX XXXX,火車開始進站了 
     else      //如果讀到的數是0,那么就把ch的最高位置為0 
  { ch=ch&0x7f;}  // ch & 0x7f 就是 XXXX XXXX & 0111 1111 ,結果自然就是 0XXX XXXX,數字最低位就進站好了 
      Delay15(3);    //延時少少,延時多長要繼續深入了解    /****************??*****/ 
    DQ=1;     //讀完之后再次置端口為1,好為下一次讀做準備,其實很關鍵的一步 
     }   
  return (ch);  //將讀到的數據返回給主函數,這就我們想要的結果了 
} 
void Write18B20(uchar ch)  //寫18b20的函數 
{   
uchar i;     //一個循環計數變量 
for(i=0;i<8;i++)   //循環8次,每次一位二進制 
{ 
  DQ=0;   //從讀和寫函數的比較可以得知,產生讀/寫的條件都是要先產生低電平,只是低電平的維持時間長短不一 
    Delay15(1);  //寫操作需要的低電平持續時間比讀操作要長的多 
    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,結果是0000 000x 
      //為什么可以用一個位變量  DQ= 0000 000x,這個問題需要繼續深入了解 /*************??****/ 
    DQ=1;   //寫完一位后,將總線抬高,為下一次拉低做準備 
    ch=ch >>1;  //將ch第二低位推到最低位,等待發射出去 
    _nop_();  //等待一段時間 
} 
} 
void Init18B20(void) //初始化18b20 
{ 
DQ=0;    //初始化操作同樣是由低電平開始,但是這個初始化低電平要持續得最久 
    Delay15(30);//至少延時480us,到底是多少,要找到-nop-()函數源碼,反匯編之后才知道/*******************??****/ 
    DQ=1;    //抬高總線,一舉兩得,可以準備接受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是否忙的程序進去,為什么P2口就沒有數據了呢?液晶就不能顯示了呢?  
關閉窗口

相關文章

主站蜘蛛池模板: 精品一区电影 | 剑来高清在线观看 | 日韩午夜一区二区三区 | 91电影 | www日韩高清 | 精品国产乱码久久久 | 色综合久 | 成人一区二区三区在线 | 夜夜骚视频 | 亚洲国产一区二区三区 | 欧美激情综合 | 亚洲一区二区高清 | 亚洲www. | 日韩免费av网站 | 一级黄色裸片 | 久久久久国产一区二区三区四区 | 视频一区在线观看 | 日本不卡免费新一二三区 | 久草视| av在线一区二区 | 天天夜天天操 | 91精品久久久久久久久久 | 成人精品鲁一区一区二区 | 国产欧美一级二级三级在线视频 | 免费精品 | 狠狠涩 | 亚洲小视频| 精品欧美一区二区三区久久久 | 91精品无人区卡一卡二卡三 | 亚洲欧美少妇 | 国产免费黄网 | 国产精品免费一区二区三区四区 | 91精品国产一区二区 | 欧美日韩在线精品 | 波多野结衣在线观看一区二区三区 | av毛片| 成人在线中文字幕 | 影音先锋成人资源 | 97在线观视频免费观看 | 一级毛片在线播放 | 日韩成人在线观看 |