这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 电子DIY+FRDM-MCXA346使用shell控制RGB

共1条 1/1 1 跳转至

电子DIY+FRDM-MCXA346使用shell控制RGB

高工
2026-03-18 07:28:59     打赏
一、硬件介绍:FRDM-MCXA346 是 NXP 推出的一款紧凑型、可扩展的开发板,基于 MCX A346 微控制器,专为工业物联网 (IoT) 和消费电子应用的快速原型设计而优化,特别擅长电机控制和混合信号处理。


使用FRDM-MCXA346实现串口Shell

FRDM-MCXA346是恩智浦(NXP)推出的一款基于ARM Cortex-M4内核的开发板,下面我将介绍如何在其上实现一个简单的串口Shell功能。
FRDM-MCXA346开发板

终端软件(Tera Term、Putty等)


设计思路:

6d021544-ced1-4b8b-8cdd-a3a49b152284.png

系统上电后,初始化串口和LED的gpio口。然后监听串口,在串口上获得消息后,就构建命令字,遇到回车构建完成。然后解析命令字,如果解析成功就按命令字执行相应操作。

任务实现:

开发工具使用官方提供的MCUXpressoIDE。使用“hello world”例程做为项目的模版进行修改。

2e7391bb-7967-4f4b-baec-120c6db13e8a.png


因为项目中要使用到串口和板载的LED灯,所以先检查管脚配置,确保对应功能的硬件已经被设置好。

首先完成基础任务,通过UART串口输出“Hello, DigiKey Funpack 5-1”。这里初始化板子后,将三个板载的LED灯设置为输出,并设置为关闭状态。然后再通过串口输出指定字符串。

f89f7a03-0c13-40de-844d-0a710152f85e.png


/* Init board hardware. */
	BOARD_InitHardware();
	/* Init output LED GPIO. */
	GPIO_PinInit(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, &led_config);
	GPIO_PinInit(BOARD_LED_GREEN_GPIO, BOARD_LED_GREEN_GPIO_PIN, &led_config);
	GPIO_PinInit(BOARD_LED_BLUE_GPIO, BOARD_LED_BLUE_GPIO_PIN, &led_config);
	PRINTF("Hello, DigiKey Funpack 5-1\r\nfunpack>$");
扩展后的代码,在原有基础上增加了 循环接收串口消息 的功能,直到收到 回车(\r 或 \n) 或 缓冲区溢出/串口异常 时停止接收,并打印接收到的数据。
while (1) {
		receivedChar = GETCHAR();
		PUTCHAR(receivedChar);
		/* 处理接收到的字符 */
		if (receivedChar == '\r' || receivedChar == '\n') {
			/* 如果是回车或换行符,说明命令输入完成 */
			PRINTF("\r\n");
			/* 解析命令 */
			parseCommand(cmdBuffer, &parsedCmd);
			/* 处理命令 */
			processCommand(&parsedCmd);
			/* 重置命令缓冲区和索引 */
			memset(cmdBuffer, 0, CMD_BUFFER_SIZE);
			cmdIndex = 0;
			/* 重新显示命令提示符 */
			PRINTF("funpack>$ ");
		} else if (receivedChar == '\b' || receivedChar == 127) {
			/* 如果是退格键,删除最后一个字符 */
			if (cmdIndex > 0) {
				cmdIndex--;
				cmdBuffer[cmdIndex] = '\0';
				/* 重新打印命令行,覆盖旧内容 */
				PRINTF("\rfunpack>$ %s", cmdBuffer);
				/* 用空格清除剩余的旧字符 */
				for (int i = cmdIndex; i < CMD_BUFFER_SIZE - 1; i++) {
					PRINTF(" ");
				}
				/* 回到正确的光标位置 */
				PRINTF("\rfunpack>$ %s", cmdBuffer);
			}
		} else {
			/* 普通字符,添加到命令缓冲区 */
			if (cmdIndex < CMD_BUFFER_SIZE - 1) {
				cmdBuffer[cmdIndex++] = (char) receivedChar;
			}
		}
	}

在接收完串口数据后,我们可以对缓冲区中的字符串进行解析,构建出可识别的命令字,以便后续执行相应的操作。


/* 命令解析结构体 */
typedef struct {
	char cmd[32]; /* 命令名称 */
	char params[MAX_PARAMS][16]; /* 参数数组 */
	int paramCount; /* 参数数量 */
} parsed_cmd_t;


/**
 * @brief 解析命令字符串
 * @param buffer 输入的命令字符串
 * @param cmd 解析后的命令结构体
 */
