本文是一篇实战教程,旨在引导你通过自定义 MCP(Model Context Protocol)工具,结合语音指令控制硬件设备。我们将以 CSK6 大模型开发套件 为例,展示如何通过语音触发串口通信,最终在 GPIO 接口输出串口信息。
无论你是物联网开发者、嵌入式爱好者,还是希望将语音交互能力接入硬件项目的创客,本教程都将带你一步步实现一个完整的 “语音—串口—GPIO” 软硬件联动示例。
你将学习到如何配置 MCP 工具、编写串口控制逻辑,并实现语音到硬件的无缝控制。
实操之前,请确保已根据文档《环境搭建》 和《获取大模型套件SDK》搭建开发环境。
如果您不想重新编译代码而希望直接体验本固件,可点击下载进行烧录:
mcp_uart_control_3.1.3.bin
在 duomotai_ap 项目下修改文件 duomotai_ap\apps\LLM_pic\prj.conf,添加语句 CONFIG_UART_COMM_EN=y

此时,初始化 Uart 外设已经完成了,您可以直接跳过这一章节,直接看 【二、端侧注册 MCP 工具】 的内容
如果您对配置了这个语句之后,具体发生了什么,或者想知道初始化一个外设需要什么步骤感兴趣的话,那么请继续往下看。
修改文件 duomotai_ap\LLM_pic\boards\csk6_duomotai_devkit.overlay
我们的目标是需要把 PA00 PA01 使用 Uart 外设,修改如下。

可查询 《CSK6系芯片引脚功能表》 哪些引脚可以使用哪些外设
找到文件夹 duomotai_ap\apps\LLM_pic\src\uart_comm,能够发现

找到文件 duomotai_ap\apps\LLM_pic\src\main.c,能够发现

函数 uart_comm_demo_init() 被调用后,会创建线程,定期发送心跳消息,或者接收到的消息原样发送回去

如果需要用其他外设,比如
I2C、SPI,初始化的的步骤是相似的
执行以下指令进行代码编译(以 Windows CMD 终端为例):
lisa zep build -b csk6_duomotai_devkit .\apps\LLM_pic\ -p
使用 Type-C 数据线连接开发套件的 DAP_USB接口,选中以下其中一种方式对固件进行烧录:
cskburn desktop是一款聆思推出的桌面烧录工具,在下载并安装 cskburn desktop 烧录工具后,双击
图标运行软件:
1.点击串口下拉框,选择连接开发套件后识别到的串口编号;
2.将编译输出的.bin文件拖拽进烧录区域;
3.点击开始烧录,等待烧录完成。

若您已按照 《环境搭建》 教程完成开发环境的安装,可在编译完成后执行 lisa zep exec cskburn 指令完成烧录。
lisa zep exec cskburn -s \\.\COMxx -C 6 -b 1500000 0x000000 --verify-all .\build\zephyr\zephyr.bin
请将命令行中的的 COMx 替换为开发套件在 PC 上对应的串口号(可通过设备管理器查看)。例如:
COM3。
lisa zep exec cskburn -s PORT -C 6 0x000000 --verify-all ./build/zephyr/zephyr.bin -b 1500000
请将命令行中的 PORT 替换为开发套件连接在 PC 上对应的串口号。例如:
/dev/ttyUSB0。

1.烧录完成后,移除 USB 线 DAPLink USB 接口的连接,使用CSK_USB 接口进行供电;
2.串口板 RX 连接 A00(UART1_TX), 串口板 TX 连接 A01(UART1_RX)
3.打开串口工具,进行语音交互,可观察到串口同步输出云端返回的文本内容。
注意:移除 USB 线 DAPLink USB 接口的连接,使用
CSK_USB接口进行供电是必须的,否则将接收不到A00的串口信息

至此,Uart 外设已经成功初始化,接下来将讲解如何通过 MCP 工具调用该接口
在 duomotai_ap/apps/LLM_pic/app_mcp/tools 文件夹下添加文件 uart_control.c

修改 aduomotai_ap/apps/LLM_pic/app_mcp/CMakeLists.txt 添加语句${CMAKE_CURRENT_SOURCE_DIR}/tools/uart_control.c

