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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 428|回復: 2
收起左側

LCD一直顯示溫度為0

[復制鏈接]
ID:1142165 發表于 2025-2-18 13:29 | 顯示全部樓層 |閱讀模式
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>

// 定義 LM016L 引腳
sbit RS = P2^3;
sbit RW = P2^2;
sbit EN = P2^1;
// 定義 DS18B20 引腳
sbit DQ = P1^4;
// 定義心率引腳
sbit HeartRateSensor = P3^2;
#define LCD_DATA P0

// 函數聲明
void delay_us(unsigned int us);
void delay_ms(unsigned int ms);
void lcd_init();
void lcd_command(unsigned char cmd);
void lcd_data(unsigned char dat);
void lcd_string(const char *str);
void display_heart_rate(unsigned int heart_rate);
void display_temperature(float temperature);
// DS18B20 相關函數聲明
bit ds18b20_reset(void);
void ds18b20_write_byte(unsigned char dat);
unsigned char ds18b20_read_byte(void);
float ds18b20_read_temp(void);

// 聲明 str 數組為全局變量
static unsigned char str[10];

// 全局變量用于心率計算
unsigned int pulse_count = 0;
unsigned int prev_pulse_count = 0;
unsigned int heart_rate = 0;

// 定時器 1 初始化函數,用于精確延時
void timer1_init() {
    TMOD |= 0x10;  // 定時器 1 工作在模式 1
    TR1 = 0;       // 先停止定時器 1
}

//精確的微秒延時函數
void delay_us(unsigned int us) {
    while(us--) {
        _nop_();  // 一個 _nop_() 指令大約 1 微秒(12MHz 晶振)
        _nop_();
        _nop_();
        _nop_();
    }
}

// 精確的毫秒延時函數,使用定時器 1
void delay_ms(unsigned int ms) {
    while (ms--) {
        delay_us(1000);
                          TR1=1;
    }
}

// 初始化 LCD
void lcd_init() {
    delay_ms(15);
    lcd_command(0x38); // 設置 16x2 顯示,5x7 點陣,8 位數據
    delay_ms(5);
    lcd_command(0x38);
    delay_ms(5);
    lcd_command(0x38);
    lcd_command(0x0C); // 打開顯示,關閉光標
    lcd_command(0x06); // 光標右移,字符不移動
    lcd_command(0x01); // 清屏
    delay_ms(5);
}

// 發送 LCD 命令
void lcd_command(unsigned char cmd) {
    RS = 0;
    RW = 0;
    LCD_DATA = cmd;
    EN = 1;
    _nop_();
    EN = 0;
    delay_ms(1);
}

// 發送 LCD 數據
void lcd_data(unsigned char dat) {
    RS = 1;
    RW = 0;
    LCD_DATA = dat;
    EN = 1;
    _nop_();
    EN = 0;
    delay_ms(1);
}

// 發送字符串到 LCD
void lcd_string(const char *str) {
    while (*str) {
        lcd_data(*str++);
    }
}

// 顯示心率
void display_heart_rate(unsigned int heart_rate) {
    lcd_command(0x87); // 設置顯示位置
    sprintf(str, "%d bpm", heart_rate);
    lcd_string(str);
}

// 顯示溫度
void display_temperature(float temperature) {
    lcd_command(0xC7); // 設置顯示位置
    if (temperature == -1) {
        sprintf(str, "Err");
    } else {
        sprintf(str, "%.1f C", temperature);
    }
    lcd_string((const char *)str);
}

// 修改復位函數使用精確延時
bit ds18b20_reset(void) {
    bit presence;
    DQ = 0;
    delay_us(480); // 拉低至少 480us
    DQ = 1;
    delay_us(60);  // 等待 15 - 60us
    presence = !DQ;
    delay_us(420); // 等待 480 - 960us
    return presence;
}

// 向 DS18B20 寫一個字節
void ds18b20_write_byte(unsigned char dat) {
    unsigned char i;
    for (i = 0; i < 8; i++) {
        DQ = 0;
        _nop_();
        DQ = dat & 0x01;
        delay_us(60); // 使用精確延時函數
        DQ = 1;
        dat >>= 1;
    }
}

// 從 DS18B20 讀一個字節
unsigned char ds18b20_read_byte(void) {
    unsigned char i, dat = 0;
    for (i = 0; i < 8; i++) {
        DQ = 0;
        _nop_();
        DQ = 1;
        _nop_();
        if (DQ) {
            dat |= (1 << i);
        }
        delay_us(60); // 使用精確延時函數
    }
    return dat;
}

