Funpack5-1 - 使用MCXA346开发板的UART串口通信
使用MCXA346开发板的UART串口输出"Hello, DigiKey Funpack 5-1"信息,并实现Shell系统通信控制RGB灯,并把执行的信息通信串口打印在串口助手中。
标签
嵌入式系统
开发板
MCU
串口
RGB
meiyao
更新2026-03-17
5

一、功能说明

 基础功能(任务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控制命令

闪烁模式控制


三、软件框架

 系统架构层次图

image.png

四、执行命令

image.png

五、核心代码

/* 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系统设计

,理解了命令行解释器的工作原理,掌握了缓冲区管理和字符处理技巧,学会了模块化设计思想在嵌入式系统中的应用。


附件下载
led_output.rar
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号