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

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

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

DS18B20讀取溫度時(shí)會(huì)突然變成85,然后馬上恢復(fù)正常

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1143673 發(fā)表于 2025-3-17 14:51 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
樓主正在做藍(lán)橋杯單片機(jī)的模擬題,是4T15屆模擬4的題目。需要用到DS18B20讀取溫度,但是溫度顯示會(huì)突然變成85,然后馬上恢復(fù)正常,我嘗試減慢溫度讀取的速度,但是無法根治問題,只是相同時(shí)間內(nèi)出現(xiàn)85的情況減少了,同樣是會(huì)出現(xiàn)問題。個(gè)人以為可以是底層有些問題,但是個(gè)人能力有限,想請(qǐng)教一下各位朋友,希望大家能夠不吝賜教。工程文件以及相關(guān)信息放在附件里了。 4T15屆模擬4.7z (373.8 KB, 下載次數(shù): 0)


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

使用道具 舉報(bào)

沙發(fā)
ID:1133081 發(fā)表于 2025-3-18 06:47 | 只看該作者
DS18B20初始化后溫度值寄存器里是初始數(shù)據(jù)“85”.要等約1秒才能讀到正確溫度,這是正,F(xiàn)象。可以在加電后初始化DS18B20,讀一次DS18B20,延時(shí)1秒再讀一次DS18B20,進(jìn)入主循環(huán)后再顯示溫度。可以避免顯示“85”。
回復(fù)

使用道具 舉報(bào)

板凳
ID:1143673 發(fā)表于 2025-3-18 10:22 | 只看該作者
WL0123 發(fā)表于 2025-3-18 06:47
DS18B20初始化后溫度值寄存器里是初始數(shù)據(jù)“85”.要等約1秒才能讀到正確溫度,這是正,F(xiàn)象?梢栽诩与姾 ...

您好,我在主函數(shù)里面已經(jīng)有一個(gè)循環(huán)防止上電就顯示85,現(xiàn)在的情況是上電沒有顯示85,是正常的數(shù)值,然后過一會(huì)兒就顯示85,然后馬上恢復(fù)正常。
void main(void) {
  unsigned char i;
  System_Init(); // 關(guān)閉LED燈和蜂鳴器
  while (rd_temperature() == 85) {
    ;
  }

  Timer0Init();
  Timer1Init(); // 定時(shí)器1初始化
  while (1) {
    Key_Proc(); // 按鍵處理函數(shù)
    Seg_Proc(); // 數(shù)碼管處理函數(shù)
    Led_Proc(); // LED顯示函數(shù)及溫度采集
  }
}
回復(fù)

使用道具 舉報(bào)

地板
ID:744809 發(fā)表于 2025-3-18 10:56 | 只看該作者
可以進(jìn)行數(shù)據(jù)校驗(yàn),只有校驗(yàn)通過的數(shù)據(jù)才賦值給溫度變量
回復(fù)

使用道具 舉報(bào)

5#
ID:277550 發(fā)表于 2025-3-18 11:22 | 只看該作者
碰到85,再重讀,……
回復(fù)

使用道具 舉報(bào)

6#
ID:1133081 發(fā)表于 2025-3-18 11:47 | 只看該作者
cien_s 發(fā)表于 2025-3-18 10:22
您好,我在主函數(shù)里面已經(jīng)有一個(gè)循環(huán)防止上電就顯示85,現(xiàn)在的情況是上電沒有顯示85,是正常的數(shù)值,然后 ...

理論上while (rd_temperature() == 85)的代碼沒有錯(cuò),但rd_temperature()函數(shù)的返回值是要經(jīng)過轉(zhuǎn)換的,否則返回的是16位數(shù)據(jù)。
回復(fù)

使用道具 舉報(bào)

7#
ID:1143673 發(fā)表于 2025-3-18 14:59 | 只看該作者
WL0123 發(fā)表于 2025-3-18 11:47
理論上while (rd_temperature() == 85)的代碼沒有錯(cuò),但rd_temperature()函數(shù)的返回值是要經(jīng)過轉(zhuǎn)換的,否 ...

