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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 13995|回復: 27
打印 上一主題 下一主題
收起左側

數碼管顯示溫度

  [復制鏈接]
跳轉到指定樓層
樓主
ID:83083 發表于 2015-6-15 18:31 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
問題:用這個程序燒寫到單片機里面結果發現。三位數碼管中總有兩位顯示的時候閃個不停,并且亮度較正常顯示的時候暗。求大神教
數碼管顯示溫度程序如下:
#include<reg52.h>    //包含單片機寄存器的頭文件
#include<intrins.h>  //包含_nop_()函數定義的頭文件
unsigned char flag,tltemp;      //負溫度標志 和臨時暫存變量
unsigned char code s8[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//數碼管數字0-9
void delay1ms()
{
   unsigned char i,j;
  for(i=0;i<4;i++)
   for(j=0;j<33;j++)
    ;   
}
void delaynms(unsigned char n)
{
   unsigned char i;
for(i=0;i<n;i++)
    delay1ms();
}
/************************************************************************
以下是DS18B20的操作程序
************************************************************************/
sbit DQ=P3^3;
unsigned char time;   //設置全局變量,專門用于嚴格延時
/*****************************************************
函數功能:將DS18B20傳感器初始化,讀取應答信號
出口參數:flag
***************************************************/
bit Init_DS18B20(void)
{
bit flag;         //儲存DS18B20是否存在的標志,flag=0,表示存在;flag=1,表示不存在
DQ = 1;           //先將數據線拉高
for(time=0;time<2;time++) //略微延時約6微秒
     ;
DQ = 0;           //再將數據線從高拉低,要求保持480~960us
for(time=0;time<200;time++)  //略微延時約600微秒
     ;         //以向DS18B20發出一持續480~960us的低電平復位脈沖
DQ = 1;           //釋放數據線(將數據線拉高)
  for(time=0;time<10;time++)
     ;  //延時約30us(釋放總線后需等待15~60us讓DS18B20輸出存在脈沖)
flag=DQ;          //讓單片機檢測是否輸出了存在脈沖(DQ=0表示存在)      
for(time=0;time<200;time++)  //延時足夠長時間,等待存在脈沖輸出完畢
      ;
return (flag);    //返回檢測成功標志
}
/*****************************************************
函數功能:從DS18B20讀取一個字節數據
出口參數:dat
***************************************************/
unsigned char ReadOneChar(void)
{
  unsigned char i=0;
  unsigned char dat;  //儲存讀出的一個字節數據
  for (i=0;i<8;i++)
   {
     
     DQ =1;       // 先將數據線拉高
     _nop_();     //等待一個機器周期  
     DQ = 0;      //單片機從DS18B20讀書據時,將數據線從高拉低即啟動讀時序
     _nop_();     //等待一個機器周期     
     DQ = 1;     //將數據線"人為"拉高,為單片機檢測DS18B20的輸出電平作準備
     for(time=0;time<2;time++)
             ;      //延時約6us,使主機在15us內采樣
     dat>>=1;
     if(DQ==1)
        dat|=0x80;  //如果讀到的數據是1,則將1存入dat
   else
    dat|=0x00;//如果讀到的數據是0,則將0存入dat
       //將單片機檢測到的電平信號DQ存入r
     for(time=0;time<8;time++)
         ;              //延時3us,兩個讀時序之間必須有大于1us的恢復期
     }                     
  return(dat);    //返回讀出的十六進制數據
}
/*****************************************************
函數功能:向DS18B20寫入一個字節數據
入口參數:dat
***************************************************/  
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=0; i<8; i++)
   {
    DQ =1;         // 先將數據線拉高
    _nop_();      //等待一個機器周期  
    DQ=0;          //將數據線從高拉低時即啟動寫時序      
    DQ=dat&0x01;   //利用與運算取出要寫的某位二進制數據,
                       //并將其送到數據線上等待DS18B20采樣
   for(time=0;time<10;time++)
       ;//延時約30us,DS18B20在拉低后的約15~60us期間從數據線上采樣
    DQ=1;          //釋放數據線      
    for(time=0;time<1;time++)
     ;//延時3us,兩個寫時序間至少需要1us的恢復期
    dat>>=1;       //將dat中的各二進制位數據右移1位
   }
   for(time=0;time<4;time++)
               ; //稍作延時,給硬件一點反應時間
}
/*****************************************************
函數功能:做好讀溫度的準備
***************************************************/
void ReadyReadTemp(void)
{
      Init_DS18B20();     //將DS18B20初始化
  WriteOneChar(0xCC); // 跳過讀序號列號的操作
  WriteOneChar(0x44); // 啟動溫度轉換   
       delaynms(200); //轉換一次需要延時一段時間

  Init_DS18B20();     //將DS18B20初始化
  WriteOneChar(0xCC); //跳過讀序號列號的操作
  WriteOneChar(0xBE); //讀取溫度寄存器,前兩個分別是溫度的低位和高位
}

