
#第九届立创电赛#温湿度检测仪8222040A
简介
利用盛思锐温湿度模块检测环境温度和湿度,主控为STM32G030K6T6
简介:利用盛思锐温湿度模块检测环境温度和湿度,主控为STM32G030K6T6开源协议
:GPL 3.0
描述
1、项目功能介绍
按下温度或湿度按键后,主控从睡眠中唤醒,通过I2C接口,与盛思锐温湿度模块通信获取检测到的环境温度和湿度,通过数码管显示温度或湿度,显示若干秒后,再次进入睡眠。主控为STM32G030K6T6,使用两节7号电池供电,软件使用stm32CubeIDE开发,使用HAL库。
2、项目属性
立创训练营(温湿度检测仪训练营)作业
3、开源协议
GPL 3.0
4、硬件部分
(1)电池防反接、电池仓、测量电池电压
通过pmos管防止电池反接烧坏电路,通过两个10kΩ电阻分压测量电池电压,注意:电阻精度应选择1%
(2)主控、晶振、复位电路
根据主控数据手册可以使用2.0v~3.6v供电,所以,可以直接使用两节7号电池串联供电,为了提升时钟信号准确性,外接了低速无源晶振。
(3)调试接口与扩展接口
使用ST-LINK调试,留了SWCLK和SWDIO接口,将未使用的io接口引出。
(4)低电量指示灯
一个led灯,用于指示电池电量低/
(5)数码管控制与数码管
为了减少主控IO使用数量,使用8位移位寄存器,该寄存器8位串行输入,并行输出。RCLK引脚每接收一个升沿时,从SER引脚接收一位数据,当接收了8位数据后,SRCLK引脚接收一个升沿,将刚才接收到的8位数据输出到QA~QH引脚。
如图:
数码管引脚:
(6)盛思锐温湿度模块
根据数据手册,模块使用I2C通信,给SDA和SCL分别接10kΩ上拉电阻
注意,引脚顺序
(7)按键
当sw1按下,数码管显示温度,当sw2按下,数码管显示湿度
(8)PCB设计
注意要给传感器模块留足空间,晶振底部不能铺铜和走线。
(9)焊接
先焊贴片后焊插件
(10)测试
最后用万用表电阻档测量3v引脚与GND是否短接,若电阻太小,说明短接
5、软件部分
(1)环境搭建
- 下载JAVA8:java.com/zh-CN/
- 下载stm32CubeIDE:https://www.st.com/en/development-tools/stm32cubeide.html
注意安装路径不要有中文
- 在stm32CubeIDE登录自己的账号
(2)创建工程
(3)图形化界面配置引脚
GPIO
ADC
TIM
(4)代码编写
原课程项目文档204:桌面温湿度仪项目文档 (yuque.com),在此基础上,略有改动。
总体逻辑
- 初始化:系统启动时,初始化所有相关的硬件接口,包括GPIO, I2C, ADC, 和定时器。
- 睡眠模式:在主循环中,设备默认进入睡眠模式,等待按键中断唤醒。
- 按键处理:当温度或湿度按键被按下触发中断唤醒设备,并通过消抖处理后,调用 Body() 函数读取并处理温湿度数据,启动定时器进行数据显示。
- 显示控制:通过定时器中断控制数码管显示,显示温度或湿度数据。如果在一定时间内没有按键操作,设备将自动返回睡眠状态。
- 电压监控:在 Body() 函数中,还会检查电池电压,如果电压过低,将点亮LED0作为指示。
adc.c
/*adc.c*/
float Get_VolValue(void)
{
uint32_t ADC_Value = 0;
float VolValue = 0;
HAL_ADC_Start(&hadc1); // 启动ADC
HAL_ADC_PollForConversion(&hadc1, 50); // 等待转换完成或超时
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
ADC_Value = HAL_ADC_GetValue(&hadc1); // 读取ADC值
VolValue = (ADC_Value*3.0f)/4095.0f; // 将ADC值转换为电压值
}
return VolValue; // 返回电压值
}
i2c.c
/*i2c.c*/
void SHT40_Read_RHData(float *temperature,float *humidity)
{
uint8_t writeData[1] = {0xFD}; // 用于启动温湿度传感器的命令
uint8_t readData[6] = {0}; // 存储从传感器读取的数据
uint32_t tempData = 0;
HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)SHT40_Write, (uint8_t *)writeData, 1, HAL_MAX_DELAY); // 向传感器发送命令
HAL_Delay(10); // 等待传感器处理
HAL_I2C_Master_Receive(&hi2c1, (uint16_t)SHT40_Read, (uint8_t *)readData, 6, HAL_MAX_DELAY); // 从传感器接收数据
tempData = readData[0] << 8 | readData[1]; // 处理温度数据
*temperature = (tempData * 175.0f) / 65535.0f - 45; // 转换为摄氏度
tempData = readData[3] << 8 | readData[4]; // 处理湿度数据
*humidity = (tempData * 125.0f) / 65535.0f - 6; // 转换为相对湿度百分比
}
gpio.c
/*gpio.c*/
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
// 根据中断源的引脚号,更新按键状态
if(GPIO_Pin == TEMPERATURE_KEY_Pin){
device_paramter.TEMPERATURE_KEY_Status = KEY_SHAKE_STATE; // 温度按键状态
HAL_ResumeTick(); // 恢复系统滴答定时器
}
if(GPIO_Pin == HUMIDITY_KEY_Pin){
device_paramter.HUMIDITY_KEY_Status = KEY_SHAKE_STATE; // 湿度按键状态
HAL_ResumeTick(); // 恢复系统滴答定时器
}
}
void Send_Data(unsigned int sendValue)
{
// 通过移位和位检查,控制GPIO用于驱动数码管
uint8_t i = 0;
for (i = 0; i < 8; i++)
{
if(((sendValue << i) & 0x80) != 0)
{
HAL_GPIO_WritePin(GPIOA, SER_Pin, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOA, SER_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(GPIOA, SRCLK_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, SRCLK_Pin, GPIO_PIN_SET);
}
HAL_GPIO_WritePin(GPIOA, RCLK_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, RCLK_Pin, GPIO_PIN_SET);
}
void ShowNum(uint8_t column, uint8_t value)
{
// 控制数码管显示数字
switch(column)
{
case 1:
HAL_GPIO_WritePin(GPIOA, DIG1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, DIG2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, DIG3_Pin, GPIO_PIN_SET);
Send_Data(sgh_value[value]);
break;
case 2:
HAL_GPIO_WritePin(GPIOA, DIG1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, DIG2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, DIG3_Pin, GPIO_PIN_SET);
Send_Data(sgh_value[value] | 0x80); // 在第二列数码管显示“.”
break;
case 3:
HAL_GPIO_WritePin(GPIOA, DIG1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, DIG2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, DIG3_Pin, GPIO_PIN_RESET);
Send_Data(sgh_value[value]);
break;
}
Send_Data(0x00); // 清空数据,避免干扰
}
void Off_LED()
{
// 关闭所有LED,用于进入睡眠模式
HAL_GPIO_WritePin(GPIOA, DIG1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, DIG2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, DIG3_Pin, GPIO_PIN_SET);
Send_Data(0x00); // 清空数据
}
tim.c
/*tim.c*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// 定时器中断回调函数,用于更新显示和控制设备状态
if(htim->Instance == TIM14)
{
HAL_TIM_Base_Stop_IT(&htim14); // 停止定时器中断
updata_flag++; // 更新标志
if(updata_flag <= 5000)
{
if(device_paramter.TEMPERATURE_KEY_Status == KEY_SHAKE_STATE) // 检查温度按键状态
{
ShowNum(1, (device_paramter.Temp / 100));
ShowNum(2, (device_paramter.Temp / 10 % 10));
ShowNum(3, device_paramter.Temp % 10);
}
else if(device_paramter.HUMIDITY_KEY_Status == KEY_SHAKE_STATE) // 检查湿度按键状态
{
ShowNum(1, (device_paramter.Humi / 100));
ShowNum(2, (device_paramter.Humi / 10 % 10));
ShowNum(3, device_paramter.Humi % 10);
}
__HAL_TIM_SetCounter(&htim14, 0); // 重置定时器计数器
HAL_TIM_Base_Start_IT(&htim14); // 重新启动定时器中断
}
else
{
updata_flag = 0;
device_paramter.sleepStatus = 1; // 更新睡眠状态
device_paramter.TEMPERATURE_KEY_Status = KEY_NO_PRESS; // 重置按键状态
device_paramter.HUMIDITY_KEY_Status = KEY_NO_PRESS; // 重置按键状态
Off_LED(); // 关闭显示
}
__HAL_TIM_SetCounter(&htim14, 0); // 重置定时器计数器
}
}
main.c
/*main.c*/
void Body(void)
{
// 主体函数,用于处理传感器数据和控制显示
float temperature = 0;
float humidity = 0;
SHT40_Read_RHData(&temperature, &humidity); // 读取温度和湿度
device_paramter.Temp = temperature * 10; // 存储温度
device_paramter.Humi = humidity * 10; // 存储湿度
HAL_TIM_Base_Start_IT(&htim14); // 启动定时器中断
device_paramter.sleepStatus = 0; // 更新睡眠状态
HAL_ADCEx_Calibration_Start(&hadc1); // 校准ADC
if(Get_VolValue() <= 2.7)
{
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET); // 电池电压低时,点亮LED0
}
}
int main(void)
{
// 主函数,初始化硬件和处理循环
HAL_Init(); // 初始化HAL库
SystemClock_Config(); // 配置系统时钟
MX_GPIO_Init(); // 初始化GPIO
MX_I2C1_Init(); // 初始化I2C
MX_ADC1_Init(); // 初始化ADC
MX_TIM14_Init(); // 初始化定时器
Off_LED(); // 初始关闭LED
HAL_SuspendTick(); // 暂停系统滴答定时器
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); // 进入睡眠模式
while (1)
{
// 循环处理按键事件和睡眠状态
if(device_paramter.TEMPERATURE_KEY_Status == KEY_SHAKE_STATE)
{
HAL_Delay(10); // 延时以消抖
if(HAL_GPIO_ReadPin(GPIOB, TEMPERATURE_KEY_Pin) == GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(GPIOB, TEMPERATURE_KEY_Pin) == GPIO_PIN_RESET); // 等待按键释放
Body(); // 处理主体函数
}
}
else if(device_paramter.HUMIDITY_KEY_Status == KEY_SHAKE_STATE)
{
HAL_Delay(10); // 延时以消抖
if(HAL_GPIO_ReadPin(GPIOB, HUMIDITY_KEY_Pin) == GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(GPIOB, HUMIDITY_KEY_Pin) == GPIO_PIN_RESET); // 等待按键释放
Body(); // 处理主体函数
}
}
else if(device_paramter.sleepStatus == 1)
{
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET); // 睡眠状态时,点亮LED0
HAL_SuspendTick(); // 暂停系统滴答定时器
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); // 重新进入睡眠模式
}
}
}
6、BOM清单
盛思锐温湿度模块:c22437501
由于MOQ限制,总价60.45元,部分材料有剩余。
7、大赛LOGO验证
8、演示您的项目并录制成视频上传
设计图

BOM


工程成员



评论