STM32F030 环境监测传感器程序设计(ADC 采集 + DO 控制)
目录
一、前言
环境监测传感器是工业与民用场景中常用的传感器类型,本次基于 STM32F030 开发板设计环境监测传感器程序,核心实现两类功能:一是 DO 外设(蜂鸣器、LED)的远程控制,二是 AI 外设(光敏电阻、可调电阻)的 ADC 电压采集。程序沿用 PC→STM32H5→STM32F030 的通信架构,通过 Modbus 协议与 PC 端 Modbus Poll 软件交互,完成环境光强、电阻电压的采集及声光外设的精准控制。
二、硬件引脚与 CubeMX 配置
1. 硬件引脚映射
环境监测模块的外设功能、引脚、工作逻辑及寄存器类别对应如下,需根据该表在 CubeMX 中完成基础 GPIO/ADC 配置:
| 模块 | 功能 | 引脚 | 工作逻辑 | 寄存器类别 |
|---|---|---|---|---|
| 环境监测模块 | BEEP1 | PB15 | 高电平触发响铃 | DO |
| BEEP2 | PB14 | 高电平触发响铃 | DO | |
| LED1 | PB11 | 低电平点亮 | DO | |
| LED2 | PB12 | 低电平点亮 | DO | |
| LED3 | PB13 | 低电平点亮 | DO | |
| OPTO_ADC | PA1 | 电压值与光强成反比 | AI | |
| RES_ADC | PA2 | 电压值与可调电阻成反比 | AI |
2. CubeMX 配置注意事项
除基础的 GPIO(DO 外设设为输出)、ADC(AI 外设设为模拟输入)配置外,需重点注意:配置 ADC 时必须启用Discontinuous Conversion Mode(离散转换模式),保障多通道 ADC 采集的稳定性。
三、点表设计:通信规则标准化
为明确 PC 与 F030 环境监测传感器的通信规则,设计如下点表,清晰定义设备地址、寄存器地址、类别及功能:
| 设备地址 | 寄存器地址 | 寄存器类别 | 用途 | 描述 |
|---|---|---|---|---|
| 02H | 0000H | DO | 控制蜂鸣器 1 | 1 - 响 |
| 02H | 0001H | DO | 控制蜂鸣器 2 | 1 - 响 |
| 02H | 0002H | DO | 控制 LED1 | 1 - 亮 |
| 02H | 0003H | DO | 控制 LED2 | 1 - 亮 |
| 02H | 0004H | DO | 控制 LED3 | 1 - 亮 |
| 02H | 0000H | AI | 读取光敏电阻电压 | 0xfff 对应 3.3V(12 位精度) |
| 02H | 0001H | AI | 读取可调电阻电压 | 0xfff 对应 3.3V(12 位精度) |
补充:AI 寄存器为 12 位 ADC 采集值,最大值 0xfff 对应 3.3V 参考电压,可通过电压值换算光敏电阻的光强、可调电阻的阻值。
四、F030 程序实现:ADC 校准 + 寄存器联动
环境监测传感器使用 ADC 采集模拟电压,需先完成 ADC 校准保障采集精度;程序通过宏定义区分传感器类型,实现 DO 外设控制与 AI 电压采集的核心逻辑,代码及关键注释如下(未修改原有代码逻辑):
// 启用环境监测传感器功能(宏定义便于切换不同传感器逻辑)
#define USE_ENV_MONITOR_SENSOR 1
#ifdef USE_ENV_MONITOR_SENSOR
// 声明ADC句柄(由CubeMX自动生成)
extern ADC_HandleTypeDef hadc;
// 从机地址(对应点表中的02H)
#define SLAVE_ADDR 2
// DO寄存器(线圈状态)数量:5个(2个蜂鸣器+3个LED)
#define NB_BITS 5
// DI寄存器(离散输入状态)数量:0(本传感器未使用)
#define NB_INPUT_BITS 0
// 保持寄存器数量:0(本传感器未使用)
#define NB_REGISTERS 0
// AI寄存器(输入寄存器)数量:2个(光敏电阻+可调电阻)
#define NB_INPUT_REGISTERS 2
#endif
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
// 存储GPIO读取状态(本传感器未使用,保留兼容)
GPIO_PinState val;
// Modbus请求报文缓冲区
uint8_t *query;
// Modbus RTU上下文
modbus_t *ctx;
// 函数返回值,判断操作是否成功
int rc;
// Modbus寄存器映射结构体
modbus_mapping_t *mb_mapping;
#ifdef USE_ENV_MONITOR_SENSOR
// ADC校准:保障12位电压采集精度(环境监测传感器核心步骤)
HAL_ADCEx_Calibration_Start(&hadc);
#endif
// 创建串口1的Modbus RTU上下文:波特率115200、无校验、8数据位、1停止位
ctx = modbus_new_st_rtu("uart1", 115200, 'N', 8, 1);
// 设置从机地址(匹配点表中的02H)
modbus_set_slave(ctx, SLAVE_ADDR);
// 分配请求报文缓冲区(FreeRTOS内存接口)
query = pvPortMalloc(MODBUS_RTU_MAX_ADU_LENGTH);
// 初始化寄存器映射:基于宏定义的寄存器数量配置
mb_mapping = modbus_mapping_new_start_address(0,
NB_BITS, // DO寄存器数量
0,
NB_INPUT_BITS, // DI寄存器数量
0,
NB_REGISTERS, // 保持寄存器数量
0,
NB_INPUT_REGISTERS); // AI寄存器数量
// 建立Modbus RTU连接
rc = modbus_connect(ctx);
if (rc == -1) {
//fprintf(stderr, "Unable to connect %s\n", modbus_strerror(errno));
modbus_free(ctx);
vTaskDelete(NULL);; // 连接失败则删除任务
}
// 无限循环接收并响应PC端Modbus请求
for (;;) {
do {
// 接收PC端请求报文,过滤无效请求(返回0的查询)
rc = modbus_receive(ctx, query);
/* Filtered queries return 0 */
} while (rc == 0);
/* The connection is not closed on errors which require on reply such as
bad CRC in RTU. */
// 非CRC错误则继续循环,不退出
if (rc == -1 && errno != EMBBADCRC) {
/* Quit */
continue;
}
/* update values of registers
* a. read gpio
* b. update reg
*/
// 开关量传感器逻辑(保留兼容,本传感器未启用)
#ifdef USE_SWITCH_SENSOR
/* key1 */
val = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3);
if (val == GPIO_PIN_RESET)
{
mb_mapping->tab_input_bits[0] = 1;
}
else
{
mb_mapping->tab_input_bits[0] = 0;
}
/* key2 */
val = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4);
if (val == GPIO_PIN_RESET)
{
mb_mapping->tab_input_bits[1] = 1;
}
else
{
mb_mapping->tab_input_bits[1] = 0;
}
/* key3 */
val = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5);
if (val == GPIO_PIN_RESET)
{
mb_mapping->tab_input_bits[2] = 1;
}
else
{
mb_mapping->tab_input_bits[2] = 0;
}
#endif
// 环境监测传感器:读取ADC值更新AI寄存器
#ifdef USE_ENV_MONITOR_SENSOR
/* READ ADC to update tab_input_registers */
// 循环采集2路ADC(光敏电阻、可调电阻),更新AI寄存器
for (int i = 0; i < 2; i++)
{
// 启动ADC采集
HAL_ADC_Start(&hadc);
// 等待采集完成(超时100ms)
if (HAL_OK == HAL_ADC_PollForConversion(&hadc, 100))
{
// 将ADC采集值写入AI寄存器
mb_mapping->tab_input_registers[i] = HAL_ADC_GetValue(&hadc);
}
}
#endif
// 解析请求并回复PC端(包含更新后的AI寄存器数据)
rc = modbus_reply(ctx, query, rc, mb_mapping);
if (rc == -1) {
//break;
}
// 开关量传感器DO控制逻辑(保留兼容,本传感器未启用)
#ifdef USE_SWITCH_SENSOR
/* switch1 */
if (mb_mapping->tab_bits[0])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); //switch1
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); //switch1
/* switch2 */
if (mb_mapping->tab_bits[1])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET); //switch2
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); //switch2
if (mb_mapping->tab_bits[2])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET); //LED1
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET); //LED1
if (mb_mapping->tab_bits[3])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET); //LED2
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET); //LED2
if (mb_mapping->tab_bits[4])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET); //LED3
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET); //LED3
#endif
// 环境监测传感器:根据DO寄存器值控制外设
#ifdef USE_ENV_MONITOR_SENSOR
/* beep1 */
// DO寄存器0号控制蜂鸣器1(PB15):1-响(高电平)、0-停(低电平)
if (mb_mapping->tab_bits[0])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_SET); //beep1
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET); //beep1
/* beep2 */
// DO寄存器1号控制蜂鸣器2(PB14):1-响(高电平)、0-停(低电平)
if (mb_mapping->tab_bits[1])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET); //beep2
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET); //beep2
// DO寄存器2号控制LED1(PB11):1-亮(低电平)、0-灭(高电平)
if (mb_mapping->tab_bits[2])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET); //LED1
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET); //LED1
// DO寄存器3号控制LED2(PB12):1-亮(低电平)、0-灭(高电平)
if (mb_mapping->tab_bits[3])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET); //LED2
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET); //LED2
// DO寄存器4号控制LED3(PB13):1-亮(低电平)、0-灭(高电平)
if (mb_mapping->tab_bits[4])
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET); //LED3
else
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET); //LED3
#endif
}
// 释放资源(实际循环不会执行到此处)
modbus_mapping_free(mb_mapping);
vPortFree(query);
modbus_close(ctx);
modbus_free(ctx);
vTaskDelete(NULL);
/* USER CODE END StartDefaultTask */
}
五、功能验证:Modbus Poll 测试
将编译后的程序烧录至 STM32F030 开发板,保持 STM32H5 转接板的 RS485-USB 透传功能开启,通过 PC 端 Modbus Poll 软件按照点表规则测试:
1. DO 寄存器控制硬件
改写 DO 寄存器值可精准控制蜂鸣器、LED 的启停 / 亮灭,例如向寄存器地址 3 发送 On 指令,LED2 成功点亮,测试效果如下:

2. AI 寄存器采集电压
读取 AI 寄存器可获取光敏电阻、可调电阻的 ADC 电压值,下图显示的采集结果表明此时环境光强较弱:

六、总结
- 环境监测传感器需配置 ADC 离散转换模式,并在程序中完成 ADC 校准,保障 12 位电压采集精度;
- 程序通过宏定义区分传感器类型,兼顾兼容性的同时实现 DO 外设控制与 AI 电压采集;
- 点表明确了设备地址、寄存器映射规则,是 PC 与传感器稳定通信的核心依据。
七、结尾
本次完成了 STM32F030 环境监测传感器的全流程程序设计,实现了模拟量(ADC 电压)采集与数字量(DO 外设)控制的 Modbus 通信闭环,这套设计思路可直接适配各类包含模拟采集、数字控制的工业传感器开发。掌握环境监测传感器的开发逻辑,是进阶实现温湿度、气体浓度等复杂环境传感器的关键基础。感谢各位的阅读,持续关注本系列笔记,一起探索更多工业级 Modbus 传感器的开发与优化技巧!加粗样式
更多推荐



所有评论(0)