/*****************************************************
函數功能:顯示溫度的整數部分
入口參數:x
***************************************************/
void display_temp1(unsigned char x)
{
unsigned char k,l;     //j,k,l分別儲存溫度的百位、十位和個位
k=(x%100)/10;    //取十位
l=x%10;             //取個位
P0=0x00;
P0=s8[l];    //將個位數字的字符常量寫入LCD
P2=0xfd;    //將十位數字的字符常量寫入LCD
delaynms(20);         //延時1ms給硬件一點反應時間      
P0=0x00;
P0=s8[k];
    P2=0xfe;
delaynms(1);

}
/*****************************************************
函數功能:顯示溫度的小數數部分
入口參數:x
***************************************************/
void display_temp2(unsigned char x)
{
P0=0x00;
P0=s8[x];
    P2=0xfb;
delaynms(20);
}

/*****************************************************
函數功能:主函數
***************************************************/
void main(void)
{   
   
   unsigned char TL;     //儲存暫存器的溫度低位
     unsigned char TH;    //儲存暫存器的溫度高位
     unsigned char TN;      //儲存溫度的整數部分
   unsigned char TD;       //儲存溫度的小數部分
    delaynms(5);        //延時5ms給硬件一點反應時間     
   while(1)                //不斷檢測并顯示溫度
  {  
   flag=0;
  ReadyReadTemp();     //讀溫度準備
     TL=ReadOneChar();    //先讀的是溫度值低位
  TH=ReadOneChar();    //接著讀的是溫度值高位  
  TN=TH*16+TL/16;      //實際溫度值=(TH*256+TL)/16,即:TH*16+TL/16
                      //這樣得出的是溫度的整數部分,小數部分被丟棄了
    TD=(TL%16)*10/16;    //計算溫度的小數部分,將余數乘以10再除以16取整,
                     //這樣得到的是溫度小數部分的第一位數字(保留1位小數)
   display_temp2(TD);
     display_temp1(TN);    //顯示溫度的整數部
       delaynms(1);                          
    }
     
}

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

使用道具 舉報

沙發
ID:83193 發表于 2015-6-16 21:37 | 只看該作者
頂一下
回復

使用道具 舉報

板凳
ID:83246 發表于 2015-6-17 12:21 | 只看該作者
不知道你用的是LCD屏還是數碼管在顯示,LCD屏顯示,如果出現閃動,或者比較暗的話,多半就是單片機一直重復在向LCD那一位寫數據,導致LCD一直在更新那一個字符,  
如果是數碼管顯示,就看看WHILE循環中是不是周期長了點,我以前也遇到過類似的,LCD也遇到過,就是一直重復在寫數據,導致LCD一直在刷新屏幕

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

地板
ID:61876 發表于 2015-6-17 12:33 | 只看該作者
這個程序用數碼管顯示還缺位碼及很多的定義;用1602顯示也缺少有關的定義。

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

5#
ID:83083 發表于 2015-6-17 13:04 | 只看該作者
z1061828841 發表于 2015-6-17 12:21
不知道你用的是LCD屏還是數碼管在顯示,LCD屏顯示,如果出現閃動,或者比較暗的話,多半就是單片機一直重復 ...

我用的是數碼管顯示。那這個程序要怎么修改才能使他正常顯示呢,求教
回復

使用道具 舉報

6#
ID:83083 發表于 2015-6-17 13:04 | 只看該作者
gaozhaohong 發表于 2015-6-17 12:33
這個程序用數碼管顯示還缺位碼及很多的定義;用1602顯示也缺少有關的定義。

那這個該怎么修改呢
回復

使用道具 舉報

7#
ID:83083 發表于 2015-6-17 14:48 | 只看該作者
gaozhaohong 發表于 2015-6-17 12:33
這個程序用數碼管顯示還缺位碼及很多的定義;用1602顯示也缺少有關的定義。