您好,我的底層在讀數(shù)據(jù)的時(shí)候有經(jīng)過處理,然后我通過串口調(diào)試發(fā)現(xiàn)會(huì)讀到一些不正常的數(shù)據(jù)。
#include "onewire.h"
#include "reg52.h"

sbit DQ = P1 ^ 4;

// 單總線內(nèi)部延時(shí)函數(shù)
void Delay_OneWire(unsigned int t) {
  t *= 12;
  while (t--)
    ;
}

// 單總線寫操作
void Write_DS18B20(unsigned char dat) {
  unsigned char i;
  for (i = 0; i < 8; i++) {
    DQ = 0;
    DQ = dat & 0x01;
    Delay_OneWire(5);
    DQ = 1;
    dat >>= 1;
  }
  Delay_OneWire(5);
}

// 單總線讀操作
unsigned char Read_DS18B20(void) {
  unsigned char i;
  unsigned char dat;

  for (i = 0; i < 8; i++) {
    DQ = 0;
    dat >>= 1;
    DQ = 1;
    if (DQ) {
      dat |= 0x80;
    }
    Delay_OneWire(5);
  }
  return dat;
}

// DS18B20初始化
bit init_ds18b20(void) {
  bit initflag = 0;

  DQ = 1;
  Delay_OneWire(12);
  DQ = 0;
  Delay_OneWire(80);
  DQ = 1;
  Delay_OneWire(10);
  initflag = DQ;
  Delay_OneWire(5);

  return initflag;
}

float rd_temperature() {
  unsigned char low, high;
  init_ds18b20();
  Delay_OneWire(20);
  Write_DS18B20(0xcc);
  Write_DS18B20(0x44);
  init_ds18b20();
  Delay_OneWire(20);
  Write_DS18B20(0xcc);
  Write_DS18B20(0xbe);
  low = Read_DS18B20();
  high = Read_DS18B20();
  return ((high << 8) | low) / 16.0;
}

Error_Temperature:1048.875000
Error_Temperature:281.562500
Error_Temperature:-2026.375000
回復(fù)

使用道具 舉報(bào)

8#
ID:844772 發(fā)表于 2025-3-18 16:27 | 只看該作者
DS18B20是單總線結(jié)構(gòu)啊,你讀它的時(shí)候關(guān)中斷沒?
回復(fù)

使用道具 舉報(bào)

9#
ID:1143523 發(fā)表于 2025-3-18 22:11 | 只看該作者
得延時(shí)一下,因?yàn)閬聿患白x取就轉(zhuǎn)換了
回復(fù)

使用道具 舉報(bào)

10#
ID:92781 發(fā)表于 2025-3-19 08:57 | 只看該作者
上電顯示85代表讀取代碼正確,一直顯示85代表正負(fù)極反接,偶爾顯示85代表兩次讀取之間有掉電情況
回復(fù)

使用道具 舉報(bào)

11#
ID:1143673 發(fā)表于 2025-3-19 15:38 | 只看該作者
denghe 發(fā)表于 2025-3-18 22:11
得延時(shí)一下,因?yàn)閬聿患白x取就轉(zhuǎn)換了

您好,您說的延時(shí)哪里加延時(shí)呢,可以幫忙指點(diǎn)一下嗎?是在底層函數(shù)里面嗎?以下是我的底層驅(qū)動(dòng)
#include "onewire.h"
#include "reg52.h"

sbit DQ = P1 ^ 4;

// 單總線內(nèi)部延時(shí)函數(shù)
void Delay_OneWire(unsigned int t) {
  t *= 12;
  while (t--)
    ;
}

// 單總線寫操作
void Write_DS18B20(unsigned char dat) {
  unsigned char i;
  for (i = 0; i < 8; i++) {
    DQ = 0;
    DQ = dat & 0x01;
    Delay_OneWire(5);
    DQ = 1;
    dat >>= 1;
  }
  Delay_OneWire(5);
}

// 單總線讀操作
unsigned char Read_DS18B20(void) {
  unsigned char i;
  unsigned char dat;

  for (i = 0; i < 8; i++) {
    DQ = 0;
    dat >>= 1;
    DQ = 1;
    if (DQ) {
      dat |= 0x80;
    }
    Delay_OneWire(5);
  }
  return dat;
}

