找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

請問C51單片機(jī)兩個延時函數(shù)互相干擾是什么原因?

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:731755 發(fā)表于 2021-5-9 18:57 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
各位大師,你們好,我是個小白,目前正在學(xué)習(xí)DS18B20測溫度,根據(jù)學(xué)習(xí)板的程序,可以正常顯示溫度,我想做一個可以溫度報警器,前面一個帖子,就是詢問想要數(shù)碼管顯示H的帖子,我經(jīng)過查詢資料,解決了,溫度超過30度,可以在數(shù)碼管末尾上顯示H,不過目前有個問題,我設(shè)定的是溫度超過30度,數(shù)碼管末尾也能顯示H,并且指示燈閃爍,蜂鳴器鳴叫,但是數(shù)碼管也會一直閃爍,當(dāng)溫度低于30度的時候,數(shù)碼管顯示就是正常的,我覺得,應(yīng)該是延時函數(shù)干擾造成的,我又另外寫了一個延時函數(shù),還是一樣的問題,請問各位大師,這是延時函數(shù)互相干擾嗎?如果想要解決問題,一定要用中斷嗎?

溫度.rar

32.42 KB, 下載次數(shù): 4

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

使用道具 舉報

沙發(fā)
ID:731755 發(fā)表于 2021-5-9 18:59 | 只看該作者
#include"temp.h"
#include "intrins.h"
/*******************************************************************************
* 函 數(shù) 名         : Delay1ms
* 函數(shù)功能                   : 延時函數(shù)
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void DelayX10us(uchar t)
{
do {
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   }
   while (--t);
}
void Delay1ms(uint y)
{
        uint x;
        for( ; y>0; y--)
        {
                for(x=110; x>0; x--);
        }
}
/*******************************************************************************
* 函 數(shù) 名         : Ds18b20Init
* 函數(shù)功能                   : 初始化
* 輸    入         : 無
* 輸    出         : 初始化成功返回1,失敗返回0
*******************************************************************************/

uchar Ds18b20Init()
{
        uchar i;
        DSPORT = 0;                         //將總線拉低480us~960us
        DelayX10us(60);
        DSPORT = 1;                        //然后拉高總線,如果DS18B20做出反應(yīng)會將在15us~60us后總線拉低
    DelayX10us(6)        ;
        while(DSPORT)        //等待DS18B20拉低總線
        {
                Delay1ms(1);
                i++;
                if(i>5)//等待>5MS
                {
                        return 0;//初始化失敗
                }
       
        }
        return 1;//初始化成功
}

/*******************************************************************************
* 函 數(shù) 名         : Ds18b20WriteByte
* 函數(shù)功能                   : 向18B20寫入一個字節(jié)
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/

void Ds18b20WriteByte(uchar dat)
{
        uint  j;

        for(j=0; j<8; j++)
        {
                DSPORT = 0;                       //每寫入一位數(shù)據(jù)之前先把總線拉低1us
                _nop_();
        _nop_();;
                DSPORT = dat & 0x01;  //然后寫入一個數(shù)據(jù),從最低位開始
                DelayX10us(6)        ;
                DSPORT = 1;        //然后釋放總線,至少1us給總線恢復(fù)時間才能接著寫入第二個數(shù)值
                dat >>= 1;
        }
}
/*******************************************************************************
* 函 數(shù) 名         : Ds18b20ReadByte
* 函數(shù)功能                   : 讀取一個字節(jié)
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/


uchar Ds18b20ReadByte()
{
        uchar byte, bi;
        uint  j;       
        for(j=8; j>0; j--)
        {
                DSPORT = 0;//先將總線拉低1us
            _nop_();
        _nop_();;
                DSPORT = 1;//然后釋放總線
                _nop_();
        _nop_();
                _nop_();
        _nop_();
                _nop_();
        _nop_();
                bi = DSPORT;         //讀取數(shù)據(jù),從最低位開始讀取
                /*將byte左移一位,然后與上右移7位后的bi,注意移動之后移掉那位補(bǔ)0。*/
                byte = (byte >> 1) | (bi << 7);                                                  
            DelayX10us(5)        ;       
        }                               
        return byte;
}