void parseCommand(char *buffer, parsed_cmd_t *cmd) {
	/* 重置解析结果 */
	memset(cmd, 0, sizeof(parsed_cmd_t));
	cmd->paramCount = 0;
	/* 跳过前导空格 */
	while (*buffer == ' ') {
		buffer++;
	}
	/* 解析命令名称 */
	char *token = strtok(buffer, " ");
	if (token != NULL) {
		/* 复制命令名称 */
		strncpy(cmd->cmd, token, sizeof(cmd->cmd) - 1);
		cmd->cmd[sizeof(cmd->cmd) - 1] = '\0';
		/* 解析参数 */
		token = strtok(NULL, " ");
		while (token != NULL && cmd->paramCount < MAX_PARAMS) {
			/* 复制参数 */
			strncpy(cmd->params[cmd->paramCount], token,sizeof(cmd->params[0]) - 1);
			cmd->params[cmd->paramCount][sizeof(cmd->params[0]) - 1] = '\0';
			cmd->paramCount++;
			/* 获取下一个参数 */
			token = strtok(NULL, " ");
		}
	}
}

代码实现了一个 串口命令解析器,用于将接收到的字符串拆分成 命令字 和 参数列表,并存储在结构体 parsed_cmd_t 中。

void parseCommand(char *buffer, parsed_cmd_t *cmd) {
    // 1. 重置解析结果
    memset(cmd, 0, sizeof(parsed_cmd_t));
    cmd->paramCount = 0;

    // 2. 跳过前导空格
    while (*buffer == ' ') {
        buffer++;
    }

    // 3. 解析命令名称(第一个空格前的部分)
    char *token = strtok(buffer, " ");
    if (token != NULL) {
        strncpy(cmd->cmd, token, sizeof(cmd->cmd) - 1);
        cmd->cmd[sizeof(cmd->cmd) - 1] = '\0'; // 确保字符串终止

        // 4. 解析后续参数(以空格分隔)
        token = strtok(NULL, " ");
        while (token != NULL && cmd->paramCount < MAX_PARAMS) {
            strncpy(cmd->params[cmd->paramCount], token, sizeof(cmd->params[0]) - 1);
            cmd->params[cmd->paramCount][sizeof(cmd->params[0]) - 1] = '\0';
            cmd->paramCount++;
            token = strtok(NULL, " ");
        }
    }
}


在完成命令解析后,系统需根据解析出的命令字执行对应的操作。当前设计支持三个核心命令:help、echo 和 led,分别用于提供帮助信息、回显输入内容以及控制LED灯的状态。以下是各命令的详细说明与执行逻辑:


help 命令

该命令用于显示所有支持的命令字及其功能说明,帮助用户快速掌握系统操作。执行时,系统会遍历预设的命令列表,将每个命令的名称、参数格式及用途以清晰易读的格式输出。例如,输出可能包含:help:显示帮助信息echo <内容>:回显输入内容led <颜色> <状态>:控制LED灯(颜色支持红/绿/蓝,状态支持开/关)此功能对新手用户尤为重要,可避免因不熟悉命令格式导致的操作错误,提升交互效率。


echo 命令

该命令用于测试通信或调试,功能简单直接:将用户输入的内容原样返回。例如,若用户输入 echo Hello,系统会响应 Hello。此命令不涉及复杂逻辑,但需注意边界条件,如输入过长时的截断处理或特殊字符的转义。在嵌入式场景中,echo 常用于验证串口通信是否正常,或作为其他命令的占位符进行功能测试。


led 命令

该命令是核心功能之一,允许用户动态控制LED灯的颜色与亮灭状态。其参数分为两部分:颜色:支持 red、green、blue 三种基础颜色,未来可扩展为RGB数值(如 255,0,0 表示红色)。状态:支持 on(点亮)和 off(熄灭)。执行时,系统需调用底层硬件驱动函数,将参数转换为具体的控制信号。例如,输入 led red on 会点亮红色LED,而 led blue off 会熄灭蓝色LED。若硬件支持多色混合,还可通过组合参数实现更复杂的效果(如 led yellow on 通过红绿混合实现黄色)。执行流程设计系统在解析完命令后,通过 switch-case 或函数指针表匹配命令字,调用对应的处理函数。例如:若命令字为 help,调用 ShowHelp() 输出帮助信息;若为 echo,调用 EchoInput() 返回用户输入;若为 led,调用 ControlLED() 解析颜色与状态参数,并更新硬件状态。错误处理与扩展性为增强鲁棒性,系统需对无效命令或参数进行提示。例如,输入 led yellow on 时,若不支持黄色,可返回 Error: Unsupported color。此外,可通过配置文件或动态加载方式支持新命令,避免硬编码限制未来功能扩展。通过以上设计,系统可清晰区分不同命令的职责,确保交互逻辑直观且易于维护,同时为硬件控制提供灵活的接口。



12a14d7c-ad11-4dbb-aca2-d2dcdde98c75.png

效果展示:

点亮红色led灯

57c05c58-6ff8-4b6c-b95f-95c5fd5c0107.png

红灯效果

8d78b7cd-0a08-4786-8e92-dc2a37a74b0a.png

绿灯效果

bbe5b135-697e-4c13-8845-16d1cc6469d4.png



















共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]