学习STM32的智能环境监测功能,我们将使用STM32的内置传感器和外部传感器来检测温度、湿度和光照强度。接下来,我会提供一个完整的代码案例,详细解释如何使用STM32进行环境监测。
在本案例中,我们将使用STM32F4 Discovery开发板,并假设你已经安装了Keil MDK-ARM开发环境,并熟悉相关的软硬件知识。
- 硬件准备 首先,我们需要准备STM32F4 Discovery开发板和相应的传感器模块。我们将使用DHT11传感器来测量温度和湿度,以及LDR光敏电阻器来测量光照强度。
将DHT11和LDR模块分别连接到STM32开发板的相应引脚,并确保连接正确。
- 代码编写 下面是一个完整的代码示例,用于读取DHT11和LDR模块的数据,并显示在串口终端上。
#include "stm32f4xx.h" #include "stdio.h"
// 定义DHT11引脚和端口 #define DHT11_PIN GPIO_Pin_0 #define DHT11_GPIO_PORT GPIOA
// 定义LDR引脚和端口 #define LDR_PIN GPIO_Pin_1 #define LDR_GPIO_PORT GPIOA
// 定义串口端口和波特率 #define USARTx USART2 #define USARTx_CLK RCC_APB1Periph_USART2 #define USARTx_IRQn USART2_IRQn #define USARTx_IRQHandler USART2_IRQHandler #define USARTx_TX_PIN GPIO_Pin_2 #define USARTx_RX_PIN GPIO_Pin_3 #define USARTx_GPIO_PORT GPIOA #define USARTx_GPIO_CLK RCC_AHB1Periph_GPIOA #define USARTx_BAUDRATE 9600
// 定义全局变量 uint8_t DHT11_Data[5]; // 存储从DHT11传感器读取的数据
// 初始化DHT11引脚 void DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);
}
// 从DHT11传感器读取数据 void DHT11_ReadData(void) { uint8_t laststate = GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_PIN); uint8_t counter = 0; uint8_t j = 0, i;
for (i = 0; i < 5; i++) {
DHT11_Data[i] = 0;
}
// 发送起始信号
GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_PIN);
delay_ms(18);
GPIO_SetBits(DHT11_GPIO_PORT, DHT11_PIN);
delay_us(20);
// 等待DHT11响应
while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_PIN) == laststate) {
if (counter++ == 100) {
return;
}
delay_us(1);
}
// 读取数据
for (i = 0; i < 40; i++) {
counter = 0;
while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_PIN) == laststate) {
if (counter++ == 100) {
return;
}
delay_us(1);
}
// 等待高电平结束
counter = 0;
while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_PIN) != laststate) {
if (counter++ == 100) {
return;
}
delay_us(1);
}
// 计算等待时长
if (counter > 40) {
DHT11_Data[j / 8] |= (1 << (7 - (j % 8)));
}
j++;
}
}
// 初始化LDR引脚 void LDR_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = LDR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LDR_GPIO_PORT, &GPIO_InitStructure);
}
// 读取LDR传感器数据 uint16_t LDR_ReadData(void) { return GPIO_ReadInputDataBit(LDR_GPIO_PORT, LDR_PIN); }
// 初始化串口 void USARTx_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure;
RCC_APB1PeriphClockCmd(USARTx_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(USARTx_GPIO_CLK, ENABLE);
GPIO_PinAFConfig(USARTx_GPIO_PORT, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(USARTx_GPIO_PORT, GPIO_PinSource3, GPIO_AF_USART2);
GPIO_InitStructure.GPIO_Pin = USARTx_TX_PIN | USARTx_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(USARTx_GPIO_PORT, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = USARTx_BAUDRATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USARTx, &USART_InitStructure);
USART_Cmd(USARTx, ENABLE);
}
// 发送数据到串口 void USARTx_SendData(uint8_t data) { while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); USART_SendData(USARTx, data); }
// 发送字符串到串口 void USARTx_SendString(char* string) { while (*string) { USARTx_SendData(*string); string++; } }
// 初始化系统时钟 void SystemClock_Config(void) { RCC_DeInit(); RCC_HSEConfig(RCC_HSE_ON); RCC_WaitForHSEStartUp(); RCC_PLLConfig(RCC_PLLSource_HSE, 8, 336, 4, 7); RCC_PLLCmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); while (RCC_GetSYSCLKSource() != 0x08); }
// 延时函数 void delay_us(uint32_t us) { volatile uint32_t i; us = us * (SystemCoreClock / 1000000); for (i = 0; i < us; i++); }
void delay_ms(uint32_t ms) { volatile uint32_t i; ms = ms * (SystemCoreClock / 1000); for (i = 0; i < ms; i++); }
int main(void) { // 初始化系统时钟 SystemClock_Config();
// 初始化DHT11和LDR引脚
DHT11_Init();
LDR_Init();
// 初始化串口
USARTx_Init();
while (1) {
// 读取DHT11数据
DHT11_ReadData();
// 打印温度和湿度数据
char temperature_str[5];
char humidity_str[5];
sprintf(temperature_str, "%d", DHT11_Data[2]);
sprintf(humidity_str, "%d", DHT11_Data[0]);
USARTx_SendString("\r\nTemperature: ");
USARTx_SendString(temperature_str);
USARTx_SendString(" C");
USARTx_SendString("\r\nHumidity: ");
USARTx_SendString(humidity_str);
USARTx_SendString(" %");
// 读取LDR数据
uint16_t ldr_data = LDR_ReadData();
// 打印光照强度数据
char ldr_str[5];
sprintf(ldr_str, "%d", ldr_data);
USARTx_SendString("\r