一、功能说明
基础功能(任务1)
串口通信:使用MCXA346开发板的UART串口输出"Hello, DigiKey Funpack 5-1"信息
实现效果:开发板上电后自动初始化串口,在串口调试工具中显示欢迎信息,RGBLED点亮与关闭。
进阶功能(Shell系统)
核心目标:实现一个带缓冲区的简易命令行解释器
主要功能:
交互式界面:显示"ysh> "提示符,支持实时字符回显
缓冲区管理:128字节输入缓冲区,支持退格删除
命令解析:支持空格分隔的参数解析
LED控制:
单个LED控制:开关、切换状态
所有LED控制:同时开关、闪烁
闪烁控制:可调节闪烁次数和间隔
系统功能:
help:显示所有可用命令
version:显示版本信息
info:显示系统信息
ysh> led red on
ysh> led blue toggle
ysh> all blink 5 200
ysh> blink green 3 100
二、实现计划
第一阶段:基础功能
开发环境配置
安装Keil MDK开发工具
配置MCXA346开发板SDK
设置串口调试工具XCOM
基础功能实现
硬件初始化GPIO、UART、时钟
实现LED基本控制功能
测试串口输出功能
第二阶段:Shell
输入系统设计
字符输入处理模块
输入缓冲区管理
特殊键处理
命令系统设计
命令解析模块
命令表结构设计
参数处理机制
第三阶段:功能扩展和优化
LED控制功能实现
LED控制命令
闪烁模式控制
三、软件框架
系统架构层次图

四、执行命令

