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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

DS18B20讀取溫度時會突然變成85,然后馬上恢復正常

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


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

使用道具 舉報

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

使用道具 舉報

板凳
ID:1143673 發表于 2025-3-18 10:22 | 只看該作者
WL0123 發表于 2025-3-18 06:47
DS18B20初始化后溫度值寄存器里是初始數據“85”.要等約1秒才能讀到正確溫度,這是正常現象。可以在加電后 ...

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

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

使用道具 舉報

地板
ID:744809 發表于 2025-3-18 10:56 | 只看該作者
可以進行數據校驗,只有校驗通過的數據才賦值給溫度變量
回復

使用道具 舉報

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

使用道具 舉報

6#
ID:1133081 發表于 2025-3-18 11:47 | 只看該作者
cien_s 發表于 2025-3-18 10:22
您好,我在主函數里面已經有一個循環防止上電就顯示85,現在的情況是上電沒有顯示85,是正常的數值,然后 ...

理論上while (rd_temperature() == 85)的代碼沒有錯,但rd_temperature()函數的返回值是要經過轉換的,否則返回的是16位數據。
回復

使用道具 舉報

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

您好,我的底層在讀數據的時候有經過處理,然后我通過串口調試發現會讀到一些不正常的數據。
#include "onewire.h"
#include "reg52.h"

sbit DQ = P1 ^ 4;

// 單總線內部延時函數
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
回復

使用道具 舉報

8#
ID:844772 發表于 2025-3-18 16:27 | 只看該作者
DS18B20是單總線結構啊,你讀它的時候關中斷沒?
回復

使用道具 舉報

9#
ID:1143523 發表于 2025-3-18 22:11 | 只看該作者
得延時一下,因為來不及讀取就轉換了
回復

使用道具 舉報

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

使用道具 舉報

11#
ID:1143673 發表于 2025-3-19 15:38 | 只看該作者
denghe 發表于 2025-3-18 22:11
得延時一下,因為來不及讀取就轉換了

您好,您說的延時哪里加延時呢,可以幫忙指點一下嗎?是在底層函數里面嗎?以下是我的底層驅動
#include "onewire.h"
#include "reg52.h"

sbit DQ = P1 ^ 4;

// 單總線內部延時函數
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;
}

我在主函數中是400多ms讀取一次的,其中我加了一些檢查讀取到的溫度數值是否正常的語句。
  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.   }
復制代碼
回復

使用道具 舉報

12#
ID:1143673 發表于 2025-3-19 15:40 | 只看該作者
glinfei 發表于 2025-3-18 16:27
DS18B20是單總線結構啊,你讀它的時候關中斷沒?

您好,請問單總線結構要關中斷的嗎?我之前是沒有關中斷的,我嘗試在讀取溫度函數前后,關開中斷,但是還是會讀取到異常的數值,只是現在讀取到的數值都是-0.062500了。
Error_Temperature:-0.062500
Error_Temperature:-0.062500
Error_Temperature:-0.062500
回復

使用道具 舉報

13#
ID:530941 發表于 2025-3-19 17:14 | 只看該作者
你的需要把結果校驗一下,有時候讀出來的值有問題的


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

    DS18B20_Reset();

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

/*******************************************************************************
* 函 數 名         : DS18B20_Read_Byte
* 函數功能                   : 從DS18B20讀取一個字節
* 輸    入         : 無
* 輸    出         : 一個字節數據
*******************************************************************************/
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進行設備尋址(只有一個從機時使用)
// 0x44溫度變換(讀取溫度前要執行溫度變換,將溫度值放到暫存器里)
// 0xBE溫度讀取(將暫存器里的溫度讀出)
//DS18B20指令
#define DS18B20_SKIP_ROM                        0xCC
#define DS18B20_CONVERT_T                        0x44
#define DS18B20_READ_SCRATCHPAD         0xBE

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

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

        for (i = 8; i; i--)
        {
            // 將新字節與CRC從低位到高位, 依次做異或運算, 每次運算完CRC右移一位
            // 如果運算結果值為1, 則將CRC與 1000 1100 作異或
            // 第3,4位代表異或運算, 第7位其實就是運算結果移入的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校驗
    {
        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溫度傳感器=========================//
回復

使用道具 舉報

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

使用道具 舉報

15#
ID:844772 發表于 2025-3-25 17:30 | 只看該作者
cien_s 發表于 2025-3-19 15:40
您好,請問單總線結構要關中斷的嗎?我之前是沒有關中斷的,我嘗試在讀取溫度函數前后,關開中斷,但是還 ...

我的意思是它對時序特別敏感,如果被打斷就讀錯,開中斷肯定會有問題。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 免费看a | 欧美精品一区二区三区在线播放 | 欧美精品片 | 97精品视频在线 | 亚洲www啪成人一区二区麻豆 | 久久国产一区二区三区 | 天天爽夜夜操 | 欧美国产日韩在线观看成人 | 在线黄色影院 | 日本一区二区三区四区 | 亚洲不卡一 | 日韩欧美精品在线 | 亚洲成人免费观看 | 国产黄色网址在线观看 | 成年人网站在线观看视频 | 日韩一区二区三区av | 国产成人精品免费 | 日韩有码一区 | 国产伦精品一区二区三区视频金莲 | 国产精品久久久 | 亚洲一区二区三区四区五区午夜 | 精品一区二区三区免费毛片 | 色接久久| 亚洲视频在线观看免费 | a级性视频 | 久久99精品久久久久久国产越南 | 黄在线 | 视频第一区 | 精品久久一区 | 日韩一区二区三区视频 | 伊人久久综合 | 精品中文在线 | 亚洲狠狠丁香婷婷综合久久久 | 尤物在线 | 国产亚洲欧美日韩精品一区二区三区 | 精品一区二区av | 精品一区二区三区在线播放 | 日日干日日操 | 天天插天天操 | 亚洲视频一区在线观看 | 特黄一级 |