|
|
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占用,提高響應速度
}
}
|
-
-
-
-
01.7z
2025-12-26 02:15 上傳
點擊文件名下載附件
209.18 KB, 下載次數: 0
keil和proteus
|