請問具體可以怎么修改呢
回復

使用道具 舉報

8#
ID:61876 發表于 2015-6-22 20:59 | 只看該作者
邱育 發表于 2015-6-17 14:48
請問具體可以怎么修改呢

不知道是想用LED還是想用LCD?
回復

使用道具 舉報

9#
ID:81118 發表于 2015-6-22 22:21 | 只看該作者
你這個程序 小數部分顯示的應該比較暗          寫個 計數中斷  把顯示 放到中斷服務函數去

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

10#
ID:83349 發表于 2015-6-27 13:35 | 只看該作者
頂頂更好

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

11#
ID:82588 發表于 2015-6-29 19:15 | 只看該作者
本帖最后由 dely2009 于 2015-6-29 19:18 編輯

修改你的延時   如果不行的話   改用頻率較高的晶振設置,,,  動態掃描顯示數碼管   延時過長 會閃爍  還會偏暗

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

12#
ID:84419 發表于 2015-6-30 23:37 | 只看該作者
這個我也需要一份,
回復

使用道具 舉報

13#
ID:18297 發表于 2015-7-1 20:47 | 只看該作者
1)你的顯示為動態掃描,必須在DS18S20的溫度采集的延時等待時間中插入顯示輸出,否則你的顯示會變暗或黑屏。
2)你的顯示程序,小數點和個位顯示重合。位選都是P2=0xfd;
3)這種DS18S20的讀取溫度需要有一定的延時,加上動態掃描顯示,必須要在時間上安排好。

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

14#
ID:84532 發表于 2015-7-2 09:30 | 只看該作者
沒有看懂。。。。
回復

使用道具 舉報

15#
ID:19715 發表于 2015-7-3 18:55 | 只看該作者
只能是改善一點
/*****************************************************
函數功能:顯示溫度的整數部分
入口參數:x
***************************************************/
void display_temp1(unsigned char x)
{
unsigned char k,l;     //j,k,l分別儲存溫度的百位、十位和個位
k=(x%100)/10;    //取十位
l=x%10;             //取個位
P0=0xff;
P2=0xfd;    //將十位數字的字符常量寫入LCD
P0=s8[l];    //將個位數字的字符常量寫入LCD
delaynms(4);         //延時1ms給硬件一點反應時間      
P0=0xff;
P2=0xfe;
P0=s8[k];
delaynms(4);
}
/*****************************************************
函數功能:顯示溫度的小數數部分
入口參數:x
***************************************************/
void display_temp2(unsigned char x)
{
P0=0xff;
P2=0xfb;
P0=s8[x];
delaynms(4);
}

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

16#
ID:19715 發表于 2015-7-3 18:58 | 只看該作者
溫度采集太過頻繁,每一秒采集最多2-3次,一般應用0.5次就夠了

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

17#
ID:19715 發表于 2015-7-3 19:00 | 只看該作者
本帖最后由 明白 于 2015-7-3 19:02 編輯

只能采用定時器中斷,才能保證數碼管正常顯示,
不然的話肯定會被把溫度采集調制著

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

18#
ID:83083 發表于 2015-7-4 13:52 | 只看該作者
歡騰智能科技 發表于 2015-6-22 22:21
你這個程序 小數部分顯示的應該比較暗          寫個 計數中斷  把顯示 放到中斷服務函數去

我試試
回復

使用道具 舉報

19#
ID:83083 發表于 2015-7-4 13:53 | 只看該作者
gaozhaohong 發表于 2015-6-22 20:59
不知道是想用LED還是想用LCD?

用LED吧,
回復

使用道具 舉報

20#
ID:83083 發表于 2015-7-4 13:56 | 只看該作者
z1061828841 發表于 2015-6-17 12:21
不知道你用的是LCD屏還是數碼管在顯示,LCD屏顯示,如果出現閃動,或者比較暗的話,多半就是單片機一直重復 ...

我用的是數碼管顯示
回復

使用道具 舉報

21#
ID:83083 發表于 2015-7-4 13:57 | 只看該作者
明白 發表于 2015-7-3 19:00
只能采用定時器中斷,才能保證數碼管正常顯示,
不然的話肯定會被把溫度采集調制著

用定時中斷程序怎么寫可以幫我寫一下嗎,謝謝
回復

使用道具 舉報

