標(biāo)題: 請(qǐng)問C51單片機(jī)兩個(gè)延時(shí)函數(shù)互相干擾是什么原因? [打印本頁]

作者: 13872888583    時(shí)間: 2021-5-9 18:57
標(biāo)題: 請(qǐng)問C51單片機(jī)兩個(gè)延時(shí)函數(shù)互相干擾是什么原因?
各位大師,你們好,我是個(gè)小白,目前正在學(xué)習(xí)DS18B20測(cè)溫度,根據(jù)學(xué)習(xí)板的程序,可以正常顯示溫度,我想做一個(gè)可以溫度報(bào)警器,前面一個(gè)帖子,就是詢問想要數(shù)碼管顯示H的帖子,我經(jīng)過查詢資料,解決了,溫度超過30度,可以在數(shù)碼管末尾上顯示H,不過目前有個(gè)問題,我設(shè)定的是溫度超過30度,數(shù)碼管末尾也能顯示H,并且指示燈閃爍,蜂鳴器鳴叫,但是數(shù)碼管也會(huì)一直閃爍,當(dāng)溫度低于30度的時(shí)候,數(shù)碼管顯示就是正常的,我覺得,應(yīng)該是延時(shí)函數(shù)干擾造成的,我又另外寫了一個(gè)延時(shí)函數(shù),還是一樣的問題,請(qǐng)問各位大師,這是延時(shí)函數(shù)互相干擾嗎?如果想要解決問題,一定要用中斷嗎?

溫度.rar

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


