亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1069|回復: 10
收起左側

求助:dht11溫濕度檢測器一直檢測不到溫濕度

[復制鏈接]
回帖獎勵 2 黑幣 回復本帖可獲得 2 黑幣獎勵! 每人限 1 次(中獎概率 50%)
ID:1152570 發表于 2025-12-25 21:40 | 顯示全部樓層 |閱讀模式
dht11.h
#ifndef __DHT11_H
#define __DHT11_H

#include "stm32f10x.h"

#define DHT11_GPIO_PORT       GPIOC
#define DHT11_GPIO_CLK        RCC_APB2Periph_GPIOC
#define DHT11_GPIO_PIN        GPIO_Pin_15

#define DHT11_OUT_H           GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN)
#define DHT11_OUT_L           GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN)
#define DHT11_IN              GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN)

void DHT11_Init(void);
uint8_t DHT11_Read_Data(uint8_t *temperature, uint8_t *humidity);
uint8_t DHT11_Read_Byte(void);

#endif

dht11.c
#include "dht11.h"
#include "Delay.h"

void DHT11_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
   
    RCC_APB2PeriphClockCmd(DHT11_GPIO_CLK, ENABLE);
   
    GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);
   
    DHT11_OUT_H;
}

uint8_t DHT11_Read_Data(uint8_t *temperature, uint8_t *humidity)
{
    uint8_t buf[5];
    uint8_t i;
   
    DHT11_OUT_L;
    Delay_ms(18);
    DHT11_OUT_H;
    Delay_us(30);
   
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);
   
    if(DHT11_IN == 0)
    {
        while(!DHT11_IN);
        while(DHT11_IN);
        
        for(i=0; i<5; i++)
        {
            buf[i ] = DHT11_Read_Byte();
        }
        
        while(DHT11_IN == 0);
        
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);
        DHT11_OUT_H;
        
        if(buf[0] + buf[1] + buf[2] + buf[3] == buf[4])
        {
            *humidity = buf[0];
            *temperature = buf[2];
            return 1;
        }
    }
   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);
    DHT11_OUT_H;
    return 0;
}

uint8_t DHT11_Read_Byte(void)
{
    uint8_t i, temp = 0;
   
    for(i=0; i<8; i++)
    {
        while(!DHT11_IN);
        Delay_us(40);
        
        if(DHT11_IN == 1)
        {
            while(DHT11_IN);
            temp |= (1 << (7-i));
        }
        else
        {
            temp &= ~(1 << (7-i));
        }
    }
    return temp;
}

main.c
#include "stm32f10x.h"
#include "stdio.h"
#include "led.h"
#include "key.h"
#include "LCD1602.h"
#include "tim.h"
#include "delay.h"
#include "dht11.h"
#include "buzzer.h"
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stm32f1xx_hal_msp.h"

// 全局變量
int time_able=0;          // 系統總控制,0-停止 1-運行
int time_set = 10;        // 倒計時默認設定值(秒)
int time_ing_down = 10;    // 倒計時剩余值(秒)
int time_ing_up = 0;      // 正計時累計值(秒)
int time_lms = 0;         // 毫秒累計,1ms+1次
int time_led = 0;         // LED閃爍定時(毫秒)
int up_run_flag = 0;      // 正計時啟停標志,0-停止 1-運行
int down_run_flag = 0;    // 倒計時啟停標志,0-停止 1-運行

// 溫濕度相關變量
u8 temperature = 0;                 // 溫度值(℃)
u8 humidity = 0;                    // 濕度值(%)
u32 dht11_read_timer = 0;           // DHT11讀取計時器(1ms遞增)
u32 dht11_last_read_time = 0;       // 上次讀取DHT11的時間戳
char display_buffer[17];            // 顯示緩沖區

// 中斷測試變量
volatile u32 interrupt_count = 0;  // 中斷計數器

// LED和蜂鳴器控制變量
volatile u32 alarm_countdown = 0;  // 蜂鳴器倒計時
volatile u8 alarm_triggered = 0;   // 蜂鳴器觸發標志

// 按鍵3相關變量
volatile u8 key3_pressed = 0;       // 按鍵3按下標志
volatile u32 key3_hold_time = 0;     // 按鍵3按住時間(ms)
volatile u32 key3_last_change = 0;   // 上次改變倒計時值的時間(ms)