22#
ID:58502 發表于 2015-7-4 15:18 | 只看該作者
這是由于在讀取溫度的時候,數碼管掃描停下來了,這時候停下來的所顯示的那位就比較亮,而由于讀取時間太長就導致其他位數在閃

評分

參與人數 1黑幣 +35 收起 理由
admin + 35 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

23#
ID:166150 發表于 2017-3-1 15:02 | 只看該作者
不知道你用的是LCD屏還是數碼管在顯示,LCD屏顯示,如果出現閃動,或者比較暗的話,多半就是單片機一直重復在向LCD那一位寫數據,導致LCD一直在更新那一個字符,  
如果是數碼管顯示,就看看WHILE循環中是不是周期長了點,我以前也遇到過類似的,LCD也遇到過,就是一直重復在寫數據,導致LCD一直在刷新屏幕
回復

使用道具 舉報

24#
ID:257097 發表于 2017-12-4 11:49 | 只看該作者
好東西值的收藏謝謝分享
回復

使用道具 舉報

25#
ID:213173 發表于 2017-12-4 21:38 | 只看該作者
給你一個例程參考
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2;           //單總線端口定義
uchar flag1;            //正或負標記
sbit dula=P2^6;                        //段選
sbit wela=P2^7;                        //位選
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,//0~f數組
           0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,//0~9帶小數點數組
                        0x87,0xff,0xef};
/************DS18B20操作程序聲明****************/
void dsreset();                              //復位和初始化
bit tmpreadbit();                                        //讀1位數據
uchar tmpread();                                   //讀取一個字節數據
void tmpwritebyte(uchar dat);        //寫一個字節
void tmpchange();                                        //發送操作指令
uint tmp();                             //讀取溫度值
/************顯示程序聲明****************/
void display(uint temp);                //數碼管顯示程序
/************延時程序聲明****************/
void delay(uchar k);                                //50us延時程序
void delay1ms(uint k);                                //1ms延時程序

/************主程序****************/
void main()
{
        tmpchange();                //初始化DS18B20
        delay1ms(1000);        //延時1s等待穩定
        while(1)
        {
                tmpchange();                //發送操作指令
                display(tmp());        //數碼管顯示讀到的溫度數據
        }
}
//初始化DS18B20
//讓DS18B20一段相對長時間低電平, 然后一段相對非常短時間高電平, 即可啟動
void dsreset()       //復位和初始化
{
        uint i;                        //用作短延時的計數變量
        DS=0;                        //發送低電平
        i=103;                        //賦值
        while(i>0)i--;        //相對長時間低電平896us
        DS=1;                        //發送高電平
        i=4;                        //賦值
        while(i>0)i--;        //相對非常短時間高電平38us
}
//向DS18B20讀取一位數據   
//讀一位, 讓DS18B20一小周期低電平, 然后兩小周期高電平,   
//之后DS18B20則會輸出持續一段時間的一位數據
bit tmpreadbit()       //讀1位數據
{
   uint i;                        //用作短延時的計數變量
   bit dat;                        //位變量
   DS=0;                                //發送低電平
        i++;                                //少許延時
   DS=1;                                //發送高電平
        i++;i++;                        //執行一個i++;3.25us
   dat=DS;                        //讀1位數據
   i=8;
        while(i>0)i--;//短延時
   return (dat);                //返回dat值
}
//讀取一個字節數據, 通過調用tmpreadbit()來實現
uchar tmpread()   //讀取一個字節數據
{
        uchar i,j,dat;
        dat=0;
        for(i=1;i<=8;i++)
        {
                j=tmpreadbit();//按位分8次讀取一個字節數據
        //最先讀出的是最低位數據  
                dat=(j<<7)|(dat>>1);   //讀出的數據最低位在最前面,這樣剛好一個字節在dat里
        }
        return(dat);        //返回dat值
}
//向DS18B20寫入一個字節數據
void tmpwritebyte(uchar dat)   //寫一個字節
{
        uint i;
        uchar j;
        bit testb;
        for(j=1;j<=8;j++)        //一個字節分8次按位寫入
        {
                testb=dat&0x01;//把dat最低位賦值與testb
                dat=dat>>1;                //dat左移一位
//寫"1", 讓低電平持續2個小延時, 高電平持續8個小延時
                if(testb)     //寫 1
                {
                        DS=0;
                        i++;i++;
                        DS=1;
                        i=8;
                        while(i>0)
                                i--;
                }
                else
                {
                        DS=0;       //寫 0
                        i=8;
                        while(i>0)
                                i--;
                        DS=1;
                        i++;i++;
                }       
        }
}
//向DS18B20發送溫度轉換命令
void tmpchange()                        //發送溫度轉換命令
{
        dsreset();                                //復位和初始化
        delay(1);                            //延時
        tmpwritebyte(0xcc);  //寫入跳過序列號命令字
        tmpwritebyte(0x44);  //寫入溫度轉換命令字
}

