发作品签到
专业版

#第九届立创电赛#温湿度检测仪8222040A

工程标签

117
0
0
0

简介

利用盛思锐温湿度模块检测环境温度和湿度,主控为STM32G030K6T6

简介:利用盛思锐温湿度模块检测环境温度和湿度,主控为STM32G030K6T6

开源协议

GPL 3.0

创建时间:2024-07-21 09:37:21更新时间:2024-07-31 03:18:54

描述

1、项目功能介绍


按下温度或湿度按键后,主控从睡眠中唤醒,通过I2C接口,与盛思锐温湿度模块通信获取检测到的环境温度和湿度,通过数码管显示温度或湿度,显示若干秒后,再次进入睡眠。主控为STM32G030K6T6,使用两节7号电池供电,软件使用stm32CubeIDE开发,使用HAL库。

微信图片_20240730073701-17223042013781.jpg

微信图片_20240730073714.jpg

2、项目属性


立创训练营(温湿度检测仪训练营)作业

3、开源协议


GPL 3.0

4、硬件部分


(1)电池防反接、电池仓、测量电池电压

image.png

通过pmos管防止电池反接烧坏电路,通过两个10kΩ电阻分压测量电池电压,注意:电阻精度应选择1%

(2)主控、晶振、复位电路

image.png

根据主控数据手册可以使用2.0v~3.6v供电,所以,可以直接使用两节7号电池串联供电,为了提升时钟信号准确性,外接了低速无源晶振。

(3)调试接口与扩展接口

image.png

使用ST-LINK调试,留了SWCLK和SWDIO接口,将未使用的io接口引出。

(4)低电量指示灯

image.png

一个led灯,用于指示电池电量低/

(5)数码管控制与数码管

image.png

为了减少主控IO使用数量,使用8位移位寄存器,该寄存器8位串行输入,并行输出。RCLK引脚每接收一个升沿时,从SER引脚接收一位数据,当接收了8位数据后,SRCLK引脚接收一个升沿,将刚才接收到的8位数据输出到QA~QH引脚。

如图:

image.png

数码管引脚:

image.png

(6)盛思锐温湿度模块

image.png

根据数据手册,模块使用I2C通信,给SDA和SCL分别接10kΩ上拉电阻

image.png

注意,引脚顺序

image.png

(7)按键

image.png

当sw1按下,数码管显示温度,当sw2按下,数码管显示湿度

(8)PCB设计

注意要给传感器模块留足空间,晶振底部不能铺铜和走线。

(9)焊接

先焊贴片后焊插件

(10)测试

最后用万用表电阻档测量3v引脚与GND是否短接,若电阻太小,说明短接

5、软件部分


(1)环境搭建

image.png

image.png
注意安装路径不要有中文

  • 在stm32CubeIDE登录自己的账号

(2)创建工程

image.png

(3)图形化界面配置引脚

image.png

GPIO

image.png
ADC

image.png
TIM

image.png

(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

image.png
由于MOQ限制,总价60.45元,部分材料有剩余。

7、大赛LOGO验证


image.png

8、演示您的项目并录制成视频上传


设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
1
立创电赛:温湿度检测仪-实物演示.mp4
0
2
代码.7z
0
3
BOM_Board1_Schematic1_2024-07-30.xlsx
0
4
Gerber_PCB1_2024-07-30.zip
0
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航