duomotai_ap/apps/LLM_pic/app_mcp/tools/uart_control.c 文件下添加代码:#include "app_mcp.h"
#include <string.h>
#include <stdio.h>
#include "cJSON.h"
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(uart_control, LOG_LEVEL_INF);
// 扩展GPIO控制处理函数
static mcp_result_t uart_switch_handler(const mcp_context_t *ctx, mcp_response_t *response)
{
LOG_ERR("TANHAOWEI");
if (!ctx || !response) {
return MCP_RESULT_INVALID_PARAM;
}
const char *value_str = NULL;
int new_state = -1; // 1: Hello, 0: World
// 解析参数
for (uint32_t i = 0; i < ctx->param_count; i++) {
if (strcmp(ctx->params[i].name, "value") == 0) {
if (cJSON_IsString(ctx->params[i].value)) {
value_str = ctx->params[i].value->valuestring;
}
}
}
if (!value_str) {
response->error_msg = "错误:缺少必需的 value 参数";
response->result = MCP_RESULT_INVALID_PARAM;
return MCP_RESULT_INVALID_PARAM;
}
if (strcmp(value_str, "Hello") == 0) {
new_state = 1;
} else if (strcmp(value_str, "World") == 0) {
new_state = 0;
} else {
response->error_msg = "错误:value 只能是 'Hello' 或者 'World'";
response->result = MCP_RESULT_INVALID_PARAM;
return MCP_RESULT_INVALID_PARAM;
}
// 调用扩展GPIO接口的API
extern void uart_comm_send_string(const char *str);
if (new_state) {
uart_comm_send_string("Hello");
} else {
uart_comm_send_string("World");
}
LOG_INF("uart send %s",
new_state ? "Hello" : "World");
char result_msg[256];
snprintf(result_msg, sizeof(result_msg),
"uart 已发送%s", new_state ? "Hello" : "World");
response->content = cJSON_CreateString(result_msg);
response->result = MCP_RESULT_SUCCESS;
return MCP_RESULT_SUCCESS;
}
/**
* @brief 生成 uart 工具的参数 Schema
*
* @return cJSON对象指针,失败返回NULL
*/
cJSON* generate_uart_switch_schema(void)
{
cJSON *root = cJSON_CreateObject();
if (!root) {
LOG_ERR("Failed to create root object for uart_switch schema");
return NULL;
}
if (!cJSON_AddStringToObject(root, "type", "object")) {
LOG_ERR("Failed to add type to led_switch schema");
cJSON_Delete(root);
return NULL;
}
cJSON *properties = cJSON_CreateObject();
if (!properties) {
LOG_ERR("Failed to create properties object");
cJSON_Delete(root);
return NULL;
}
// value 参数
cJSON *value_prop = cJSON_CreateObject();
if (!value_prop) {
LOG_ERR("Failed to create value property");
cJSON_Delete(properties);
cJSON_Delete(root);
return NULL;
}
if (!cJSON_AddStringToObject(value_prop, "type", "string") ||
!cJSON_AddStringToObject(value_prop, "description", "只可传字符串 'Hello'或'World'")) {
LOG_ERR("Failed to add value property fields");
cJSON_Delete(value_prop);
cJSON_Delete(properties);
cJSON_Delete(root);
return NULL;
}
cJSON_AddItemToObject(properties, "value", value_prop);
cJSON_AddItemToObject(root, "properties", properties);
// required 数组
cJSON *required = cJSON_CreateArray();
if (!required) {
LOG_ERR("Failed to create required array");
cJSON_Delete(root);
return NULL;
}
cJSON *value_str = cJSON_CreateString("value");
if (!value_str) {
LOG_ERR("Failed to create value string for required array");
cJSON_Delete(required);
cJSON_Delete(root);
return NULL;
}
cJSON_AddItemToArray(required, value_str);
cJSON_AddItemToObject(root, "required", required);
return root;
}
// 注册扩展GPIO控制工具
MCP_REGISTER_TOOL_STATIC(uart_switch,
"uart_switch",
"控制串口输出内容,只能是'Hello'或'World'",
"1.0",
generate_uart_switch_schema,
1,
uart_switch_handler,
false,
NULL);
执行以下指令进行代码编译(以 Windows CMD 终端为例):
lisa zep build -b csk6_duomotai_devkit samples\llm_pic_extent\LLM_pic_uart -p
使用 Type-C 数据线连接开发套件的 DAP_USB接口,选中以下其中一种方式对固件进行烧录:
cskburn desktop是一款聆思推出的桌面烧录工具,在下载并安装 cskburn desktop 烧录工具后,双击
图标运行软件:
1.点击串口下拉框,选择连接开发套件后识别到的串口编号;
2.将编译输出的.bin文件拖拽进烧录区域;
3.点击开始烧录,等待烧录完成。