// DS18B20初始化
bit init_ds18b20(void) {
  bit initflag = 0;

  DQ = 1;
  Delay_OneWire(12);
  DQ = 0;
  Delay_OneWire(80);
  DQ = 1;
  Delay_OneWire(10);
  initflag = DQ;
  Delay_OneWire(5);

  return initflag;
}

float rd_temperature() {
  unsigned char low, high;
  init_ds18b20();
  Delay_OneWire(20);
  Write_DS18B20(0xcc);
  Write_DS18B20(0x44);
  init_ds18b20();
  Delay_OneWire(20);
  Write_DS18B20(0xcc);
  Write_DS18B20(0xbe);
  EA = 0;
  low = Read_DS18B20();
  high = Read_DS18B20();
  EA = 1;
  return (float)((high << 8) | low) * 0.0625;
}

我在主函數(shù)中是400多ms讀取一次的,其中我加了一些檢查讀取到的溫度數(shù)值是否正常的語句。
  1.   if (Seg_Slow_Down % 490 == 0) {
  2.     Temperature_Old = Temperature;
  3.     Temperature_Read = rd_temperature();
  4.     if (Temperature_Read > 50 || Temperature_Read < 10) {
  5.       error_time++;
  6.       printf("Error_Temperature:%f\r\n", Temperature_Read);
  7.       Temperature = Temperature_Old;
  8.     } else {
  9.       Temperature = Temperature_Read;
  10.     }
  11.   }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

12#
ID:1143673 發(fā)表于 2025-3-19 15:40 | 只看該作者
glinfei 發(fā)表于 2025-3-18 16:27
DS18B20是單總線結(jié)構(gòu)啊,你讀它的時(shí)候關(guān)中斷沒?

您好,請(qǐng)問單總線結(jié)構(gòu)要關(guān)中斷的嗎?我之前是沒有關(guān)中斷的,我嘗試在讀取溫度函數(shù)前后,關(guān)開中斷,但是還是會(huì)讀取到異常的數(shù)值,只是現(xiàn)在讀取到的數(shù)值都是-0.062500了。
Error_Temperature:-0.062500
Error_Temperature:-0.062500
Error_Temperature:-0.062500
回復(fù)

使用道具 舉報(bào)

13#
ID:530941 發(fā)表于 2025-3-19 17:14 | 只看該作者
你的需要把結(jié)果校驗(yàn)一下,有時(shí)候讀出來的值有問題的


