概述
官方基础工程已预置继电器驱动(components/relay)并在任务中完成初始化;relay 工具已在创建 MCP 工具第 5 章注册。本章接线(PB5)→ 确认工具 → 实现 AI 语音控制继电器开/关。
示例工程已预置继电器驱动(components/relay,STM32 HAL 直调版),无需复制或修改。驱动接口如下(对照理解):
/* components/relay/relay.c —— HAL 直调版 */
#include "relay.h"
#include "gpio.h"
#include "log.h"
#include "stm32f1xx_hal_gpio.h"
static unsigned char axk_relay_state = 0;
/* 上电时把继电器置为断开(PB5 输出低) */
void axk_relay_init(void) {
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5) != GPIO_PIN_RESET) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
return;
}
}
/* 设置继电器:state=ON(1) 吸合,state=OFF(0) 释放 */
void axk_relay_set(unsigned char state) {
axk_relay_state = state;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, state);
}
void axk_relay_toggle(void) {
axk_relay_state = !axk_relay_state;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, axk_relay_state);
}
unsigned char axk_relay_get(void) { return axk_relay_state; }
头文件 relay.h 接口:
#ifndef __RELAY_H__
#define __RELAY_H__
#define ON 1 // 吸合
#define OFF 0 // 释放
void axk_relay_init(void);
void axk_relay_set(unsigned char state);
unsigned char axk_relay_get(void);
void axk_relay_toggle(void);
#endif
示例工程的 components/CMakeLists.txt 已包含 relay 目录(源文件与头文件路径),无需修改。
🧩 九章板继电器已板载接好(PB5 控制),无需接线。下表供对照认识引脚,或扩展外部继电器模块时参考。
| 继电器模块 | 接开发板 | 说明 |
|---|---|---|
| IN / SIG(信号输入) | PB5 | 高电平吸合、低电平释放 |
| VCC | 5V | 继电器线圈供电 |
| GND | GND | 共地 |
| COM / NO(触点) | 被控负载回路 | 如灯泡:火线串入 COM–NO |
⚠️ 安全提醒:继电器触点常用于控制 220V 交流电器,接线务必断电操作,裸露线头做好绝缘。新手建议先用 LED + 电阻 或 蜂鸣器 当负载测试,确认逻辑正确后再接强电。
relay 工具的回调与注册已在创建 MCP 工具第 5 章完成(relay_set_handler 控制继电器、relay_check_handler 查询状态)。工具回调中的核心动作就是调用驱动:
/* 工具回调里调用驱动 */
if (strcmp(s, "on") == 0) { relay_on = true; axk_relay_set(ON); log_info("Relay -> ON"); }
else if (strcmp(s, "off") == 0) { relay_on = false; axk_relay_set(OFF); log_info("Relay -> OFF"); }
/* 任务初始化时调用一次 */
axk_relay_init();
别忘了在 freertos.c 顶部
#include "relay.h",并定义全局状态static bool relay_on = false;。
-
编译烧录(见 例程运行验证),板子上电。
-
手动验证(俗称"冒烟测试"——不依赖 AI,先用串口直接发指令,确认硬件和工具逻辑正常):串口助手连 USART2(115200)发送:
{"role":"AI","msgType":"MCP","data":{"name":"relay","args":{"state":"on"}}}继电器应吸合;将
"on"改为"off",继电器释放。 -
AI 语音控制:确认 AI 模组已配网后,对模组说:
- “你好小安”(唤醒,日志出现 WakeUP)
- “打开继电器” → 继电器吸合
- “关闭继电器” → 继电器释放
- “继电器现在是什么状态?” → AI 调用 check 回调并回复

AI 不执行指令?① 模组未联网 → 重新配网;② 工具未注册成功 → 看日志是否有
mcp-tool sent;③ 描述不匹配 → 工具的 description 写清楚(“打开/关闭继电器”),AI 依靠 description 理解工具;④ 手动 JSON 能控制但语音不行 → 确认模组固件为 UART-MCP 版本。
常见问题与踩坑提示
🔧 继电器不动作(无吸合声)
原因:① 模块供电不足 ② 触发极性不对 ③ 未共地
解决:① 模块 VCC 必须接 5V(接 3.3V 时线圈吸合力不足)② 部分模块为低电平触发,可将接线接至常闭端,或修改 axk_relay_set 逻辑 ③ GND 必须与板子共地
🔧 上电时继电器乱跳一下
原因:芯片复位瞬间引脚电平不定
解决:正常现象;如需消除可在模块 IN 加下拉电阻,或接受它(本项目 axk_relay_init 上电即拉低)
🔧 手动 JSON 能控制,AI 语音不行
原因:工具描述不清晰或模组未唤醒
解决:说"你好小安"先唤醒;把 description 写成"打开/关闭继电器"这类大白话
🔧 继电器吸合但负载不工作
原因:触点接线错
解决:COM 和 NO 是常开端(吸合才通);要常通就接 COM/NC;确认负载回路有电
🔧 继电器动作了,但 AI 播报"打开失败";且指令要过一会才执行原因:⚠️ USART2 中断未使能(.ioc 没勾 USART2 global interrupt) 解决:在 STM32 工程创建 勾选 USART2 global interrupt 并重新生成,这是本项目最容易踩的坑
🔧 继电器能开、AI 也播报正常,但温湿度/灯带等长消息工具总失败原因:接收消息字节丢失 解决:串口日志乱码/丢字节时见温湿度案例的日志互斥锁说明
🔧 控制 220V 电器时模块发热/异味
原因:电流超过继电器触点额定
解决:SRD-05VDC 触点额定约 10A;大功率负载换更大继电器,接线务必断电操作
🔧 测试时 LED 直接烧了
原因:LED 没串限流电阻
解决:LED 必须串电阻(220Ω~1kΩ),或直接用蜂鸣器模块/万用表蜂鸣档
🔧 PB5 电平一直高
原因:CubeMX 里 PB5 没配置或初始状态不对
解决:确认 .ioc 里 PB5 为 GPIO_Output(本项目初始为低电平,断开状态)
高压负载测试顺序
先空载测试(确认继电器吸合/释放动作正常)→ 再接 LED+电阻 或蜂鸣器 → 确认逻辑无误后,最后才接强电负载,且全程断电接线。