作者: 13872888583    時(shí)間: 2021-5-9 18:59
#include"temp.h"
#include "intrins.h"
/*******************************************************************************
* 函 數(shù) 名         : Delay1ms
* 函數(shù)功能                   : 延時(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)會(huì)將在15us~60us后總線拉低
    DelayX10us(6)        ;
        while(DSPORT)        //等待DS18B20拉低總線
        {
                Delay1ms(1);
                i++;
                if(i>5)//等待>5MS
                {
                        return 0;//初始化失敗
                }
       
        }
        return 1;//初始化成功
}

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

void Ds18b20WriteByte(uchar dat)
{
        uint  j;

        for(j=0; j<8; j++)
        {
                DSPORT = 0;                       //每寫入一位數(shù)據(jù)之前先把總線拉低1us
                _nop_();
        _nop_();;
                DSPORT = dat & 0x01;  //然后寫入一個(gè)數(shù)據(jù),從最低位開始
                DelayX10us(6)        ;
                DSPORT = 1;        //然后釋放總線,至少1us給總線恢復(fù)時(shí)間才能接著寫入第二個(gè)數(shù)值
                dat >>= 1;
        }
}
/*******************************************************************************
* 函 數(shù) 名         : Ds18b20ReadByte
* 函數(shù)功能                   : 讀取一個(gè)字節(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,注意移動(dòng)之后移掉那位補(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;
}



作者: 13872888583    時(shí)間: 2021-5-9 19:00
#include "reg51.h"
#include "temp.h"
#define OVERTEMP 30 //定義超溫報(bào)警數(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() ;          
         }         
   }
   
作者: 13872888583    時(shí)間: 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


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

上電后是從main()開始動(dòng)行的。其它的函數(shù)無所謂順序。在main之后的函數(shù)在C文件的前端加入聲明;
如果是多個(gè)文件,要包含對(duì)應(yīng)的頭文件
作者: glinfei    時(shí)間: 2021-5-10 14:31
不是延時(shí)沖突問題,就是你程序?qū)懙膯栴},你延誤了一百多毫秒顯示一次就會(huì)閃爍.
            beep=~beep;
            DelayMS(100);  //主要這句導(dǎo)致
            led=~led;
            DelayMS(10) ;  
作者: 張?zhí)鞄?nbsp;   時(shí)間: 2021-5-10 16:22
多看看如何利用用定時(shí)器管理時(shí)間方面的架構(gòu),才能提升水平。DelayMs()只會(huì)誤事
作者: wulin    時(shí)間: 2021-5-10 16:27
與延時(shí)函數(shù)沒有直接關(guān)系,關(guān)鍵是協(xié)調(diào)好讀寫DS18B20的時(shí)序與數(shù)碼管動(dòng)態(tài)掃描的時(shí)間關(guān)系。給你一個(gè)示例參考。

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


作者: 赤研    時(shí)間: 2021-5-11 09:15
如果感到迷糊,就點(diǎn)開調(diào)試模式,或者自己讀程序,畫一個(gè)時(shí)序圖。你的這個(gè)程序做判斷的時(shí)間太久了
作者: birdzhyli    時(shí)間: 2021-5-11 11:17
單片機(jī)程序都是順序執(zhí)行,從main函數(shù) 開始 ,你的程序結(jié)構(gòu)挺好,先讀取溫度,轉(zhuǎn)換格式 ,顯示,問題在于你的動(dòng)態(tài)顯示里面用到了delay100ms,視覺不閃爍起碼要顯示頻率大于24,而你的顯示頻率小于10了,可以把LED控制和顯示數(shù)碼管分開。
前幾天看到大神的貼子,能不用delay盡量不用,因?yàn)閐elay的時(shí)候CPU沒有閑著,它一直在忙,別的程序就沒法執(zhí)行,除非像讀取DS18B20這種需要具體延時(shí)多少us或ms的時(shí)候用delay,其實(shí)顯示控制之類的可以用定時(shí)器來控制時(shí)間。在定時(shí)器中設(shè)置一個(gè)或幾個(gè)變量累加,到某個(gè)值之后置0,在主程序中判斷范圍顯示或是關(guān)閉
作者: 13872888583    時(shí)間: 2021-5-13 07:31
名字不是重點(diǎn) 發(fā)表于 2021-5-10 11:37
上電后是從main()開始動(dòng)行的。其它的函數(shù)無所謂順序。在main之后的函數(shù)在C文件的前端加入聲明;
如果是多 ...

好的,感謝,我在搜集別人的程序中,發(fā)現(xiàn)有人的程序確如師傅說的那樣。
作者: 13872888583    時(shí)間: 2021-5-13 07:33
glinfei 發(fā)表于 2021-5-10 14:31
不是延時(shí)沖突問題,就是你程序?qū)懙膯栴},你延誤了一百多毫秒顯示一次就會(huì)閃爍.
            beep=~beep;
...

你好,我在網(wǎng)上找到類似的程序,把顯示的那個(gè)地方的延時(shí)給換了,現(xiàn)在的就不閃了,謝謝
作者: 13872888583    時(shí)間: 2021-5-13 07:33
張?zhí)鞄?發(fā)表于 2021-5-10 16:22
多看看如何利用用定時(shí)器管理時(shí)間方面的架構(gòu),才能提升水平。DelayMs()只會(huì)誤事

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

好的,感謝,文件已下載
作者: 13872888583    時(shí)間: 2021-5-13 07:39
birdzhyli 發(fā)表于 2021-5-11 11:17
單片機(jī)程序都是順序執(zhí)行,從main函數(shù) 開始 ,你的程序結(jié)構(gòu)挺好,先讀取溫度,轉(zhuǎn)換格式 ,顯示,問題在于你 ...

你好,師傅,前幾天我用定時(shí)中斷來寫數(shù)碼顯示,可是效果不好,可以看到數(shù)碼管一位位的在跳變,溫度可以正常顯示,問題是時(shí)間填充,我已經(jīng)設(shè)置的很低了,1us一次跳動(dòng)顯示數(shù)碼管八位,
作者: aking991    時(shí)間: 2021-5-13 08:16
如果你顯示加蜂鳴器報(bào)警聲都放在主函數(shù)中,當(dāng)報(bào)警時(shí)顯示肯定會(huì)閃。解決辦法是,把顯示改用定時(shí)器驅(qū)動(dòng)顯示,或是把蜂鳴器報(bào)警放在定時(shí)器中驅(qū)動(dòng),這樣影響就比較小了,就看你定時(shí)器如何用了
作者: cn_zhx    時(shí)間: 2021-5-13 11:29
先進(jìn)行位選,再送數(shù)據(jù)。
作者: 13872888583    時(shí)間: 2021-5-13 21:32
aking991 發(fā)表于 2021-5-13 08:16
如果你顯示加蜂鳴器報(bào)警聲都放在主函數(shù)中,當(dāng)報(bào)警時(shí)顯示肯定會(huì)閃。解決辦法是,把顯示改用定時(shí)器驅(qū)動(dòng)顯示, ...

感謝師傅提點(diǎn),我目前把顯示那里的延時(shí)改成其他的延時(shí),目前不閃了,不過,用定時(shí)器來顯示數(shù)碼管,沒有寫成功,可以看到數(shù)碼管一位位的在閃爍,定時(shí)時(shí)間是1us,
作者: 13872888583    時(shí)間: 2021-5-13 21:33
cn_zhx 發(fā)表于 2021-5-13 11:29
先進(jìn)行位選,再送數(shù)據(jù)。

好的,感謝,提點(diǎn)




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1