// 讀取 DS18B20 的溫度值
float ds18b20_read_temp(void) {
    unsigned char low_byte, high_byte;
    int temp_value;
    float temperature;
    int retry = 3;  // 重試次數
    int reset_failure_count = 0;

    while (retry--) {
        if (ds18b20_reset()) {
            reset_failure_count++;
            continue; // 復位失敗,重試
        }
        ds18b20_write_byte(0xCC); // 跳過 ROM 操作
        ds18b20_write_byte(0x44); // 啟動溫度轉換
        delay_ms(750); // 等待轉換完成

        low_byte = ds18b20_read_byte();
        high_byte = ds18b20_read_byte();

        temp_value = (high_byte << 8) | low_byte;
        temperature = (float)temp_value * 0.0625;

            return temperature;
        }
    }

// 外部中斷 0 服務函數,用于檢測心率脈沖
void External0_ISR() interrupt 0 {
    pulse_count++;
}

// 主程序
void main() {
    float temperature = 0.0;
    unsigned int time_count = 0;

    timer1_init(); // 修正拼寫錯誤,正確調用定時器初始化函數

    // 初始化 LCD
    lcd_init();
    lcd_string("Heart: ");
    lcd_command(0xC0); // 第二行
    lcd_string("Temp: ");

    // 初始化外部中斷 0
    IT0 = 1;  // 下降沿觸發
    EX0 = 1;  // 使能外部中斷 0
    EA = 1;   // 使能全局中斷

    while(1) {
        // 每 1 秒計算一次心率
        delay_ms(1000);
        time_count++;
        if (time_count >= 1) {
            heart_rate = pulse_count - prev_pulse_count;
            prev_pulse_count = pulse_count;
            display_heart_rate(heart_rate);
            time_count = 0;
        }

        // 獲取溫度
        temperature = ds18b20_read_temp();
        display_temperature(temperature);
        delay_ms(1000);
                }       
}


lcd上一直顯示溫度為0
求大佬解決一下,幫一下感謝

回復

使用道具 舉報

ID:1133081 發表于 2025-2-18 21:21 | 顯示全部樓層
不要把delay當萬精油,超過1ms慎用!
回復

使用道具 舉報