五、核心代码
/* Shell input buffer */
static char shell_buffer[SHELL_BUFFER_SIZE];
static uint16_t shell_buffer_index = 0;
static bool shell_new_command = false;
/* Command table structure */
typedef struct {
const char *cmd_name; /* Command name */
const char *cmd_help; /* Command help text */
int (*cmd_func)(int argc, char *argv[]); /* Command handler */
} shell_command_t;
/* Command table */
static const shell_command_t shell_cmd_table[] = {
{"help", "Show all available commands", shell_cmd_help},
{"led", "Control LED: led [red|green|blue] [on|off|toggle]", shell_cmd_led},
{"all", "Control all LEDs: all [on|off|blink]", shell_cmd_all},
{"blink", "Blink LED: blink [red|green|blue] [times=3] [delay=500]", shell_cmd_blink},
{"clear", "Clear screen", shell_cmd_clear},
{"version", "Show version information", shell_cmd_version},
{"info", "Show system information", shell_cmd_info},
{NULL, NULL, NULL} /* End marker */
};
/*******************************************************************************
* Code
******************************************************************************/
/* Delay function */
void delay(void)
{
volatile uint32_t i = 0;
for (i = 0; i < 8000000; ++i)
{
__asm("NOP");
}
}
/* Millisecond delay function */
void delay_ms(uint32_t ms)
{
/* Simple delay loop - adjust for your clock speed */
for (volatile uint32_t i = 0; i < ms * 1000; ++i)
{
__asm("NOP");
}
}
/*******************************************************************************
* Shell Core Functions
******************************************************************************/
/* Shell initialization */
void shell_init(void)
{
shell_clear_buffer();
shell_new_command = false;
/* Show welcome message */
PRINTF("\r\n");
PRINTF("==============================================\r\n");
PRINTF(" eetree.cn for MCXA346 Board\r\n", SHELL_VERSION);
PRINTF(" Hello, DigiKey Funpack 5-1\r\n");
PRINTF("==============================================\r\n\r\n");
shell_show_prompt();
}
/* Run shell main loop */
void shell_run(void)
{
while (1)
{
/* Check if character is available */
int ch = GETCHAR();
if (ch != -1) /* Check if character is available */
{
shell_process_char((char)ch);
}
/* If new command is ready, execute it */
if (shell_new_command)
{
shell_execute_command();
shell_new_command = false;
shell_show_prompt();
}
}
}
/* Process input character */
void shell_process_char(char ch)
{
switch (ch)
{
case ASCII_CR: /* Enter */
case ASCII_LF: /* New line */
if (shell_buffer_index > 0)
{
shell_newline();
shell_new_command = true;
}
else
{
/* Empty command, just new line and show prompt */
PRINTF("\r\n");
shell_show_prompt();
}
break;
case ASCII_BACKSPACE: /* Backspace */
case ASCII_DEL: /* Delete */
if (shell_buffer_index > 0)
{
shell_backspace();
}
break;
case ASCII_CTRL_C: /* Ctrl+C */
PRINTF("^C\r\n");
shell_clear_buffer();
shell_show_prompt();
break;
default:
/* Handle printable characters only */
if (ch >= 0x20 && ch <= 0x7E)
{
if (shell_buffer_index < SHELL_BUFFER_SIZE - 1)
{
/* Store in buffer and echo */
shell_buffer[shell_buffer_index++] = ch;
shell_buffer[shell_buffer_index] = '\0';
PUTCHAR(ch);
}
else
{
/* Buffer full, beep warning */
PUTCHAR('\a');
}
}
break;
}
}
/* Execute command */
void shell_execute_command(void)
{
if (shell_buffer[0] == '\0')
{
return; /* Empty command */
}
/* Copy command string to avoid modifying original buffer */
char cmd_line[SHELL_BUFFER_SIZE];
strcpy(cmd_line, shell_buffer);
/* Parse and execute command */
shell_parse_command(cmd_line);
/* Clear buffer */
shell_clear_buffer();
}
/* Parse command */
void shell_parse_command(char *cmd_line)
{
char *argv[SHELL_MAX_ARGS];
int argc = 0;
char *token;
/* Split command arguments */
token = strtok(cmd_line, " \t");
while (token != NULL && argc < SHELL_MAX_ARGS)
{
argv[argc++] = token;
token = strtok(NULL, " \t");
}
if (argc == 0)
{
return; /* No command */
}
/* Find and execute command */
bool cmd_found = false;
for (int i = 0; shell_cmd_table[i].cmd_name != NULL; i++)
{
if (strcmp(argv[0], shell_cmd_table[i].cmd_name) == 0)
{
cmd_found = true;
shell_cmd_table[i].cmd_func(argc - 1, (argc > 1) ? &argv[1] : NULL);
break;
}
}
/* Command not found */
if (!cmd_found)
{
PRINTF("Unknown command: '%s'\r\n", argv[0]);
PRINTF("Hello, DigiKey Funpack 5-1\r\n");
}
}
/* Show prompt */
void shell_show_prompt(void)
{
PRINTF(SHELL_PROMPT);
}
/* Clear buffer */
void shell_clear_buffer(void)
{
shell_buffer[0] = '\0';
shell_buffer_index = 0;
}
/* Handle backspace */
void shell_backspace(void)
{
if (shell_buffer_index > 0)
{
shell_buffer_index--;
shell_buffer[shell_buffer_index] = '\0';
/* Backspace, space, backspace */
PUTCHAR('\b');
PUTCHAR(' ');
PUTCHAR('\b');
}
}
/* Handle new line */
void shell_newline(void)
{
PRINTF("\r\n");
}
/*******************************************************************************
* LED Control Functions
******************************************************************************/
/* Turn off all LEDs */
void led_all_off(void)
{
LED_RED_OFF();
LED_GREEN_OFF();
LED_BLUE_OFF();
}
/* Turn on all LEDs */
void led_all_on(void)
{
LED_RED_ON();
LED_GREEN_ON();
LED_BLUE_ON();
}
/* Blink all LEDs */
void led_blink_all(uint32_t times, uint32_t delay_time_ms)
{
for (uint32_t i = 0; i < times; i++)
{
led_all_on();
delay_ms(delay_time_ms);
led_all_off();
if (i < times - 1)
{
delay_ms(delay_time_ms);
}
}
}
/*******************************************************************************
* Command Handlers
******************************************************************************/
/* help command */
int shell_cmd_help(int argc, char *argv[])
{
PRINTF("\r\n=== Available Commands ===\r\n");
for (int i = 0; shell_cmd_table[i].cmd_name != NULL; i++)
{
PRINTF(" %-10s - %s\r\n",
shell_cmd_table[i].cmd_name,
shell_cmd_table[i].cmd_help);
}
PRINTF("===========================\r\n");
return 0;
}
/* led command */
int shell_cmd_led(int argc, char *argv[])
{
if (argc < 2)
{
PRINTF("\r\nUsage: led [red|green|blue] [on|off|toggle]\r\n");
PRINTF("Examples:\r\n");
PRINTF(" led red on # Turn on red LED\r\n");
PRINTF(" led green off # Turn off green LED\r\n");
PRINTF(" led blue toggle # Toggle blue LED\r\n");
return -1;
}
const char *color = argv[0];
const char *action = argv[1];
if (strcmp(color, "red") == 0)
{
if (strcmp(action, "on") == 0)
{
LED_RED_ON();
PRINTF("Red LED turned ON\r\n");
}
else if (strcmp(action, "off") == 0)
{
LED_RED_OFF();
PRINTF("Red LED turned OFF\r\n");
}
else if (strcmp(action, "toggle") == 0)
{
GPIO_PortToggle(BOARD_LED_GPIO, 1U << BOARD_LED_GPIO_PIN);
PRINTF("Red LED toggled\r\n");
}
else
{
PRINTF("Error: Invalid action '%s'\r\n", action);
return -1;
}
}
else if (strcmp(color, "green") == 0)
{
if (strcmp(action, "on") == 0)
{
LED_GREEN_ON();
PRINTF("Green LED turned ON\r\n");
}
else if (strcmp(action, "off") == 0)
{
LED_GREEN_OFF();
PRINTF("Green LED turned OFF\r\n");
}
else if (strcmp(action, "toggle") == 0)
{
GPIO_PortToggle(BOARD_LED_GPIO, 1U << BOARD_LED2_GPIO_PIN);
PRINTF("Green LED toggled\r\n");
}
else
{
PRINTF("Error: Invalid action '%s'\r\n", action);
return -1;
}
}
else if (strcmp(color, "blue") == 0)
{
if (strcmp(action, "on") == 0)
{
LED_BLUE_ON();
PRINTF("Blue LED turned ON\r\n");
}
else if (strcmp(action, "off") == 0)
{
LED_BLUE_OFF();
PRINTF("Blue LED turned OFF\r\n");
}
else if (strcmp(action, "toggle") == 0)
{
GPIO_PortToggle(BOARD_LED_GPIO, 1U << BOARD_LED3_GPIO_PIN);
PRINTF("Blue LED toggled\r\n");
}
else
{
PRINTF("Error: Invalid action '%s'\r\n", action);
return -1;
}
}
else
{
PRINTF("Error: Invalid color '%s'\r\n", color);
PRINTF("Available colors: red, green, blue\r\n");
return -1;
}
return 0;
}
/* all command - control all LEDs */
int shell_cmd_all(int argc, char *argv[])
{
if (argc < 1)
{
PRINTF("\r\nUsage: all [on|off|blink]\r\n");
PRINTF("Examples:\r\n");
PRINTF(" all on # Turn on all LEDs\r\n");
PRINTF(" all off # Turn off all LEDs\r\n");
PRINTF(" all blink # Blink all LEDs\r\n");
return -1;
}
const char *action = argv[0];
if (strcmp(action, "on") == 0)
{
led_all_on();
PRINTF("All LEDs turned ON\r\n");
}
else if (strcmp(action, "off") == 0)
{
led_all_off();
PRINTF("All LEDs turned OFF\r\n");
}
else if (strcmp(action, "blink") == 0)
{
uint32_t times = (argc > 1) ? (uint32_t)atoi(argv[1]) : 3;
uint32_t delay_time = (argc > 2) ? (uint32_t)atoi(argv[2]) : 800;
if (times == 0) times = 3;
if (delay_time == 0) delay_time = 800;
PRINTF("Blinking all LEDs %lu times, %lums interval\r\n", times, delay_time);
led_blink_all(times, delay_time);
}
else
{
PRINTF("Error: Invalid action '%s'\r\n", action);
return -1;
}
return 0;
}
/* blink command */
int shell_cmd_blink(int argc, char *argv[])
{
if (argc < 1)
{
PRINTF("\r\nUsage: blink [red|green|blue] [times=3] [delay=500]\r\n");
return -1;
}
const char *color = argv[0];
uint32_t times = (argc > 1) ? (uint32_t)atoi(argv[1]) : 3;
uint32_t delay_time_ms = (argc > 2) ? (uint32_t)atoi(argv[2]) : 500;
if (times == 0) times = 3;
if (delay_time_ms == 0) delay_time_ms = 500;
PRINTF("%s LED blinking %lu times, %lums interval\r\n", color, times, delay_time_ms);
for (uint32_t i = 0; i < times; i++)
{
if (strcmp(color, "red") == 0)
{
LED_RED_ON();
delay_ms(delay_time_ms);
LED_RED_OFF();
}
else if (strcmp(color, "green") == 0)
{
LED_GREEN_ON();
delay_ms(delay_time_ms);
LED_GREEN_OFF();
}
else if (strcmp(color, "blue") == 0)
{
LED_BLUE_ON();
delay_ms(delay_time_ms);
LED_BLUE_OFF();
}
else
{
PRINTF("Error: Invalid color '%s'\r\n", color);
return -1;
}
if (i < times - 1)
{
delay_ms(delay_time_ms);
}
}
return 0;
}
/* clear command */
int shell_cmd_clear(int argc, char *argv[])
{
/* Send ANSI escape sequence to clear screen */
PRINTF("\033[2J\033[H");
return 0;
}
/* version command */
int shell_cmd_version(int argc, char *argv[])
{
PRINTF("\r\nSimple Shell v%s\r\n", SHELL_VERSION);
PRINTF("MCUX SDK Version: %s\r\n", MCUXSDK_VERSION_FULL_STR);
PRINTF("Compiled: %s %s\r\n", __DATE__, __TIME__);
return 0;
}
/* info command */
int shell_cmd_info(int argc, char *argv[])
{
PRINTF("\r\n=== System Information ===\r\n");
PRINTF("Board: MCXA346\r\n");
PRINTF("Shell: ysh v%s\r\n", SHELL_VERSION);
PRINTF("Buffer size: %d bytes\r\n", SHELL_BUFFER_SIZE);
PRINTF("Supported commands: %d\r\n", (int)(sizeof(shell_cmd_table)/sizeof(shell_cmd_table[0])) - 1);
PRINTF("=======================\r\n");
return 0;
}
/*******************************************************************************
* Main Function
******************************************************************************/
int main(void)
{
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = {
kGPIO_DigitalOutput,
0,
};
/* Board pin, clock, debug console init */
BOARD_InitHardware();
/* Print welcome message */
PRINTF("\r\n");
PRINTF("MCUX SDK Version: %s\r\n", MCUXSDK_VERSION_FULL_STR);
PRINTF("LED Control Shell Example\r\n");
PRINTF("=====================================\r\n");
/* Init output LED GPIO */
GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &led_config);
GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED2_GPIO_PIN, &led_config);
GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED3_GPIO_PIN, &led_config);
/* Initial state: all LEDs off */
LED_RED_OFF();
LED_GREEN_OFF();
LED_BLUE_OFF();
/* Initialize shell */
shell_init();
/* Run shell main loop */
shell_run();
return 0;
}
六、心得体会
从这个开发板功能的实现,深入理解了MCXA346开发板的硬件架构,掌握了GPIO控制和UART通信原理,学会了中断和轮询的实现方式,并学会了Shell系统设计
,理解了命令行解释器的工作原理,掌握了缓冲区管理和字符处理技巧,学会了模块化设计思想在嵌入式系统中的应用。