Files
433_STM32/Core/Src/io_monitor.c
zhongxuanzhen 71027ebc46 3.27_433:添加UART2调试打印、IO监控、指令解析和继电器控制模块。
能够接收UART2指令控制继电器开关,或向UART2发送四路IO输入状态,并使用轮询方式检测IO状态进行及时反馈。
2026-03-27 10:09:13 +08:00

159 lines
4.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @file io_monitor.c
* @brief IO状态监控模块实现
* @author Application Layer
* @version 1.1
******************************************************************************
* @attention
* 本模块实现四路数字输入的状态监控
* 关键特性:
* 1. 10ms定时扫描平衡响应速度和CPU占用
* 2. 软件去抖连续3次相同状态才确认变化
* 3. 状态变化时自动上报ASCII格式消息
*
* 修订历史:
* v1.1 - 修复审查报告中危-5去抖计数器初始化优化
******************************************************************************
*/
#include "io_monitor.h"
#include "uart2_print.h"
#include "main.h"
#include <string.h>
#define DEBUG_IO_MONITOR 1
#if DEBUG_IO_MONITOR
#define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[IO] " fmt "\r\n", ##__VA_ARGS__)
#else
#define DEBUG_LOG(fmt, ...)
#endif
typedef struct {
GPIO_TypeDef *port;
uint16_t pin;
uint8_t current_state;
uint8_t debounce_counter;
uint8_t last_raw_state;
uint32_t change_count;
} io_channel_t;
static io_channel_t di_channels[IO_CHANNEL_COUNT] = {
{GPIOB, GPIO_PIN_4, 0, 0, 0, 0},
{GPIOB, GPIO_PIN_5, 0, 0, 0, 0},
{GPIOB, GPIO_PIN_6, 0, 0, 0, 0},
{GPIOB, GPIO_PIN_7, 0, 0, 0, 0}
};
static uint32_t last_scan_tick = 0;
static bool report_enabled = true;
static uint8_t calc_checksum(const char *data, uint8_t len)
{
uint8_t cs = 0;
for (uint8_t i = 0; i < len; i++) {
cs ^= (uint8_t)data[i];
}
return cs;
}
static void send_di_event(uint8_t channel, uint8_t state)
{
char msg[32];
uint8_t cs;
int len = snprintf(msg, sizeof(msg), "$DI_EVENT,%d,%d*", channel + 1, state);
cs = calc_checksum(msg + 1, len - 1);
snprintf(msg + len, sizeof(msg) - len, "%02X\r\n", cs);
UART2_Print_String(msg);
DEBUG_LOG("CH%d -> %s", channel + 1, state ? "HIGH" : "LOW");
}
void IO_Monitor_Init(void)
{
for (int i = 0; i < IO_CHANNEL_COUNT; i++) {
io_channel_t *ch = &di_channels[i];
ch->current_state = HAL_GPIO_ReadPin(ch->port, ch->pin) ? 1 : 0;
ch->last_raw_state = ch->current_state;
ch->debounce_counter = 1;
ch->change_count = 0;
}
last_scan_tick = 0;
report_enabled = true;
DEBUG_LOG("Init OK, initial states: 0x%02X", IO_Monitor_GetAllStates());
}
void IO_Monitor_Task(void)
{
uint32_t current_tick = HAL_GetTick();
if (current_tick - last_scan_tick < IO_SCAN_PERIOD_MS) {
return;
}
last_scan_tick = current_tick;
for (int i = 0; i < IO_CHANNEL_COUNT; i++) {
io_channel_t *ch = &di_channels[i];
uint8_t raw_state = HAL_GPIO_ReadPin(ch->port, ch->pin) ? 1 : 0;
if (raw_state != ch->last_raw_state) {
ch->debounce_counter = 0;
ch->last_raw_state = raw_state;
} else {
if (ch->debounce_counter < IO_DEBOUNCE_COUNT) {
ch->debounce_counter++;
} else if (ch->current_state != raw_state) {
ch->current_state = raw_state;
ch->change_count++;
if (report_enabled) {
send_di_event(i, raw_state);
}
}
}
}
}
uint8_t IO_Monitor_GetState(uint8_t channel)
{
if (channel >= IO_CHANNEL_COUNT) {
return 0;
}
return di_channels[channel].current_state;
}
uint8_t IO_Monitor_GetAllStates(void)
{
uint8_t states = 0;
for (int i = 0; i < IO_CHANNEL_COUNT; i++) {
if (di_channels[i].current_state) {
states |= (1 << i);
}
}
return states;
}
void IO_Monitor_EnableReport(bool enable)
{
report_enabled = enable;
DEBUG_LOG("Report %s", enable ? "enabled" : "disabled");
}
uint32_t IO_Monitor_GetChangeCount(uint8_t channel)
{
if (channel >= IO_CHANNEL_COUNT) {
return 0;
}
return di_channels[channel].change_count;
}