调试单片机程序往往要用串口,光有输出也不够爽,我自己一直留着一份命令行代码,只要单片机资源足够就放上去。直接贴源码如下:
#define PARAM_MAX (10) /* 最多支持10个参数 */
#define CLI_MAX_LEN (32) /* 缓存大小,根据资源和最长命令行长度决定 */
/* 用户输入命令行 */
unsigned char g_input_buf[CLI_MAX_LEN];
unsigned char g_input_idx = 0;
/**********************************************************
函数描述 : 16进制字符转数值
输入参数 : c -- 字符,不作参数检查
输出参数 :
返 回 值 : 数值,
作 者 : gavinpeng
时 间 : 2016.11.25
************************************************************/
unsigned char char_to_val(unsigned char c)
{
if ( (c >= '0') && (c <= '9') )
return c - '0';
else if ( (c >= 'A') && (c <= 'Z') )
return c - 'A' + 10;
else if ( (c >= 'a') && (c <= 'z') )
return c - 'a' + 10;
else
return 0;
}
/**********************************************************
函数描述 : 字符串转数值
输入参数 : str -- 字符串
输出参数 :
返 回 值 : 数值,
作 者 : gavinpeng
时 间 : 2016.11.25
************************************************************/
int str_to_int(unsigned char *str)
{
int flag;
int value = 0;
unsigned char *p = str;
if ( NULL == str )
return 0;
/* 16进制 */
if ( (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')) )
{
value = 0;
p = &str[2];
while ( *p )
{
value = value * 16 + char_to_val(*p);
p++;
}
return value;
}
/* 10进制 */
if ( str[0] == '-' )
flag = -1;
else
flag = 1;
value = 0;
p = str;
while ( *p )
value = value * 10 + char_to_val(*p++);
value = value * flag;
return value;
}
/**********************************************************
函数描述 : 命令行测试
输入参数 :
输出参数 :
返 回 值 :
作 者 : gavinpeng
时 间 : 2016.11.25
************************************************************/
void cmd_proc_test(int argc, char *argv[])
{
int val;
/* test val */
if ( argc == 2 )
{
val = str_to_int(argv[1]);
printf("val = %d\r\n", val);
return;
}
}
/**********************************************************
函数描述 : 命令行菜单
输入参数 :
输出参数 :
返 回 值 :
作 者 : gavinpeng
时 间 : 2016.11.25
************************************************************/
void cmd_usage(void)
{
printf("\r\ncmd usage:\r\n");
printf("? -- this menu\r\n");
printf("ver -- show version\r\n");
printf("test val -- how to use int\r\n");
}
/**********************************************************
函数描述 : 处理用户输入的命令
输入参数 :
输出参数 :
返 回 值 :
作 者 : gavinpeng
时 间 : 2016.11.25
************************************************************/
void cmd_proc(void)
{
int argc;
char *argv[PARAM_MAX];
char *p;
/* 格式化字符串,把空格分开的词放入多个字符串 */
p = (char*)g_input_buf;
while ( *p && (' ' == *p) ) p++;
if ( *p == '\0' )
return;
argc = 0;
argv[argc++] = p;
while ( *p )
{
if ( ' ' == *p )
{
*p++ = '\0';
while ( *p && (' ' == *p) ) p++;
if ( *p == '\0' )
break;
else
argv[argc++] = p;
if ( argc >= PARAM_MAX )
return;
}
p++;
}
/* 处理消息 */
if ( strcmp("?", argv[0]) == 0 )
cmd_usage();
else if ( strcmp("ver", argv[0]) == 0 )
printf("master ver: 1.0\r\n%s %s\r\n", __DATE__, __TIME__);
else if ( strcmp("test", argv[0]) == 0 )
cmd_proc_test(argc, argv);
else
{
printf("unknown cmd: %s\r\n\r\n", argv[0]);
cmd_usage();
}
return;
}
/**********************************************************
函数描述 : 分析输入的字符
输入参数 : buf -- 输入的字符首指针
len -- 输入字符的长度
输出参数 :
返 回 值 :
作 者 : gavinpeng
时 间 : 2016.11.25
************************************************************/
void cmd_parse(char *buf, unsigned int len)
{
int i = 0;
char c;
while ( i < len )
{
c = buf[i++];
if ( c <= 0 )
continue;
switch ( c )
{
case '\r':
case '\n': /* 0x0A, 回车的处理 */
//g_input_buf[g_input_idx++] = '\r';
printf("\r\n");
g_input_buf[g_input_idx] = '\0';
cmd_proc();
g_input_idx = 0;
break;
case '\b': /* 0x08, 退格键 */
if ( g_input_idx > 0 )
{
g_input_idx--;
printf("\b \b");
}
g_input_buf[g_input_idx] = 0;
break;
default:
/* 添加可见字符,其它忽略 */
g_input_buf[g_input_idx++] = c;
printf("%c", c);
break;
}
}
}
/* 这里是串口中断函数 */
void uart1_ISR(void) interrupt
{
// 从串口寄存器读出数据,放进全局buffer中
if ( g_uart_rx_len < CLI_MAX_LEN )
g_uart_db_rx_buf[g_uart_db_rx_len++] = uart_buf;
}
void main(void)
{
// 串口初始化
// 主循环
while ( 1 )
{
if ( g_uart_db_rx_len )
{
cmd_parse(g_uart_db_rx_buf, g_uart_db_rx_len);
g_uart_db_rx_len = 0;
}
}
}
有更好的,欢迎指出。
惯例要介绍一下自家的产品:
https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.594c1debREF8Mj&id=579411892273