//=========================DS18B20溫度傳感器=========================//
#define DS18B20_DQ_IN PIND & (1 << PD6)
/*******************************************************************************
* 函 數(shù) 名         : DS18B20_Reset
* 函數(shù)功能                   : 復(fù)位DS18B20
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void DS18B20_Reset(void)
{
    DDRD &= ~(1 << PD6);  // 端口輸入
    PORTD &= ~(1 << PD6); // 高阻態(tài)
    delay_ms(1);
    DDRD |= (1 << PD6); // 端口輸出,因?yàn)槭禽斎敫咦钁B(tài),設(shè)置成輸出時(shí)直接就會(huì)輸出低電平,拉低DQ
    delay_us(500);
    DDRD &= ~(1 << PD6); // 拉高DQ,釋放總線
    delay_us(10);
}
/**
* @brief  單總線初始化
* @param  無
* @retval 從機(jī)響應(yīng)位,0為響應(yīng),1為未響應(yīng)
*/
uchar DS18B20_Check(void)
{
    uchar i;
    uchar AckBit = 1;
    uchar TIMEOUT_MS = 500; // 進(jìn)行超時(shí)判斷

    DS18B20_Reset();

    while (DS18B20_DQ_IN && TIMEOUT_MS > 0)
    {
        TIMEOUT_MS--;
        AckBit = DS18B20_DQ_IN;
    }
    delay_ms(1);
    return AckBit;//如何DS18B20存在返回0,否則返回1
}
/*******************************************************************************
* 函 數(shù) 名         : DS18B20_Init
* 函數(shù)功能                   : 初始化DS18B20的IO口 DQ 同時(shí)檢測(cè)DS的存在
* 輸    入         : 無
* 輸    出         : 1:不存在,0:存在
*******************************************************************************/
uchar DS18B20_Init(void)
{
    uchar a;
    a = DS18B20_Check();
    return a;
}
/*******************************************************************************
* 函 數(shù) 名         : DS18B20_Write_Byte
* 函數(shù)功能                   : 寫一個(gè)字節(jié)到DS18B20
* 輸    入         : dat:要寫入的字節(jié)
* 輸    出         : 無
*******************************************************************************/
void DS18B20_Write_Byte(uchar dat)
{
    uchar j;
    uchar testb;
    for (j = 1; j <= 8; j++)
    {
        testb = dat & 0x01;
        dat = dat >> 1;
        if (testb)
        {
            DDRD |= (1 << PD6); // 拉低DQ
            delay_us(2);
            DDRD &= ~(1 << PD6); //輸入高阻態(tài),拉高DQ
            delay_us(60);
        }
        else // Write 0
        {
            DDRD |= (1 << PD6); // 拉低DQ
            delay_us(60);
            DDRD &= ~(1 << PD6); //輸入高阻態(tài),拉高DQ
            delay_us(2);
        }
    }
}
/*******************************************************************************
* 函 數(shù) 名         : DS18B20_Read_Bit
* 函數(shù)功能                   : 從DS18B20讀取一個(gè)位
* 輸    入         : 無
* 輸    出         : 1/0  1001 0000
*******************************************************************************/
uchar DS18B20_Read_Bit(void) // read one bit
{
    uchar data;
    DDRD |= (1 << PD6); // 拉低DQ
    delay_us(2);
    DDRD &= ~(1 << PD6); //輸入高阻態(tài),拉高DQ
    delay_us(2);
    if (DS18B20_DQ_IN)
    {
        data = 1;
    }
    else
    {
        data = 0;
    }
    delay_us(50);
    return data;
}

/*******************************************************************************
* 函 數(shù) 名         : DS18B20_Read_Byte
* 函數(shù)功能                   : 從DS18B20讀取一個(gè)字節(jié)
* 輸    入         : 無
* 輸    出         : 一個(gè)字節(jié)數(shù)據(jù)
*******************************************************************************/
uchar DS18B20_Read_Byte(void)    // read one byte
{        
        uchar i,j,dat;
        dat=0;
        for (i=0;i<8;i++)
        {
                j=DS18B20_Read_Bit();
        if(j==1)
        {
            dat|=(0x01<<i);
        }
        }                                                    
        return dat;
}
// 0xCC進(jìn)行設(shè)備尋址(只有一個(gè)從機(jī)時(shí)使用)
// 0x44溫度變換(讀取溫度前要執(zhí)行溫度變換,將溫度值放到暫存器里)
// 0xBE溫度讀。▽捍嫫骼锏臏囟茸x出)
//DS18B20指令
#define DS18B20_SKIP_ROM                        0xCC
#define DS18B20_CONVERT_T                        0x44
#define DS18B20_READ_SCRATCHPAD         0xBE