// 定時器2中斷服務函數,1ms執行一次
void TIM2_IRQHandler(void)
{
    // 清除并檢查定時器2更新中斷標志,繼續
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        time_lms++;
        dht11_read_timer++;  // DHT11讀取計時器累加
        interrupt_count++;   // 中斷計數器累加
        // 系統總控制啟動時的計時邏輯
        if(time_able == 1)
        {
            // ---------------- 倒計時邏輯 ----------------
            if(down_run_flag == 1 && time_ing_down > 0)
            {
                if(time_lms >= 10) // 累計1000ms=1秒
                {
                    time_lms = 0;
                    time_ing_down--;
                    // 倒計時結束,啟動LED和蜂鳴器提醒
                    if(time_ing_down == 0)
                    {
                        time_led = 10; // LED亮100ms(0.1秒)
                        alarm_triggered = 1; // 觸發蜂鳴器標志
                        alarm_countdown = 14; // 蜂鳴器響1.4秒(3次)
                        down_run_flag = 0; // 倒計時停止
                        time_ing_down=10;
                    }
                }
            }
                                                         

            // ---------------- 正計時邏輯 ----------------
            if(up_run_flag == 1)
            {
                if(time_lms >= 10) // 累計1000ms=1秒
                {
                    time_lms = 0;
                    time_ing_up++;
                    if(time_ing_up >= 10) time_ing_up = 99; // 上限保護
                }
            }
        }
        else
        {
            // 系統停止時,毫秒計數器清零,防止殘留
            time_lms = 0;
                                          up_run_flag = 0;
            down_run_flag = 0;
            time_ing_up = 0;
            time_ing_down = 10;
            time_led = 0;
            LED_OFF();
        }

        // LED閃爍邏輯
        if(time_led > 0)
        {
            LED_ON();  // time_led>0時LED亮
            time_led--;
        }
        else
        {
            LED_OFF(); // time_led=0時LED滅
        }

        // 蜂鳴器提醒邏輯(非阻塞)
        if(alarm_countdown > 0)
        {
            alarm_countdown--;
            // 每40ms為一個周期:前20ms響,后20ms停
            if(alarm_countdown % 4 < 2)
            {
                BUZZER_ON();
            }
            else
            {
                BUZZER_OFF();
            }
        }
        else
        {
            BUZZER_OFF();
            // 重置標志
            if(time_led == 0)
            {
                alarm_triggered = 0;
            }
        }

        // 清除中斷標志,繼續
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

int main(void)
{

    // 外設初始化
    delay_init();              // 延時函數初始化
    KEY_Init();                // 按鍵初始化
    LED_Init();                // LED初始化
    Buzzer_Init();             // 蜂鳴器初始化
    LCD_init();                // LCD初始化
    DHT11_Init();              // DHT11初始化
    tim2_init(100, 7200-1);       // 定時器2初始化,1ms中斷

    // LCD初始化顯示
    LCD1602_showstring(0, 1, "T:00 C H:00 %");  // 第一行:溫濕度
    LCD1602_showstring(0, 0, "UP:000s DN:010s"); // 第二行:計時

    while (1)
    {
        // ---------------- 按鍵處理邏輯 ----------------
        // 按鍵1:系統全局啟停控制,啟停
        if(KEY1 == 0)
        {
            Delay_ms(20); // 消抖
            if(KEY1 == 0)
            {
                time_able = !time_able; // 切換啟停狀態
                if(time_able == 0) // 停止時,清零所有狀態
                {
                    up_run_flag = 0;
                    down_run_flag = 0;
                    time_ing_up = 0;
                    time_ing_down = 10;
                    time_led = 0;
                    LED_OFF();
                }
                while(KEY1 == 0); // 等待按鍵釋放
            }
        }

        // 按鍵2:正計時啟停,系統運行時才有效
        if(KEY2 == 0 && time_able == 1)
        {
            Delay_ms(20); // 消抖
            if(KEY2 == 0)
            {
                up_run_flag = !up_run_flag; // 切換正計時啟停
                if(up_run_flag == 1 && time_ing_up == 0)
                {
                    time_ing_up = 0; // 正計時重置為0
                }
                while(KEY2 == 0); // 等待按鍵釋放
            }
        }

        // 按鍵3:長按調節倒計時時間,松開開始倒計時,系統運行時才有效
        if(KEY3 == 0 && time_able == 1)
        {
            Delay_ms(20); // 消抖
            if(KEY3 == 0)
            {
                if(key3_pressed == 0) // 剛按下
                {
                    key3_pressed = 1;
                    key3_hold_time = 0;
                    key3_last_change = 0;
                    down_run_flag = 0; // 暫停倒計時
                }
            }
        }

        // 按鍵3處理邏輯
        if(key3_pressed == 1)
        {
            // 在主循環中按鍵按住時間每10ms增加一次
            key3_hold_time += 10;

            // 長按每秒增加倒計時時間
            if(key3_hold_time - key3_last_change >= 100) // 每秒增加
            {
                key3_last_change = key3_hold_time;
                time_set++;
                if(time_set > 99) time_set = 99; // 上限999秒
                time_ing_down = time_set; // 更新顯示值
            }

            // 按鍵釋放檢測
            if(KEY3 == 1)
            {
                if(key3_hold_time < 50) // 短按(小于500ms)
                {
                    // 如果倒計時正在運行,則暫停;如果暫停,則開始
                    if(down_run_flag == 1)
                    {
                        down_run_flag = 0; // 暫停倒計時
                    }
                    else
                    {
                        down_run_flag = 1; // 開始倒計時
                        time_ing_down = time_set; // 使用當前設定值
                    }
                }
                else // 長按(大于500ms),松開開始倒計時
                {
                    down_run_flag = 1; // 開始倒計時
                    time_ing_down = time_set; // 使用當前設定值
                }

                // 重置按鍵狀態
                key3_pressed = 0;
                key3_hold_time = 0;
                key3_last_change = 0;
            }
        }


        // ---------------- LCD顯示邏輯 ----------------
        if(time_able == 1)
        {
            // 正計時顯示,第一行,列3
            LCD1602_shownum(3, 0, time_ing_up, 3);
            // 倒計時顯示,第一行,列11
            LCD1602_shownum(11, 0, time_ing_down, 3);
        }

        // ---------------- DHT11溫濕度讀取邏輯(每2秒讀取一次)----------------
        if(dht11_read_timer - dht11_last_read_time >= 20) // 2000ms = 2秒
        {
            dht11_last_read_time = dht11_read_timer;
            u8 temp, humi;
            if(DHT11_Read_Data(&temp, &humi)) // 讀取成功
            {
                temperature = temp;
                humidity = humi;
                // 使用sprintf格式化顯示字符串
             //   sprintf(display_buffer, "T:%2dC H:%2d%%", temperature, humidity);
             //   LCD1602_showstring(0, 1, display_buffer);
                                                          LCD1602_shownum(2, 1, temperature, 2);
                                              LCD1602_shownum(8, 1, humidity, 2);
            }
            // 如果讀取失敗,保留上次的值,不更新顯示
        }
        // 同時在time_able==1時也更新溫濕度顯示(確保顯示不消失)
        if(time_able == 1)
        {
          //  sprintf(display_buffer, "T:%2dC H:%2d%%", temperature, humidity);
          //  LCD1602_showstring(0, 1, display_buffer);
                                          LCD1602_shownum(2, 1, temperature, 2);
                                          LCD1602_shownum(9, 1, humidity, 2);
        }

        Delay_ms(5); // 減少CPU占用,提高響應速度

      
    }
}
屏幕截圖 2025-12-25 213844.png
mmexport1766655304441.png

01.7z

209.18 KB, 下載次數: 0

keil和proteus

回復

使用道具 舉報

ID:584814 發表于 2025-12-26 12:09 | 顯示全部樓層
本壇內搜索“DHT11 仿真”即可。
回復

使用道具 舉報

ID:592807 發表于 2025-12-27 11:16 | 顯示全部樓層
你怎么判斷01數據,你說怎么判斷uint8_t DHT11_Read_Byte(void)
{
    uint8_t i, temp = 0;
   
    for(i=0; i<8; i++)
    {
        while(!DHT11_IN);
        Delay_us(40);
        
        if(DHT11_IN == 1)
        {
            while(DHT11_IN);
            temp |= (1 << (7-i));
        }
        else
        {
            temp &= ~(1 << (7-i));
        }
    }
    return temp;
}
回復

使用道具 舉報

ID:469589 發表于 2025-12-27 18:41 | 顯示全部樓層
簡單問題復雜化了,簡單抄一個,一定好用,然后移植。
回復

使用道具 舉報

ID:349276 發表于 2025-12-28 09:39 來自觸屏版 | 顯示全部樓層
你仿真里,引腳都沒有連上它
回復

使用道具 舉報

ID:1152570 發表于 2025-12-28 10:14 | 顯示全部樓層
黃youhui 發表于 2025-12-27 11:16
你怎么判斷01數據,你說怎么判斷uint8_t DHT11_Read_Byte(void)
{
    uint8_t i, temp = 0;

我不太懂欸,沒怎么學明白
回復

使用道具 舉報

ID:1152570 發表于 2025-12-28 10:15 | 顯示全部樓層
萬家燈火51 發表于 2025-12-28 09:39
你仿真里,引腳都沒有連上它

你指的是哪個引腳哇,PC15嗎
回復

使用道具 舉報

ID:1152570 發表于 2025-12-28 10:15 | 顯示全部樓層
GlenXu 發表于 2025-12-27 18:41
簡單問題復雜化了,簡單抄一個,一定好用,然后移植。

我試試,其實這個也是移植過來的
回復

使用道具 舉報

ID:1152570 發表于 2025-12-28 16:36 | 顯示全部樓層
我又新找了一個代碼實現了,謝謝大家啦
回復

使用道具 舉報

ID:469589 發表于 2025-12-29 09:03 | 顯示全部樓層
滾雪球:
下作一個功能甚至一個I/O,不要直接做個系統。特別是不要從“通訊”開始。
有的專業認識很多年都沒搞清楚怎么作通訊。通訊確實很簡單,但不適合入手。
回復

使用道具 舉報

ID:1160531 發表于 2026-1-5 15:23 | 顯示全部樓層
一般來說,多數不能正確讀取數據的原因在于延時的準確性,這個需要先測試驗證好,然后程序的控制邏輯方面,嚴格按照時序要求就行。換了個程序成功了,還是要認真分析下自己所遇問題的根本原因是什么,祝你不斷進步。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表