uint tmp()               //讀取溫度值
{
        float tt;                                //單精度浮點型數據變量
        uint temp;                                        //變量溫度
        uchar a,b;
        dsreset();                        //發送復位和初始化命令
        delay(1);
        tmpwritebyte(0xcc);  //寫入跳過序列號命令字
        tmpwritebyte(0xbe);        //寫入讀取數據令字
//連續讀取兩個字節數據
        a=tmpread();
        b=tmpread();
        temp=b;
        temp<<=8;          //兩個字節組成一個整型變量
        temp=temp|a;
//DS18B20的精確度為0.0625度, 即讀回數據的最低位代表0.0625度
        tt=temp*0.0625;
//將它放大10倍, 使顯示時可顯示小數點后一位, 并對小數點后第二2進行4舍5入
//如t=11.0625, 進行計數后, 得到value = 111, 即11.1 度
        temp=tt*10+0.5;
        return temp;        //返回3位有效數
}
//顯示當前溫度值, 精確到小數點后一位
void display(uint temp)                        //顯示程序
{
        static uchar count=0;
        switch(count)
        {
                case 0:
                        dula=0;
                        P0=table[temp/100];                //顯示十位
                        dula=1;
                        dula=0;
                       
                        wela=0;
                        P0=0x7e;
                        wela=1;
                        wela=0;
                        count=1;
                break;

                case 1:
                        dula=0;
                        P0=table1[temp/10%10];                //顯示個位
                        dula=1;
                        dula=0;
                       
                        wela=0;
                        P0=0x7d;
                        wela=1;
                        wela=0;
                        count=2;
                break;

                case 2:
                        P0=table[temp%10];                //顯示1/10位
                        dula=1;
                        dula=0;
                       
                        P0=0x7b;
                        wela=1;
                        wela=0;
                        count=0;
                break;
        }                               
}

void delay(uchar k)   //11.0592MHz 50us延時
{
    uchar a,b;
    for(b=k;b>0;b--)
        for(a=43;a>0;a--);
}
void delay1ms(uint k)                        //11.0592MHz 1ms延時
{
        uint i,j;
        for(i=k;i>0;i--)
                for(j=114;j>0;j--);       
}
回復

使用道具 舉報

26#
ID:245044 發表于 2017-12-4 22:09 | 只看該作者
很不錯,好東西
回復

使用道具 舉報

27#
ID:257582 發表于 2017-12-5 10:38 | 只看該作者
謝謝樓主,正是需要的參考,頂!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲欧洲一区 | 美女毛片免费看 | 国产精品久久久久久久久图文区 | 成年人在线视频 | 免费国产一区二区 | 亚洲一区二区三区免费在线 | 日韩在线高清 | 国产精品久久久久无码av | 在线视频 亚洲 | aaaaaaa片毛片免费观看 | 日韩播放 | 欧美久久综合 | 伊人影院在线观看 | 欧美日韩中文在线观看 | 毛片久久久| 午夜小视频免费观看 | 日韩欧美一区二区三区免费观看 | 一级毛片免费视频观看 | 国产99久久久久 | 国产精品 亚洲一区 | 性做久久久久久免费观看欧美 | 亚洲伊人精品酒店 | 久久综合av | 久久人人网| 亚洲国产成人精品女人久久久野战 | 色视频www在线播放国产人成 | www.狠狠操| 草草视频在线观看 | 91视频在线 | 欧美久久一级 | 日日爱av | 国产免费一二三区 | 国产精品久久久久久久久久 | 国产精品久久久久久久久久三级 | 日韩精品1区2区3区 爱爱综合网 | 欧美一级二级视频 | 国产精品视频一区二区三区 | 国产精品日韩欧美一区二区三区 | 成人在线精品视频 | 国产激情在线看 | 久久噜噜噜精品国产亚洲综合 |