若您已按照 《环境搭建》 教程完成开发环境的安装,可在编译完成后执行 lisa zep exec cskburn 指令完成烧录。
lisa zep exec cskburn -s \\.\COMxx -C 6 -b 1500000 0x000000 --verify-all .\build\zephyr\zephyr.bin
请将命令行中的的 COMx 替换为开发套件在 PC 上对应的串口号(可通过设备管理器查看)。例如:
COM3。
lisa zep exec cskburn -s PORT -C 6 0x000000 --verify-all ./build/zephyr/zephyr.bin -b 1500000
请将命令行中的 PORT 替换为开发套件连接在 PC 上对应的串口号。例如:
/dev/ttyUSB0。

1.烧录完成后,移除 USB 线 DAPLink USB 接口的连接,使用CSK_USB 接口进行供电;
2.串口板 RX 连接 A00(UART1_TX), 串口板 TX 连接 A01(UART1_RX)
3.打开串口工具,进行语音交互,可观察到串口同步输出云端返回的文本内容。
注意:移除 USB 线 DAPLink USB 接口的连接,使用
CSK_USB接口进行供电是必须的,否则将接收不到A00的串口信息


至此, MCP 工具已经可以调用 Uart 外设,接下来将讲解如何在接入自定义编排应用情况下,通过 MCP 工具调用调用扩展 GPIO 接口
如果 Arcs-mini 开发板接入的大模型是出厂默认的 小聆AI ,进行端侧注册即可使用 MCP 工具,本章节可以忽略。


MCP 工具示例.json文件导入

若提示“您要导入的某些节点已经存在于工作空间中。”,则选择“导入副本”即可。

完成云端配置后,需将产品ID(product ID)与密钥(secret ID)写入设备,才能让设备连接对应的产品并完成鉴权服务。
若您当前设备上运行的固件不具备扫码接入功能,请参照 《应用合集TF卡》更新 TF 卡中的镜像文件夹。
配置方式:



注:屏幕亮度和反光会影响扫码识别,可以把二维码的网页放大200%以上再扫码。
出厂时的摄像头膜需要取下
设备 ID 是一个产品下的唯一设备标识,我们需要获取当前设备 ID 方便后续在云端配置,才能让设备鉴权通过实现端云交互。
读取方式:
cskburn desktop 是一款聆思推出的桌面烧录工具,下载地址(cskburn 桌面烧录工具 | 聆思文档中心)打开软件后

聆思平台只会对列表中的设备鉴权提供交互服务,因此需要将前面读取到的设备 ID 在设备管理页面进行导入才能实现设备正常交互。


云端配置设备 id 后,还需将产品 ID 写入开发板固件中,才能让设备在运行时找到正确的云端产品服务完进行鉴权,鉴权完成就可以进行大模型语音交互了。
写入方式:
使用数据线连接开发板 DAP_USB 接口后,打开聆思在线串口终端,选择对应的串口设备进行连接,波特率默认 115200,完成配置后点击连接按钮。

通过 set product_id 和 set secret_id 指令可以分别配置开发板接入的大模型应用 product ID 及其密钥,示例如下:
set product_id 71cd1721-xxx-xxx-xxx-1000055c8b2f
set secret_id cb09013f-xxx-xxx-xxx-e212b32f9218
其中,product_id 和 product_secret 可在对应产品的产品信息中获取,请将指令中的参数替换为产品信息中的 id 与 secret 信息。


最后,重启开发板即可。
旧版固件请使用 aiui set product_id 与 aiui set secret_id 指令。


下载后直接覆盖 SDK 的 apps/LLM_pic 文件夹
下载后,可以通过命令
git apply .\mcp_uart_control_3.1.3.diff应用更改