ID:1133081 發表于 2025-2-19 14:34 | 顯示全部樓層
溫度讀取異常主要還是時序問題,心率采樣和計算也不對。給你改了,仿真無誤。 無標題.jpg

  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include <stdio.h>
  4. #define uint unsigned int
  5. #define uchar unsigned char
  6. #define DASE 60000
  7. // 定義 LM016L 引腳
  8. sbit RS = P2^3;
  9. sbit RW = P2^2;
  10. sbit EN = P2^1;
  11. // 定義 DS18B20 引腳
  12. sbit DQ = P1^4;
  13. // 定義心率引腳
  14. sbit HeartRateSensor = P3^2;
  15. #define LCD_DATA P0

  16. // 函數聲明
  17. void delay_us(unsigned int us);
  18. void delay_ms(unsigned int ms);
  19. void lcd_init();
  20. void lcd_command(unsigned char cmd);
  21. void lcd_data(unsigned char dat);
  22. void lcd_string(const char *str);
  23. void display_heart_rate(unsigned int heart_rate);
  24. void display_temperature(float temperature);
  25. // DS18B20 相關函數聲明
  26. bit ds18b20_reset(void);
  27. void ds18b20_write_byte(unsigned char dat);
  28. unsigned char ds18b20_read_byte(void);
  29. float ds18b20_read_temp(void);
  30. uint  D_num;            //定時器中斷計數變量
  31. // 聲明 str 數組為全局變量
  32. static unsigned char str[10];

  33. // 全局變量用于心率計算
  34. unsigned int pulse_count = 0;
  35. unsigned int prev_pulse_count = 0;
  36. unsigned int heart_rate = 0;
  37. uint  temp;                   //臨時變量
  38. uint  count;//計數
  39. float tempF;
  40. bit   flag_S=0;

  41. // 定時器0初始化函數
  42. void InitTimer0(void)
  43. {
  44.     TMOD = 0x01;
  45.     TH0 = 0xFC;
  46.     TL0 = 0x18;
  47.     EA = 1;
  48.     ET0 = 1;
  49.     TR0 = 1;
  50. }

  51. void delay_ms(unsigned int ms)//@12MHz
  52. {
  53.         unsigned i,j;
  54.         for(i=ms;i>0;i--)
  55.                 for(j=120;j>0;j--);
  56. }

  57. // 初始化 LCD
  58. void lcd_init()
  59. {
  60.     delay_ms(15);
  61.     lcd_command(0x38); // 設置 16x2 顯示,5x7 點陣,8 位數據
  62.     delay_ms(5);
  63.     lcd_command(0x38);
  64.     delay_ms(5);
  65.     lcd_command(0x38);
  66.     lcd_command(0x0C); // 打開顯示,關閉光標
  67.     lcd_command(0x06); // 光標右移,字符不移動
  68.     lcd_command(0x01); // 清屏
  69.     delay_ms(5);
  70. }

  71. // 發送 LCD 命令
  72. void lcd_command(unsigned char cmd)
  73. {
  74.     RS = 0;
  75.     RW = 0;
  76.     LCD_DATA = cmd;
  77.     delay_ms(1);
  78.     EN = 1;
  79.     _nop_();
  80.     EN = 0;
  81. }

  82. // 發送 LCD 數據
  83. void lcd_data(unsigned char dat)
  84. {
  85.     RS = 1;
  86.     RW = 0;
  87.     LCD_DATA = dat;
  88.     delay_ms(1);
  89.     EN = 1;
  90.     _nop_();
  91.     EN = 0;
  92. }

  93. // 發送字符串到 LCD
  94. void lcd_string(const char *str)
  95. {
  96.         while (*str)
  97.         {
  98.                 lcd_data(*str++);
  99.         }
  100. }

  101. // 顯示心率
  102. void display_heart_rate(unsigned int heart_rate)
  103. {
  104.     lcd_command(0x87); // 設置顯示位置
  105.     sprintf(str, "%d bpm ", heart_rate);
  106.     lcd_string(str);
  107. }

  108. // 顯示溫度
  109. void display_temperature(float temperature)
  110. {
  111.         lcd_command(0xC7); // 設置顯示位置
  112.         if (temperature == -1)
  113.         {
  114.                 sprintf(str, "Err");
  115.         }
  116.         else
  117.         {
  118.                 sprintf(str, "%.1f C", temperature);
  119.         }
  120.         lcd_string((const char *)str);
  121. }
  122. /*
  123. // 修改復位函數使用精確延時
  124. bit ds18b20_reset(void)
  125. {
  126.     bit presence;
  127.     DQ = 0;
  128.     delay_us(480); // 拉低至少 480us
  129.     DQ = 1;
  130.     delay_us(60);  // 等待 15 - 60us
  131.     presence = !DQ;
  132.     delay_us(420); // 等待 480 - 960us
  133.     return presence;
  134. }

  135. // 向 DS18B20 寫一個字節
  136. void ds18b20_write_byte(unsigned char dat)
  137. {
  138.     unsigned char i;
  139.     for (i = 0; i < 8; i++)
  140.         {
  141.         DQ = 0;
  142.         _nop_();
  143.         DQ = dat & 0x01;
  144.         delay_us(60); // 使用精確延時函數
  145.         DQ = 1;
  146.         dat >>= 1;
  147.     }
  148. }

  149. // 從 DS18B20 讀一個字節
  150. unsigned char ds18b20_read_byte(void)
  151. {
  152.     unsigned char i, dat = 0;
  153.     for (i = 0; i < 8; i++)
  154.         {
  155.         DQ = 0;
  156.         _nop_();
  157.         DQ = 1;
  158.         _nop_();
  159.         if (DQ)
  160.                 {
  161.             dat |= (1 << i);
  162.         }
  163.         delay_us(60); // 使用精確延時函數
  164.     }
  165.     return dat;
  166. }

  167. // 讀取 DS18B20 的溫度值
  168. float ds18b20_read_temp(void)
  169. {
  170.     unsigned char low_byte, high_byte;
  171.     int temp_value;
  172.     float temperature;
  173.     int retry = 3;  // 重試次數
  174.     int reset_failure_count = 0;

  175.     while (retry--)
  176.         {
  177.         if (ds18b20_reset())
  178.                 {
  179.             reset_failure_count++;
  180.             continue; // 復位失敗,重試
  181.         }
  182.         ds18b20_write_byte(0xCC); // 跳過 ROM 操作
  183.         ds18b20_write_byte(0x44); // 啟動溫度轉換
  184.         delay_ms(750); // 等待轉換完成

  185.         low_byte = ds18b20_read_byte();
  186.         high_byte = ds18b20_read_byte();

  187.         temp_value = (high_byte << 8) | low_byte;
  188.         temperature = (float)temp_value * 0.0625;

  189.         return temperature;
  190.     }
  191. }*/

  192. void delay(uint t)//@12T 1us
  193. {
  194.         while(t--);      
  195. }

  196. void Init_DS18b20()//18b20初始化函數
  197. {
  198.         DQ = 1;    //DQ復位
  199.         delay(8);
  200.         DQ=0;    //釋放DQ
  201.         delay(80); //DS18B20收到信號后延時
  202.         DQ=1;   //讀取DQ
  203.         delay(30);
  204. }
  205. void write_byte(uchar dat)//寫時序
  206. {
  207.         uchar i=0;
  208.         for(i=8;i>0;i--)
  209.         {
  210.                 DQ=0;
  211.                 DQ=dat&0x01;//寫1,在15微秒內拉低
  212.                 delay(5);//寫0,拉低60微秒
  213.                 DQ=1;
  214.                 dat>>=1;
  215.         }
  216.         delay(4);
  217. }

  218. uchar read_byte()//讀時序
  219. {
  220.         uchar i=0;
  221.         uchar dat=0;
  222.         for(i=8;i>0;i--)
  223.         {
  224.                 DQ=0;//拉低ds18b20單總線
  225.                 dat>>=1;
  226.                 DQ=1;//15微秒內拉釋放總線
  227.                 if(DQ)
  228.                 dat|=0x80;
  229.                 delay(4);
  230.         }
  231.         return (dat);
  232. }
  233. //void Read_Temperature()//讀取溫度函數
  234. float ds18b20_read_temp(void)
  235. {
  236.         Init_DS18b20();  //初始化18b20
  237.         write_byte(0xcc);//跳過讀寫序列號
  238.         write_byte(0x44);//啟動溫度轉換
  239.         Init_DS18b20();  //初始化18b20
  240.         write_byte(0xCC);//跳過讀寫序列號
  241.         write_byte(0xBE);//讀溫度寄存器
  242.         temp=read_byte();//讀取溫度低8位
  243.         temp=read_byte()<<8|temp;//讀取溫度高8位
  244.         tempF=temp*0.0625;
  245.         return tempF;

  246. }
  247. void Timer0Interrupt() interrupt 1
  248. {
  249.         static uint i;
  250.         TH0 = 0xFC;
  251.         TL0 = 0x18;
  252.         count++;
  253.         i++;
  254.         if(i>=500)                                //0.5秒
  255.         {
  256.                 i=0;
  257.                 flag_S=1;                        //0.5秒標志
  258.         }
  259. }
  260. // 外部中斷 0 服務函數,用于檢測心率脈沖
  261. void External0_ISR() interrupt 0
  262. {
  263.         TR0=0;                                        //關定時器0
  264.         D_num=count;                        //讀取定時器1ms中斷計數值
  265.         count=0;                                        //定時器1ms中斷計數值清0
  266.         TH0 = 0xFC;
  267.         TL0 = 0x18;
  268.         TR0=1;                                        //開定時器0
  269. }

  270. // 主程序
  271. void main()
  272. {
  273.         float temperature = 0.0;
  274.         unsigned int time_count = 0;
  275.         // 初始化 LCD
  276.         lcd_init();
  277.         lcd_string("Heart: ");
  278.         lcd_command(0xC0); // 第二行
  279.         lcd_string("Temp: ");
  280.         InitTimer0();        
  281.         // 初始化外部中斷 0
  282.         IT0 = 1;  // 下降沿觸發
  283.         EX0 = 1;  // 使能外部中斷 0
  284.         EA = 1;   // 使能全局中斷
  285.         IE0 = 0;         //INT0中斷請求標志清0       
  286.         while(1)
  287.         {
  288.                 if(flag_S)//0.5秒
  289.                 {
  290.                         flag_S=0;
  291.                         heart_rate = DASE/D_num;        //計算心率
  292.                         display_heart_rate(heart_rate);
  293.                         // 獲取溫度
  294.                         temperature = ds18b20_read_temp();
  295.                         display_temperature(temperature);
  296.                 }               
  297.         }      
  298. }
復制代碼




回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲视频在线一区 | 欧美三区在线观看 | 日韩精品久久一区 | 欧美亚洲高清 | 午夜影院操 | 懂色中文一区二区三区在线视频 | 日韩精品久久一区二区三区 | 国产精品一区久久久久 | 精品久久国产 | 91久久精品一区二区二区 | 日韩成人在线看 | 91麻豆精品国产91久久久久久久久 | 美女黄频 | 国产精品高潮呻吟久久av野狼 | 亚洲色欧美另类 | 久久精品国产精品青草 | 在线观看国产h | 男女下面一进一出网站 | 国产一区二区三区 | 久草视频在线看 | 国产精品一级 | 国产日韩欧美二区 | 精品视频在线观看 | 福利久久 | 亚洲精品久久久久久久久久吃药 | 91视频观看 | 欧美日韩网站 | 免费不卡视频 | 午夜精品三区 | 精品9999| 欧美一级视频在线观看 | 成人亚洲精品 | 天天操欧美 | 一区在线观看 | 欧美视频一区二区三区 | 91视频在线 | 美女天天操 | 成人精品久久 | 天天草av| 懂色tv| 国产高清精品一区二区三区 |