如何去实现一种串口命令控制台呢?

发布者:EnchantedBreeze最新更新时间:2024-06-28 来源: elecfans关键字:串口命令  STM32F系列 手机看文章 扫描二维码
随时随地手机看文章

1. 前言


玩过Linux的朋友, 是不是对Linux无所不能的串口Shell命令控制台羡慕不已, 要是自己做的STM32F系列低档次的MCU也有这种控制交互能力, 会给调试/维护和配置省下多少麻烦事呀, 比如启动/关闭调试或自检模式, 打印调试信息, 配置系统参数, 传输文件等等, 也有相当多的朋友凭借自己出色的编程能力可以实现这些功能, 这里提出我的这个解决方案, 以作交流.



本平台(xc_shell)具备以下性能特点:


大量主要代码, 和具体硬件无关, 移植性强,代码文件少.


只有在处理用户的输入命令时, 才占用CPU资源, 且代码可裁剪到1KB SRAM和4KB Flash;


用户可以非常灵活的添加按模板编写的命令脚本文件, 自定义扩张能力强.


支持操作系统和非操作系统两种场景应用.


支持Ymodem文件传输协议


支持将Flash的扇区开辟为参数区, 可实现本地/远程升级。


实用Led灯信号管理, 可将65535虚拟信号灯选择输出到1个实体LED灯上, 调试时序和状态非常有用


拥有基础的LED管理, 调试模式设置, 命令帮助指令, 复位指令等基础功能


功能越多设计会越复杂, 为了解释清楚代码, 先向大家解释一下以上功能的基础实现原理, 并提供一个最小的的源码工程。


2. xc_shell平台介绍


2.1 如何实现硬件无关


类比Linux会发现, 设备的硬件接口往往会被虚拟成一个文件(驱动), 而Linux内核完全与硬件系统无任何字节关联, 不同平台驱动不同而已, 故而本xc_shell的串口驱动也采用了相似的思路:


1 ) 串口驱动用一个结构体描述, 这样只需在xc_shell.c中用指针指向这个TTYx_HANDLE结构体对象就可以将串口(tty)硬件与内核联系在一起, 聪明的朋友可能会想到, 假如我将带网络的开发板按此结构体,虚拟一个TTY对象, 岂不是就可以实现一个网络远程控制台了!  这点确实是可以的!


2) 当然诸如多TTY串口实现接口互换等, 都是一个指针和step2中的注入回调处理交换的问题。


3)用户在使用api_TxdFrame或api_TxdByte时”bsp_ttyX.c“,会驱动具体MCU的串口将数据发送出去, 收到一帧数据后,若用户设置了inj_RcvFrame回调处理方法,则会在中断中执行用户的回调处理。


 


/*---------------------* 

*     指正函数定义

*----------------------*/

typedef void    (*pvFunDummy)(void);

 

//输入整行,输出逻辑

typedef void    (*pvFunVoid) (void);

typedef void    (*pvFunBool) (bool     bVal);

typedef void    (*pvFunChar) (uint8_t  cVal);

typedef void    (*pvFunShort)(uint16_t sVal);

typedef void    (*pvFunWord) (uint32_t wVal);

 

//输入整行,输出逻辑

typedef bool    (*pbFunVoid) (void);

typedef bool    (*pbFunBool) (bool     bVal);

typedef bool    (*pbFunChar) (uint8_t  cVal);

typedef bool    (*pbFunShort)(uint16_t sVal);

typedef bool    (*pbFunWord) (uint32_t wVal);

 

//输入整形指针,输出逻辑

typedef bool    (*pbFun_pVoid) (void * pVoid);

typedef bool    (*pbFun_pChar) (uint8_t  * pStr);

typedef bool    (*pbFun_pShort)(uint16_t * pShor);

typedef bool    (*pbFun_pWord) (uint32_t * pWord);

 

//输入数据帧,输出逻辑

typedef bool    (*pbFun_Buffx)(void * pcBuff, uint16_t len );

typedef bool    (*pbFun_Bytex)(uint8_t * pcByte, uint16_t len );

/*---------------------* 

*    TTYx 句柄结构

*----------------------*/

typedef struct TTYx_HANDLE_STRUCT 

{

    const char  * const name;       //驱动器

    const uint16_t      rxSize;     //接收大小

    const uint16_t      txSize;     //发送大小

    

    //------------------------------------------------------

    //step1: 用户可用API

    const pvFunWord     init;           //初始化.

    const pbFun_Bytex   api_TxdFrame;   //发送数据帧. (发送帧)

    const pbFunChar     api_TxdByte;    //发送数据字节

    

    //------------------------------------------------------

    //step2: 注入回调函数

    pbFun_Bytex         inj_RcvFrame;   //(ISR)接收数据帧. (接收帧)

    pvFunDummy          inj_TxdReady;   //(ISR)发送完毕回调

    

    //------------------------------------------------------

    //step3: 接收回调函数

    struct TTYx_HANDLE_STRUCT * pvNext; //连接到下一个指令 

}TTYx_HANDLE;

 


可注入的命令脚本(CLI)实现


