3.27_433:添加UART2调试打印、IO监控、指令解析和继电器控制模块。
能够接收UART2指令控制继电器开关,或向UART2发送四路IO输入状态,并使用轮询方式检测IO状态进行及时反馈。
This commit is contained in:
158
Core/Src/io_monitor.c
Normal file
158
Core/Src/io_monitor.c
Normal file
@ -0,0 +1,158 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @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;
|
||||
}
|
||||
Reference in New Issue
Block a user