/*******************************************************************************
* 函 數(shù) 名         : DS18B20_Start
* 函數(shù)功能                   : 開始溫度轉(zhuǎn)換
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void DS18B20_Start(void)// ds1820 start convert
{                                                                            
        DS18B20_Check();         
        DS18B20_Write_Byte(DS18B20_SKIP_ROM);// skip rom
        DS18B20_Write_Byte(DS18B20_CONVERT_T);// convert
}

/*******************************************************************************
* 函 數(shù) 名         : DS18B20_GetTemperture
* 函數(shù)功能                   : 從ds18b20得到溫度值
* 輸    入         : 無
* 輸    出         : 溫度數(shù)據(jù)
*******************************************************************************/
uchar DS18B20_Crc(uchar *addr, uchar len)
{
    uchar crc = 0, inbyte, i, mix;
    while (len--)
    {
        // inbyte 存儲(chǔ)當(dāng)前參與計(jì)算的新字節(jié)
        inbyte = *addr++;

        for (i = 8; i; i--)
        {
            // 將新字節(jié)與CRC從低位到高位, 依次做異或運(yùn)算, 每次運(yùn)算完CRC右移一位
            // 如果運(yùn)算結(jié)果值為1, 則將CRC與 1000 1100 作異或
            // 第3,4位代表異或運(yùn)算, 第7位其實(shí)就是運(yùn)算結(jié)果移入的1
            mix = (crc ^ inbyte) & 0x01;
            crc >>= 1;
            if (mix)
            {
                crc ^= 0x8C;
            }
            inbyte >>= 1;
        }
    }
    return crc;
}
float DS18B20_GetTemperture(void)
{
    uint temp;
    uchar a, b;
    static float value;
    uchar tab[9], CRC8;

    DS18B20_Start(); // ds1820 start convert

    DS18B20_Check();
    DS18B20_Write_Byte(DS18B20_SKIP_ROM);        // skip rom
    DS18B20_Write_Byte(DS18B20_READ_SCRATCHPAD); // convert
    tab[0] = a = DS18B20_Read_Byte();            // LSB
    tab[1] = b = DS18B20_Read_Byte();            // MSB
    tab[2] = DS18B20_Read_Byte();                //
    tab[3] = DS18B20_Read_Byte();                //
    tab[4] = DS18B20_Read_Byte();                //
    tab[5] = DS18B20_Read_Byte();                //
    tab[6] = DS18B20_Read_Byte();                //
    tab[7] = DS18B20_Read_Byte();                //
    tab[8] = DS18B20_Read_Byte();                // CRC
    CRC8 = DS18B20_Crc(tab,8);
    if (CRC8 != tab[8])                          // CRC校驗(yàn)
    {
        return value;
    }

    temp = (b << 8) | a;
    if ((temp & 0xf800) == 0xf800)
    {
        temp = (~temp) + 1;
        value = temp * (-0.0625);
    }
    else
    {
        value = temp * 0.0625;
    }
    return value;
}
//=========================DS18B20溫度傳感器=========================//
回復(fù)

使用道具 舉報(bào)

14#
ID:1110477 發(fā)表于 2025-3-20 05:33 | 只看該作者
看來要好好讀手冊(cè)了
回復(fù)

使用道具 舉報(bào)

15#
ID:844772 發(fā)表于 2025-3-25 17:30 | 只看該作者
cien_s 發(fā)表于 2025-3-19 15:40
您好,請(qǐng)問單總線結(jié)構(gòu)要關(guān)中斷的嗎?我之前是沒有關(guān)中斷的,我嘗試在讀取溫度函數(shù)前后,關(guān)開中斷,但是還 ...

我的意思是它對(duì)時(shí)序特別敏感,如果被打斷就讀錯(cuò),開中斷肯定會(huì)有問題。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久精品亚洲精品国产欧美 | 在线观看成年人视频 | 久久久久国产一级毛片高清网站 | 日本超碰 | 一区二区三区在线观看视频 | 97精品超碰一区二区三区 | 亚洲欧美日韩在线一区二区 | 超碰精品在线观看 | 国产亚洲区 | 中文一区| 作爱视频免费看 | 天天操精品视频 | 久久久一区二区三区 | 色视频在线播放 | 久久久高清 | 久久久久国产 | 国产精品99久久免费观看 | 国产中文在线 | 亚洲欧美激情精品一区二区 | 日本福利一区 | 自拍偷拍视频网 | 日日夜夜天天久久 | 久久久国产一区二区三区 | 久草新在线 | 欧美国产日韩精品 | 国产成人网 | 亚洲狠狠丁香婷婷综合久久久 | 暖暖日本在线视频 | 蜜桃av一区二区三区 | 天天看夜夜 | 欧美一级二级三级视频 | 久草久草久草 | 日韩成人 | 欧美日韩在线一区 | 国产精品av久久久久久毛片 | 日韩精品在线一区 | 91av在线免费看 | 欧美在线观看一区 | 欧美日韩成人在线观看 | 久久不卡视频 | 国产久|