/*******************************************************************************
* 函 數(shù) 名         : Ds18b20ReadTemp
* 函數(shù)功能                   : 讀取溫度
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/

int Ds18b20ReadTemp()
{
        int temp = 0;
        uchar tmh, tml;
        Ds18b20Init();
        Delay1ms(1);
        Ds18b20WriteByte(0xcc);                //跳過ROM操作命令                 
        Ds18b20WriteByte(0x44);
    Ds18b20Init();
    Delay1ms(1);
        Ds18b20WriteByte(0xcc);         //跳過ROM操作命令
        Ds18b20WriteByte(0xbe);         //發(fā)送讀取溫度命令               
        tml = Ds18b20ReadByte();                //讀取溫度值共16位,先讀低字節(jié)
        tmh = Ds18b20ReadByte();                //再讀高字節(jié)
        temp = tmh;
        temp <<= 8;
        temp |= tml;
        return temp;
}


回復(fù)

使用道具 舉報

板凳
ID:731755 發(fā)表于 2021-5-9 19:00 | 只看該作者
#include "reg51.h"
#include "temp.h"
#define OVERTEMP 30 //定義超溫報警數(shù)值
  typedef unsigned char u8;
  typedef unsigned int u16;
  sbit LEDA=P1^0;
  sbit LEDB=P1^1;
  sbit LEDC=P1^2;
  sbit beep=P2^7;
  sbit led= P2^6;
  u8 code shuma[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f };
  u8 shijian[8];
  
  void delay(u16 q)
  {
   while(q--);
  }
  void DelayMS(u16 x)
{
  u8 y;
  while(x--)
  {
    for(y=0;y<120;y++);
  }  
}
   void dongtai()
   {
             u8 i;
          for(i=0;i<8;i++)
          {
                  switch(i)
           {
                   case(0):LEDA=0;LEDB=0;LEDC=0; break;
                case(1):LEDA=1;LEDB=0;LEDC=0; break;
                case(2):LEDA=0;LEDB=1;LEDC=0; break;
                case(3):LEDA=1;LEDB=1;LEDC=0; break;
                case(4):LEDA=0;LEDB=0;LEDC=1; break;
                case(5):LEDA=1;LEDB=0;LEDC=1; break;
                case(6):LEDA=0;LEDB=1;LEDC=1; break;
                case(7):LEDA=1;LEDB=1;LEDC=1; break;
           }
           P0=shijian[i];
           delay(10);        
           P0=0x00;
          }
   }
   void datapros(int temp)
   {
          float tp;
          if(temp<0)
          {
                shijian[0] = 0x40;
                temp=temp-1;
                temp=~temp;
                tp=temp;
                temp=tp*0.0625*100+0.5;
          }
          else
          {
                  shijian[0] = 0x00;
                  tp=temp;
                temp=tp*0.0625*100+0.5;
          }
           shijian[1] = shuma[temp/ 10000];
              shijian[2] = shuma[temp % 10000 / 1000];
              shijian[3] = shuma[temp % 1000 / 100] | 0x80;
       shijian[4] = shuma[temp % 100 / 10];
           shijian[5] = shuma[temp % 10];
           shijian[6] = 0x00;
              shijian[7] = 0x00;
          if((temp/100)>OVERTEMP)
     {
            shijian[7]=0x76;//顯示"H"
            beep=~beep;
            DelayMS(100);
            led=~led;
            DelayMS(10) ;
         }                     
   }  
  
   void main()
   {
            
            while(1)
         {
           datapros( Ds18b20ReadTemp());
           dongtai() ;          
         }         
   }
   
回復(fù)

使用道具 舉報

地板
ID:731755 發(fā)表于 2021-5-9 19:00 | 只看該作者
#ifndef __TEMP_H_
#define __TEMP_H_

#include<reg51.h>
//---重定義關(guān)鍵詞---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int
#endif

//--定義使用的IO口--//
sbit DSPORT=P3^7;

//--聲明全局函數(shù)--//
void Delay1ms(uint );
uchar Ds18b20Init();
void Ds18b20WriteByte(uchar com);
uchar Ds18b20ReadByte();
int Ds18b20ReadTemp();

#endif

回復(fù)

使用道具 舉報

5#
ID:569384 發(fā)表于 2021-5-10 09:18 | 只看該作者
程序是從上往下執(zhí)行的,這樣做延時程序都是一直在延時函數(shù)里面循環(huán),那程序當(dāng)時就不能執(zhí)行其他代碼。
回復(fù)

使用道具 舉報

6#
ID:824490 發(fā)表于 2021-5-10 11:37 | 只看該作者
haokey 發(fā)表于 2021-5-10 09:18
程序是從上往下執(zhí)行的,這樣做延時程序都是一直在延時函數(shù)里面循環(huán),那程序當(dāng)時就不能執(zhí)行其他代碼。

上電后是從main()開始動行的。其它的函數(shù)無所謂順序。在main之后的函數(shù)在C文件的前端加入聲明;
如果是多個文件,要包含對應(yīng)的頭文件
回復(fù)

使用道具 舉報

7#
ID:844772 發(fā)表于 2021-5-10 14:31 | 只看該作者
不是延時沖突問題,就是你程序?qū)懙膯栴},你延誤了一百多毫秒顯示一次就會閃爍.
            beep=~beep;
            DelayMS(100);  //主要這句導(dǎo)致
            led=~led;
            DelayMS(10) ;  
回復(fù)

使用道具 舉報

8#
ID:814525 發(fā)表于 2021-5-10 16:22 | 只看該作者
多看看如何利用用定時器管理時間方面的架構(gòu),才能提升水平。DelayMs()只會誤事
回復(fù)

使用道具 舉報

9#
ID:213173 發(fā)表于 2021-5-10 16:27 | 只看該作者
與延時函數(shù)沒有直接關(guān)系,關(guān)鍵是協(xié)調(diào)好讀寫DS18B20的時序與數(shù)碼管動態(tài)掃描的時間關(guān)系。給你一個示例參考。

DS18B20溫度上下限報警 仿真示例.zip (231.57 KB, 下載次數(shù): 7)

回復(fù)

使用道具 舉報

10#
ID:919104 發(fā)表于 2021-5-11 09:15 | 只看該作者
如果感到迷糊,就點(diǎn)開調(diào)試模式,或者自己讀程序,畫一個時序圖。你的這個程序做判斷的時間太久了
回復(fù)

使用道具 舉報

11#
ID:889094 發(fā)表于 2021-5-11 11:17 | 只看該作者
單片機(jī)程序都是順序執(zhí)行,從main函數(shù) 開始 ,你的程序結(jié)構(gòu)挺好,先讀取溫度,轉(zhuǎn)換格式 ,顯示,問題在于你的動態(tài)顯示里面用到了delay100ms,視覺不閃爍起碼要顯示頻率大于24,而你的顯示頻率小于10了,可以把LED控制和顯示數(shù)碼管分開。
前幾天看到大神的貼子,能不用delay盡量不用,因?yàn)閐elay的時候CPU沒有閑著,它一直在忙,別的程序就沒法執(zhí)行,除非像讀取DS18B20這種需要具體延時多少us或ms的時候用delay,其實(shí)顯示控制之類的可以用定時器來控制時間。在定時器中設(shè)置一個或幾個變量累加,到某個值之后置0,在主程序中判斷范圍顯示或是關(guān)閉
回復(fù)

使用道具 舉報

12#
ID:731755 發(fā)表于 2021-5-13 07:31 | 只看該作者
名字不是重點(diǎn) 發(fā)表于 2021-5-10 11:37
上電后是從main()開始動行的。其它的函數(shù)無所謂順序。在main之后的函數(shù)在C文件的前端加入聲明;
如果是多 ...

好的,感謝,我在搜集別人的程序中,發(fā)現(xiàn)有人的程序確如師傅說的那樣。
回復(fù)

使用道具 舉報

13#
ID:731755 發(fā)表于 2021-5-13 07:33 | 只看該作者
glinfei 發(fā)表于 2021-5-10 14:31
不是延時沖突問題,就是你程序?qū)懙膯栴},你延誤了一百多毫秒顯示一次就會閃爍.
            beep=~beep;
...

你好,我在網(wǎng)上找到類似的程序,把顯示的那個地方的延時給換了,現(xiàn)在的就不閃了,謝謝
回復(fù)

使用道具 舉報

14#
ID:731755 發(fā)表于 2021-5-13 07:33 | 只看該作者
張?zhí)鞄?發(fā)表于 2021-5-10 16:22
多看看如何利用用定時器管理時間方面的架構(gòu),才能提升水平。DelayMs()只會誤事

好的,感謝
回復(fù)

使用道具 舉報

15#
ID:731755 發(fā)表于 2021-5-13 07:34 | 只看該作者
wulin 發(fā)表于 2021-5-10 16:27
與延時函數(shù)沒有直接關(guān)系,關(guān)鍵是協(xié)調(diào)好讀寫DS18B20的時序與數(shù)碼管動態(tài)掃描的時間關(guān)系。給你一個示例參考。
...

好的,感謝,文件已下載
回復(fù)

使用道具 舉報

16#
ID:731755 發(fā)表于 2021-5-13 07:39 | 只看該作者
birdzhyli 發(fā)表于 2021-5-11 11:17
單片機(jī)程序都是順序執(zhí)行,從main函數(shù) 開始 ,你的程序結(jié)構(gòu)挺好,先讀取溫度,轉(zhuǎn)換格式 ,顯示,問題在于你 ...

你好,師傅,前幾天我用定時中斷來寫數(shù)碼顯示,可是效果不好,可以看到數(shù)碼管一位位的在跳變,溫度可以正常顯示,問題是時間填充,我已經(jīng)設(shè)置的很低了,1us一次跳動顯示數(shù)碼管八位,
回復(fù)

使用道具 舉報

17#
ID:65956 發(fā)表于 2021-5-13 08:16 | 只看該作者
如果你顯示加蜂鳴器報警聲都放在主函數(shù)中,當(dāng)報警時顯示肯定會閃。解決辦法是,把顯示改用定時器驅(qū)動顯示,或是把蜂鳴器報警放在定時器中驅(qū)動,這樣影響就比較小了,就看你定時器如何用了
回復(fù)

使用道具 舉報

18#
ID:883031 發(fā)表于 2021-5-13 11:29 | 只看該作者
先進(jìn)行位選,再送數(shù)據(jù)。
回復(fù)

使用道具 舉報

19#
ID:731755 發(fā)表于 2021-5-13 21:32 | 只看該作者
aking991 發(fā)表于 2021-5-13 08:16
如果你顯示加蜂鳴器報警聲都放在主函數(shù)中,當(dāng)報警時顯示肯定會閃。解決辦法是,把顯示改用定時器驅(qū)動顯示, ...

感謝師傅提點(diǎn),我目前把顯示那里的延時改成其他的延時,目前不閃了,不過,用定時器來顯示數(shù)碼管,沒有寫成功,可以看到數(shù)碼管一位位的在閃爍,定時時間是1us,
回復(fù)

使用道具 舉報

20#
ID:731755 發(fā)表于 2021-5-13 21:33 | 只看該作者
cn_zhx 發(fā)表于 2021-5-13 11:29
先進(jìn)行位選,再送數(shù)據(jù)。

好的,感謝,提點(diǎn)
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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