命令CLI也是一个结构体对象:


 


/*---------------------* 

*       CLI指令

*----------------------*/

typedef struct

{

 const char * const  pcCmdStr;     //指令字符串(只能为小写字母)

 const char * const  pcHelpStr;     //指令描述,必须以:'

结束'. 比如:'help: Returns a list

'.

 const pFunHook      pxCmdHook;     //指向回调函数的指针,处理成功返回真否者返回0;

 uint8_t             ucExpParam;     //指令期望的参数个数

 const MEDIA_HANDLE *phStorage;      //指向存储介质,没有的话填充NULL  

}Cmd_Typedef_t;

 


各位朋友可能会使用到非常多的自定义CLI命令, 格式诸如这个网卡的命令:


 


const Cmd_Typedef_t CLI_WizMsg=

{

    //识别关键字

    .pcCmdStr   = 'wiz',

    //帮助内容

    .pcHelpStr  =

    '[WIZ contorls]

'

 ' wiz help

'

 ' wiz rd info

'

 ' wiz reset

'

 ' wiz wr ip ...

'

 ' wiz wr mask ...

'

 ' wiz wr way ...

'

 ' wiz wr mac -

-

-

-

-


'

 ' wiz wr port    

'

 ' wiz wr sip ... 

'

 ' wiz wr cip ... 

'

 ' wiz load default

'

 '[WIZ Test mode]

'

 ' wiz loop open

'

 ' wiz loop close

'

 '

',

 

 //处理函数

 .pxCmdHook  = &Shell_WIZ_Service,        //见实体函数

 

 //附带数据

 .ucExpParam = 0,

 

  #ifdef SHELL_USE_YMODEM  

    //存储介质

    .phStorage  = NULL,

  #endif

};

/*---------------------* 

*       CLI 链表节

*----------------------*/

Cmd_List_t  WizList   = { &CLI_WizMsg,   NULL,}; //Shell指令的头

 


如配置IP地址输入“wiz wr ip 192.168.1.250 ”则可以了


3. 环境准备


3.1 硬件开发环境


STM32F103系列开发板一块, 带USART1接口。


USB转串口线一根。


3.2 软件开发环境


MDK4.72或以上


SecureCRT串口超级终端


3.3 软件配置

在xc_shell使用“/r/n”作为命令的结束符, 而SecureCRT按下Enter不是输入“/r/n”故而需要按下图设置:此外在《终端》/仿真/高级中选取【本地回显】

8e2d4e92-263e-11ee-962d-dac502259ad0.png?imageView2/2/w/1000

4. 代码介绍


4.1 目录结构


 


□ XC_SHELL

├──┬── BSP_LIB    BSP库,硬件相关驱动代买

│  ├──── bsp_ledx.c   基础LED驱动      

│  └──── bsp_tty0.c   调试串口驱动

├──┬──MDK-ARM     工程文件

│  └──── Project.uvproj

├──┬──SHELL_CFG   SHELL配置头文件

│  └──── user_eval.h

├──┬──SHELL_CORE  SHELL内核文件

│  ├──── xc_shell.c   SHELL内核文件

│  ├──── xc_ymodem.c  Ymodem传输协议(默认关闭,在xc_shell.h中启动)

│  ├──── xc_iap.c     Flash的IAP操作,需要bsp_flash.c驱动支持

│  └──── shell_iap.c  shell的用户脚本模板

├──┬──SHELL_INC   SHELL头文件

│  ├──── bsp_type.h   驱动结构定义

│  ├──── xc_shell.h   SHELL头文件

│  └──── xconfig.h    硬件无关配置文件

├──┬──STM32F10x_StdPeriph_Lib_V3.5.0  STM32的标准外设库

│  └──── ......

└──┬──USER        用户文件    

   ├─ .....       

   └──── main.c        main文件


4.2 工程设置要点

1) 设置使用微库:

8e539d18-263e-11ee-962d-dac502259ad0.png?imageView2/2/w/1000

2)配置包含和路径,注意使用了“--c99”标准,如图

8e7b1da2-263e-11ee-962d-dac502259ad0.png?imageView2/2/w/1000

3) 编译工程,无错误警告后烧写程序到开发板运行。

4.3 最终效果

按图输入一下指令,SHELL平台会回复相关信息。其中输入“led set 0=1”会将信号1分配到物理LED0上;输入“led set 0=2”会将信号2分配到物理LED0上。这样用户编写程序代码时相当于拥有了超级多的LED信号可用,调试时序非常有用。8e8f1172-263e-11ee-962d-dac502259ad0.png?imageView2/2/w/1000

5. 添加自己的指令脚本

5.1 源代码示例

假设我要编写一个自己的指令脚本, 来读取MCU的关键信息,关键字为mcu, 文件命名为shell_mcu.c;当输入“mcu rd 0”时显示MCU的FLASH大小,输入“mcu rd 1”时读取MCU的唯一ID信息。shell_mcu.c源代码:

/*********************************Copyright (c)*********************************

**                               

**                                 FIVE工作组

**

**---------------------------------File Info------------------------------------

** File Name:               shell_mcu.c

** Last modified Date:      2017/9/17 1557

** Last Version:            V1.0

** Description:             shell测试

**

**------------------------------------------------------------------------------

** Created By:              wanxuncpx

** Created date:            2017/9/17 1508

** Version:                 V1.0

** Descriptions:            none

**------------------------------------------------------------------------------

** HW_CMU:                  STM32F103

** Libraries:               STM32F10x_StdPeriph_Lib_V3.5.0

** version                  V3.5

*******************************************************************************/

 

/******************************************************************************

更新说明:

******************************************************************************/

 

/******************************************************************************

*********************************  编 译 控 制 ********************************

******************************************************************************/

#define MCU_SHELL               //注释掉时屏蔽iap shell功能

 

#include 'xc_shell.h'       //Shell支持文件,含bool,uint8_t..以及串口数据收发操作

/******************************************************************************

********************************* 文件引用部分 ********************************

******************************************************************************/

/*---------------------* 

*     模块驱动引用

*----------------------*/

//#include 'net_w5500.h'

 

#ifdef MCU_SHELL

/******************************************************************************

********************************** Shell实例 **********************************

******************************************************************************/

/*---------------------* 

*      CLI指令服务

*----------------------*/

extern bool Shell_MCU_Service(void * pcBuff, uint16_t len );

 

/*---------------------* 

*       CLI 结构

*----------------------*/

const Cmd_Typedef_t CLI_McuMsg=

{

    //识别关键字

    'mcu',

    

    //帮助内容

 '[mcu contorls]

'

 ' mcu rd - Read FLASH information.

'

 '

',

 

 //处理函数

 &Shell_MCU_Service,

 

 //附带数据

 0,

  #ifdef SHELL_USE_YMODEM  

    //存储介质

    NULL,

  #endif

};

 

/*---------------------* 

*     CLI链表节(输出)

*----------------------*/

Cmd_List_t  McuList  = {&CLI_McuMsg      ,NULL}; //IAP指令链表

[1] [2]
关键字:串口命令  STM32F系列 引用地址:如何去实现一种串口命令控制台呢?

上一篇:彻底搞懂8种GPIO输入输出模式
下一篇:C语言基础知识点

推荐阅读最新更新时间:2026-03-24 21:49

CC2530串口命令控制LED灯开关
实验要求 代码实现 #include ioCC2530.h #define D4 P1_1 #define D6 P1_4 unsigned char temp=0;//接收命令变量 //系统时钟切换函数从16M——32M void Set_Clock_32M() { CLKCONCMD &=~0x40; while(CLKCONSTA &0X40) { } CLKCONCMD &=~0x47; } //端口初始化函数 void Init_Prot() { //配置4个LED灯的引擎 //选择端口的功能 P1SEL &=~0x1B;//设置通用io端口 //配置端口的方向 P1DIR |
[单片机]
CC2530<font color='red'>串口</font><font color='red'>命令</font>控制LED灯开关
8051单片机串口复杂命令接收与解析
下面程序是为了实现二自由度自动进样检测器的控制而编写的. 在程序执行过程中, 我发现, 在发送Start.E再发送Stop.E后, 串口助手接收缓存区并未显示一连串 00 : 这说明在输入Start.E后, 虽然又收到Stop.E时执行了 en = 0 这个表达式, 但是回到第一层中断处理程序后, 这里的en还是 1 (并未变为我们希望的 0 ). 这说明, 以串口中断实现对二自由度自动进样检测仪的控制, 还是有一定难度的. 接下来我将致力于解决这一难题. #include STC89C5xRC.H char buf ;//存放串口传来的数据 int i = 0; int en; void UART_INT()
[单片机]
串口命令解析
本文件直接使用在stm32平台上 实现功能是,例如串口中数据有:sjakjshdkjdjsahesmklsahesnkjshesndsahes 能精确的把每个hes解析出来。 使用方式也简单: 添加我上面的库文件到你的工程 串口中断中调用以下函数 .h文件添加想要查找的命令 主函数里面检测命令,查找到这些命令你就可以做相应的事了 用串口助手给单片机发送数据效果:
[单片机]
<font color='red'>串口</font><font color='red'>命令</font>解析
nRF24L01 无线模块 串口命令 通过无线控制另一个的灯
_ !概述: 这是在上一个的基础上通过按键发送4种不同命令来控制接收端的LED灯亮的改进版(上一个: http://www.cnblogs.com/zjutlitao/p/3840013.html ),这里俺把按键发命令给去掉,然后加入一个串口通信的功能,PC通过串口给发送端发送命令,然后发送端通过无线将命令发给接收端来实现控制,这里接收端和上一个例程中的一样,只是在发送端的代码里去除了按键控制,变成了串口控制。 _ !发送端电路: _ !接收电路图: _ !代码: 由于这里的接收端的代码和上一个一样,所以不做介绍(惜墨如金呀,哈哈~~),下面就发送端进行介绍: 1 /*------------------------
[单片机]
nRF24L01 无线模块 <font color='red'>串口</font>法<font color='red'>命令</font> 通过无线控制另一个的灯
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved