你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】实用STM32的串口控制平台的实现!

[复制链接]
STMCU小助手 发布时间:2022-1-5 21:00
1. 前言

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

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

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

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

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

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

  • 支持Ymodem文件传输协议

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

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

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


    6 _0 q3 Q' ]9 I: ]* ~! _1 j

    7 }  B6 y( d8 {% p+ q5 M* |) i7 L+ l) f

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

# }" ^9 ^( j. {

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回调处理方法,则会在中断中执行用户的回调处理。

  1. <i>/*---------------------*
    5 E- v* u7 T; s: K& J! l
  2. *     指正函数定义
    ! b0 I/ J, t2 V9 Y
  3. *----------------------*/</i>2 h) C* O( _& F! \
  4. typedef void    (*pvFunDummy)(void);1 d; C' v- v* m( t  D) _+ m
  5. 7 V8 N$ ^5 P$ S- j+ p8 C+ W2 {5 R. [
  6. <i>//输入整行,输出逻辑</i>2 F$ L! l, ^+ h  o# W5 i
  7. typedef void    (*pvFunVoid) (void);
      B' o2 Y2 w; L6 }0 M6 W
  8. typedef void    (*pvFunBool) (bool     bVal);! O  ^, P+ m0 h
  9. typedef void    (*pvFunChar) (uint8_t  cVal);
    # n" d" F& U# P/ V0 j( ^/ N- y
  10. typedef void    (*pvFunShort)(uint16_t sVal);& v- ]' Z4 ]" H& ~0 W5 F; ?; ?
  11. typedef void    (*pvFunWord) (uint32_t wVal);
    5 E+ j6 H0 [# ~# v

  12. $ `3 l: m. f. O) P. L" V
  13. <i>//输入整行,输出逻辑</i>
    8 R" U5 K2 o, W# {* S6 L) \) ]# ?2 F
  14. typedef bool    (*pbFunVoid) (void);
    + L" ?8 k: e( n  f# [& B& C
  15. typedef bool    (*pbFunBool) (bool     bVal);. r- w, ^4 f8 o
  16. typedef bool    (*pbFunChar) (uint8_t  cVal);- `8 Z  K, `$ \
  17. typedef bool    (*pbFunShort)(uint16_t sVal);
    ) K, i$ Q2 N; o  q3 a, P2 Z
  18. typedef bool    (*pbFunWord) (uint32_t wVal);7 ?2 B6 {% `, ?8 v# x$ K
  19. ; |; P9 K% u0 M1 J& Z3 y& G
  20. <i>//输入整形指针,输出逻辑</i>4 o2 K4 W7 Y) [5 R# }7 N. ]
  21. typedef bool    (*pbFun_pVoid) (void * pVoid);. y9 N4 S! v) }  r$ a
  22. typedef bool    (*pbFun_pChar) (uint8_t  * pStr);* x; _7 _+ ?7 o* q; L( p( l
  23. typedef bool    (*pbFun_pShort)(uint16_t * pShor);/ Y, X5 h6 [/ q0 T
  24. typedef bool    (*pbFun_pWord) (uint32_t * pWord);
    ; [1 S; [. A/ l$ F, r& `) h1 t
  25. $ z2 C! T# O( x7 I2 N
  26. <i>//输入数据帧,输出逻辑</i># Q% T* P- [' W5 I* u
  27. typedef bool    (*pbFun_Buffx)(void * pcBuff, uint16_t len );
    ; i2 l7 K) m( b2 c
  28. typedef bool    (*pbFun_Bytex)(uint8_t * pcByte, uint16_t len );, [8 R' ]4 N& Q% `
  29. <i>/*---------------------* 6 j3 F  V) C9 |
  30. *    TTYx 句柄结构' l% U- R( i4 [& E; M6 |4 G( Q, f
  31. *----------------------*/</i>
      x7 u; ^/ F6 y9 ^
  32. typedef struct TTYx_HANDLE_STRUCT 5 G2 h+ U/ v: k6 k7 {  X% F5 Q" I; _: F4 t
  33. {
    % ?- ^+ M6 A/ \) q, s$ K5 H
  34.     const char  * const name;       <i>//驱动器名</i>
    $ l% }) `6 D+ X) ]! L6 L
  35.     const uint16_t      rxSize;     <i>//接收大小</i>+ i- N: {$ N6 _: K% F' S. I* I
  36.     const uint16_t      txSize;     <i>//发送大小</i>
    & \& ]9 b# Y) v! @: v4 T+ J
  37.    
    : t6 @! a2 D/ @+ |) r2 F5 \
  38.     <i>//------------------------------------------------------</i>( C& O( R, o% R6 t1 N. @
  39.     <i>//step1: 用户可用API</i>
    $ o4 T6 `) h. h, l! ]3 ]* P
  40.     const pvFunWord     init;           <i>//初始化.</i>7 P/ b  v0 \% H
  41.     const pbFun_Bytex   api_TxdFrame;   <i>//发送数据帧. (发送帧)</i>% h. H# J" J- N4 X7 C9 {, d
  42.     const pbFunChar     api_TxdByte;    <i>//发送数据字节</i>2 q( r1 x7 o5 p7 y! U1 M6 d' T
  43.    
    # m1 ~, ^$ |* V; C. F! U
  44.     <i>//------------------------------------------------------</i>  x/ R2 G: x. s# f% k- f0 U
  45.     <i>//step2: 注入回调函数</i>
    2 b, W4 `4 f; k1 u
  46.     pbFun_Bytex         inj_RcvFrame;   <i>//(ISR)接收数据帧. (接收帧)</i>
    4 _. J/ ?2 I! x
  47.     pvFunDummy          inj_TxdReady;   <i>//(ISR)发送完毕回调</i>
    & g# K9 e, }/ _! L& H
  48.    
    ! r; t  }9 }& H: f+ K
  49.     <i>//------------------------------------------------------</i>/ c+ g5 l- m; ]
  50.     <i>//step3: 接收回调函数</i>
    7 j1 ]5 G2 O+ ^4 O$ K
  51.     struct TTYx_HANDLE_STRUCT * pvNext; <i>//连接到下一个指令 </i>
    ! m# i6 z) g/ n7 A) b% v7 Q# I' w
  52. }TTYx_HANDLE;
复制代码
可注入的命令脚本(CLI)实现
+ n+ u# w& M. w2 I, ?! w' v, b$ @
  • 命令CLI也是一个结构体对象:6 h+ J+ O4 Z% P, w

. I7 I3 ]. h% N% k1 F# M

. e' T8 Y  s, y0 a7 `

) d) K8 W: V# A" b
  1. <i>/*---------------------* / K' |1 J5 B7 q6 a& V$ F
  2. *       CLI指令
    7 Z( X  [: ^: K1 J
  3. *----------------------*/</i>
    8 Z. w6 b+ g* \; p2 v1 Z) d
  4. typedef struct
    $ N4 y4 G2 M1 i3 P; m; h4 ]
  5. {9 |: q# a0 J' |: R
  6. const char * const  pcCmdStr;     <i>//指令字符串(只能为小写字母)</i>& B; }: f' N$ @; k& C& X0 W
  7. const char * const  pcHelpStr;     <i>//指令描述,必须以:"\r\n结束". 比如:"help: Returns a list\r\n".</i>5 \6 ?- y1 q+ f" L- q& I7 p: I; |
  8. const pFunHook      pxCmdHook;     <i>//指向回调函数的指针,处理成功返回真否者返回0;</i>
    . d& Y7 B4 u5 j: g5 L
  9. uint8_t             ucExpParam;     <i>//指令期望的参数个数</i>/ h$ D7 D; v5 v% K# e5 V4 |/ D7 r( |
  10. const MEDIA_HANDLE *phStorage;      <i>//指向存储介质,没有的话填充NULL  </i>* I; A) ?$ f& Q' s7 V
  11. }Cmd_Typedef_t;
复制代码
0 i# `' b0 L8 r# @' i* q

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

  1. const Cmd_Typedef_t CLI_WizMsg=
    4 Z! p) u8 a/ _0 t
  2. {7 V- K& O/ g. J! k- t( J
  3.     <i>//识别关键字</i>
    0 l, z  }# P+ }& I. m
  4.     .pcCmdStr   = "wiz",( C- D" ~4 _, z- l! M, H, B7 M
  5.     <i>//帮助内容</i>& G9 x. G( A- t& x! s: v: y4 X/ X
  6.     .pcHelpStr  =! x$ Q' G% ~7 ]* H) h
  7.     "[WIZ contorls]\r\n"+ A8 H7 \$ O: ^
  8. " wiz help\r\n"+ n. b: r" V0 T
  9. " wiz rd info\r\n"
    ( X$ [+ A* v  s- _% g( |' ]* ]$ h" U
  10. " wiz reset\r\n"
    / D$ n7 ?; i( e) x0 a, W
  11. " wiz wr ip <D0>.<D1>.<D2>.<D3>\r\n"
    * u& i# o. _- S1 b7 T; M$ G
  12. " wiz wr mask <D0>.<D1>.<D2>.<D3>\r\n"* `2 z* `8 ~( `; F
  13. " wiz wr way <D0>.<D1>.<D2>.<D3>\r\n"
    0 J) z  V" s& v: S, N, c
  14. " wiz wr mac <H0>-<H1>-<H2>-<H3>-<H4>-<H5>\r\n"
    5 P6 l; J9 f, s. y* z& s. G3 U- j
  15. " wiz wr port <udp> <bak> <vol> <pic>\r\n"* z2 f4 E$ j( ?+ z' v6 Y; Y
  16. " wiz wr sip <D0>.<D1>.<D2>.<D3> <port>\r\n"
    6 {6 P; z  h% f: A+ F. ~' R
  17. " wiz wr cip <D0>.<D1>.<D2>.<D3> <port>\r\n"
    ! }+ b+ T& s8 @; I
  18. " wiz load default\r\n"  N% ?& M$ m: [. p' J
  19. "[WIZ Test mode]\r\n"
    1 q9 [7 ?9 Y' K/ c9 s- Z
  20. " wiz loop open\r\n"
    - `* R  {/ _/ B. w1 O
  21. " wiz loop close\r\n"
    3 p4 M1 D7 l6 F: {) Z4 c
  22. "\r\n",
    , w1 L# r3 ^9 @
  23. % W: S' `& X* h
  24. <i>//处理函数</i>
    , t$ i1 l0 K! P4 t
  25. .pxCmdHook  = &Shell_WIZ_Service,        <i>//见实体函数</i>' e" J0 A+ E. U. w! m. q

  26. + G% E6 [9 c4 ~. f* Z
  27. <i>//附带数据</i>6 F: v) M; Z/ |( [
  28. .ucExpParam = 0,
    ' n% e& ^1 M; L7 X

  29. * o5 {8 a! i* ]" w
  30.   #ifdef SHELL_USE_YMODEM  
    8 t1 s7 @2 ?( v( ]% I
  31.     <i>//存储介质</i>0 W2 F6 |$ O6 Y6 p/ b& q: @
  32.     .phStorage  = NULL,' i& P: g2 }( \  N# w
  33.   #endif+ B1 R& i/ S- U  w7 f& I6 P
  34. };  i& S& T: I! d: u# S. y( i
  35. <i>/*---------------------*
    8 t6 N, W4 X: l: S" W
  36. *       CLI 链表节2 Z, ?6 H* }: c: X' S9 E2 h+ K
  37. *----------------------*/</i>
    6 r, C, F9 u; d* Q% o: ~+ [
  38. Cmd_List_t  WizList   = { &CLI_WizMsg,   NULL,}; <i>//Shell指令的头</i>
复制代码
0 C, _7 m+ z& H+ ^

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

3. 环境准备
) w" y' ~3 f/ i( g; N8 A" h0 A3.1 硬件开发环境
  • STM32F103系列开发板一块, 带USART1接口。
  • USB转串口线一根。
    3 [. t3 R. R+ Z/ C9 ^/ r

    ; a! E. O- v0 `; }" F' Y# r& c" d, }
3.2 软件开发环境
  • MDK4.72或以上
  • SecureCRT串口超级终端. t: u9 N; s, t* I1 j5 v
    * ?: T9 [$ h. @; m
3.3 软件配置

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

4. 代码介绍
! A- C3 \. t5 I- t; ?& X) B% g7 o4.1 目录结构□ XC_SHELL! U+ Z! k2 S( M$ T
  1. ├──┬── BSP_LIB    BSP库,硬件相关驱动代买
      l, }; C7 l3 }
  2. │  ├──── bsp_ledx.c   基础LED驱动      : u0 S* Y2 B1 w
  3. │  └──── bsp_tty0.c   调试串口驱动* S8 f) v0 F2 o1 v9 E( G6 S
  4.   e. Z4 M. @0 P9 u8 U1 L
  5. ├──┬──MDK-ARM     工程文件
    0 c, e7 ^9 R" C' Q( S2 p- f" t
  6. │  └──── Project.uvproj% _; M& G( w1 `  x- C$ X: o& @
  7. 8 n8 K) y0 ?( m' J0 y6 Y% b! p" @
  8. ├──┬──SHELL_CFG   SHELL配置头文件  f& o! I! w. W6 [1 {
  9. │  └──── user_eval.h
    . s/ T1 o9 `1 _3 `/ W- v9 h; o' l
  10. ( Q4 i& u. h4 E" l* z
  11. ├──┬──SHELL_CORE  SHELL内核文件
    0 ]$ b% P6 l$ ^. I4 q- R) H8 {- F
  12. │  ├──── xc_shell.c   SHELL内核文件
    3 u. Y% A4 v1 c& S% _( o) |
  13. │  ├──── xc_ymodem.c  Ymodem传输协议(默认关闭,在xc_shell.h中启动)
    * T6 T7 `4 x1 w0 T
  14. │  ├──── xc_iap.c     Flash的IAP操作,需要bsp_flash.c驱动支持9 h( z2 f' P8 ~
  15. │  └──── shell_iap.c  shell的用户脚本模板" w9 Z2 h' A7 d8 {

  16.   M: ^7 ?2 u) U% ~# q) g
  17. ├──┬──SHELL_INC   SHELL头文件
    * u* e) y9 U% z( n$ I
  18. │  ├──── bsp_type.h   驱动结构定义
    7 c( x+ n' {& @" W
  19. │  ├──── xc_shell.h   SHELL头文件8 i2 Y; C2 @; x' ]$ e
  20. │  └──── xconfig.h    硬件无关配置文件
    ! R6 g" O/ f& y6 Y# C
  21. 9 r9 ^2 P+ t/ G9 A% m0 d0 k
  22. ├──┬──STM32F10x_StdPeriph_Lib_V3.5.0  STM32的标准外设库
    ( u$ Y$ ~8 s7 y9 r6 Q6 _: _
  23. │  └──── ......
    ) @* E4 k; t' I4 T; {6 R) L
  24. / _* r' S" I" ~7 D. n, R  C& M
  25. └──┬──USER        用户文件   
    9 w4 {: e/ Q3 a: z
  26.    ├─ .....       , d8 L" J5 R# s+ R- P7 ]5 E, u* M
  27.    └──── main.c        main文件
复制代码

" F0 e9 S5 @6 O3 k/ N3 A: C4.2 工程设置要点

1) 设置使用微库:

J{@]PI_A)431TG@)75W{_CX.png

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

Z2X3(U{9WKNBTW`PJ@9{P3K.png

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

4.3 最终效果

按图输入一下指令,SHELL平台会回复相关信息。其中输入“led set 0=1”会将信号1分配到物理LED0上;输入“led set 0=2”会将信号2分配到物理LED0上。这样用户编写程序代码时相当于拥有了超级多的LED信号可用,调试时序非常有用。

}S7`(NS`D2R$]Q]@3I_{O9U.png
5. 添加自己的指令脚本5.1 源代码示例

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

  1. <i>/*********************************Copyright (c)*********************************1 {- b+ A9 P5 ^3 \( }! X
  2. **                               ' P7 n3 s; ?7 X) G7 j$ [( U1 |
  3. **                                 FIVE工作组
    0 g$ p8 ]& i  k- Q
  4. **2 E4 n% _  N; f3 Y2 G
  5. **---------------------------------File Info------------------------------------
    : N3 R. t- N( z
  6. ** File Name:               shell_mcu.c4 X; I; r4 {. h; g7 [1 q
  7. ** Last modified Date:      2017/9/17 15:13:575 Z6 f, {7 ^1 u1 A1 B( v
  8. ** Last Version:            V1.04 F) G$ L2 J9 F. E* g( @
  9. ** Description:             shell测试# u8 N) c1 G2 g
  10. **
    ( g+ e& S( b( F
  11. **------------------------------------------------------------------------------
    * g4 R* F  |7 C8 q7 k: C
  12. ** Created By:              wanxuncpx
    $ h9 D4 I; A7 n3 q4 B
  13. ** Created date:            2017/9/17 15:14:081 F. @6 g* U9 U4 c2 V& q+ d3 L' ]
  14. ** Version:                 V1.0
    7 v! d6 ?. l* R4 b& @9 K
  15. ** Descriptions:            none
    4 z+ O# u+ y5 N6 G) f7 `. b
  16. **------------------------------------------------------------------------------
    9 I; C" l1 H. A
  17. ** HW_CMU:                  STM32F103
    8 t3 @1 F% H, U4 I1 I
  18. ** Libraries:               STM32F10x_StdPeriph_Lib_V3.5.0% @6 L4 e# ]' A9 p
  19. ** version                  V3.55 ?0 z) Q/ i6 N( ^$ Q  Z. o
  20. *******************************************************************************/</i>: Z8 Z! j  f/ c) [" h

  21. + m) E) O+ \0 o) g+ r! ~( g% |
  22. <i>/******************************************************************************
    0 B% I7 t0 e; a
  23. 更新说明:: E7 _9 ?8 V! Q, B* m
  24. ******************************************************************************/</i>8 r, L# [- y( m6 Z+ u- ^

  25. ; J3 c6 b! Z$ J! z. Q
  26. <i>/******************************************************************************0 ?! d5 U: t# b  t+ n
  27. *********************************  编 译 控 制 ********************************
    & ]5 i' Q- W  R. p. W* w2 i" P
  28. ******************************************************************************/</i>
    - M7 I1 K5 ]4 j7 Y% J+ ]# X( F
  29. #define MCU_SHELL               //注释掉时屏蔽iap shell功能
    " a1 u  E8 _% R$ _5 R7 C& t0 a

  30. - Q6 l8 a8 D# ~
  31. #include "xc_shell.h"       //Shell支持文件,含bool,uint8_t..以及串口数据收发操作
      h9 s1 S4 C; @+ E9 @6 b
  32. <i>/******************************************************************************' u7 k6 m- M+ U' H" q
  33. ********************************* 文件引用部分 ********************************
    $ @. H! E7 r& t3 X: k9 d
  34. ******************************************************************************/</i>  D2 G* h6 q/ ~& f- V5 U% b& O
  35. <i>/*---------------------* % D7 L1 H: L" ?$ g0 O4 K
  36. *     模块驱动引用; Y( h5 v9 ]( q# l! K) r; f
  37. *----------------------*/</i>
    * s! b/ b# h8 ?3 R  {
  38. <i>//#include "net_w5500.h"</i>
    ) v: K# ]8 h* v  w
  39. , q) e  `! I0 E4 @1 t
  40. #ifdef MCU_SHELL  h7 e% l1 {! n3 x7 x5 ]
  41. <i>/******************************************************************************" M3 f6 O1 E& a" |- s9 v
  42. ********************************** Shell实例 **********************************: {0 M4 \! `" o2 {
  43. ******************************************************************************/</i>  U5 O5 J! A8 F. w
  44. <i>/*---------------------*
    & o" S# q- E2 [: q/ l
  45. *      CLI指令服务5 D# M0 s/ r  i# P% p9 I9 K
  46. *----------------------*/</i>5 c. j& Q0 m" v; e
  47. extern bool Shell_MCU_Service(void * pcBuff, uint16_t len );
    # b; x+ i- r$ i

  48. & v4 ?2 R) Y# t- B* Y
  49. <i>/*---------------------* & V. ]# z* u! v, W% z& R
  50. *       CLI 结构" f+ i$ b; s) x/ l% T4 K
  51. *----------------------*/</i>
    - F3 @' g# n+ @
  52. const Cmd_Typedef_t CLI_McuMsg=
    ; B7 h! J" L# Y/ ?  J& `& u3 }/ M
  53. {. T: J. @- d, v
  54.     <i>//识别关键字</i>
    6 n1 S, [' W) ^) R$ ]$ G! x
  55.     "mcu",
    6 _. b: o3 Y( r, v. {& O! p0 C
  56.     0 i" n: J! R8 C/ {) K- h2 u) A
  57.     <i>//帮助内容</i>
    ' S1 }7 f4 r! P' a
  58. "[mcu contorls]\r\n", T1 [* _2 `$ P4 n
  59. " mcu rd <d>\t\t- Read FLASH information.\r\n"
    ! L5 Z* V0 ]6 \
  60. "\r\n",: o! D: T& F- r6 {# Q" f" u
  61. / j6 O8 C+ ~# X8 w- E( x  _
  62. <i>//处理函数</i>
    4 f4 `6 ?9 C6 ~- @! O
  63. &Shell_MCU_Service,/ h7 L4 ]7 ?' l$ T" z( p+ Y

  64. 5 I% T% V; E1 X7 o5 F
  65. <i>//附带数据</i>( o9 D8 S: W; r' {0 X- V1 X$ w
  66. 0," H6 b" E/ I) X4 H5 t
  67.   #ifdef SHELL_USE_YMODEM  0 v4 }$ W- }& ~2 d/ U2 c* Y+ O
  68.     <i>//存储介质</i>9 K- [1 n$ N/ Q; a
  69.     NULL,
    % Q9 w! A4 ]% x1 J# g
  70.   #endif
    0 z8 {. r) |# i" T" K: j
  71. };
    " ]3 q1 e% j* l3 A# G  J

  72. 0 J, H; w/ I1 f7 o: {7 g9 o
  73. <i>/*---------------------*
    0 l) O# L: e" K$ b$ c
  74. *     CLI链表节(输出)- `' x4 i4 \, {* F. c
  75. *----------------------*/</i>, ~9 R: G5 ^9 o
  76. Cmd_List_t  McuList  = {&CLI_McuMsg      ,NULL}; <i>//IAP指令链表</i>( ^' m1 Q# J" Z  s, U1 \
  77. # q- o3 `5 [3 \7 D1 c; Q$ `
  78. <i>/******************************************************************************4 M" d6 b/ l5 a3 y" Q% ~, k
  79. ********************************* 函 数 声 明 *********************************
    8 v7 e$ A( a0 P: }; W5 H
  80. ******************************************************************************/</i>; X0 K, P9 M4 }1 c9 P
  81. <i>/******************************************************************************
    - R7 P; U- _8 }+ z. E/ ^9 Z% o, ]
  82. / 函数功能:STM32F103控制函数
    & n- Q9 Y4 ^% @0 o- o7 T
  83. / 修改日期:2015/7/14 20:22:02
    9 v* v- t! a8 X1 T+ c: K  q
  84. / 输入参数:none2 w. R8 j9 v& w8 n6 u! D# m
  85. / 输出参数:none8 N! V4 w5 T! q- N4 \3 I( `3 t
  86. / 使用说明:需要执行约10s
    ; R  c% _2 c% y2 p
  87. ******************************************************************************/</i>5 ^4 v5 V+ l) V" Q/ _
  88. static bool FLASH_ioctl(uint8_t cmd,void * param)0 o7 W. f' M' X: o
  89. {0 r, W1 I$ H( l9 `6 y
  90.     #define UID_ADDR            0x1FFFF7E0  //闪存容量寄存器,值对应KB单位' T' d' ^. c( ~/ Y/ \: \
  91.     #define MAC_ADDR            0x1FFFF7E8  //MCU的唯一ID号,共12个字节
    5 ^% M) f6 M4 a" m$ o) m0 y) i7 V0 P
  92.     #define UID_SIZE            2           //UID的字节数8 }( |2 E8 s0 ?4 T
  93.     #define MAC_SIZE            12          //MAC的字节数$ g+ `* i, e' V% q0 C

  94. 9 ^& s) P0 e4 J& Q
  95.     <i>//step1: 检查参数</i>
    & c& H; p' E, C; X! L! d
  96.     if(!param)return false;
    4 ^7 v' x. p1 S. {4 e; N7 J; C
  97.         
    * s5 _& p  y1 k( f- m' `  B5 a/ E; x3 M
  98.     <i>//step2: 处理数据</i>
      A- n2 R5 L4 [
  99.     switch(cmd){
    9 v- |+ _% X1 {; N
  100.       case 0 : {       <i>//获取FLASH的的UID</i>
    0 J- w" o  K) e: I
  101.         uint16_t * ptDst = (uint16_t *)((uint32_t)param+1);, u4 n  ^! p  O2 {
  102.         : q$ t8 D3 U0 n$ n( ^- ~) ~7 {2 t! i7 Y
  103.         *ptDst = *(uint16_t *)UID_ADDR;9 }* q5 o" u  |( O- i
  104.         *(uint8_t  *)param =  UID_SIZE;. W- T& ]$ A- |  B: M+ ~0 g' V
  105.         return true;( D. {8 q* C# w; V- s6 Z" B% @; S
  106.       }! @7 X# ]9 k& K
  107.       case 1 : {       <i>//获取芯片的MAC地址</i>
    4 A7 f# {, U" M
  108.         uint32_t * ptDst = (uint32_t *)((uint32_t)param+1);7 U( E) h; Z+ o
  109.         uint32_t * ptSrc = (uint32_t *)MAC_ADDR;
    & y3 w; A; G, B( T8 x0 ]
  110.    
    5 U- S/ ~. f3 r7 Y# E5 }, |
  111.         *ptDst++ = *ptSrc++;' P: `/ J2 c% C9 r
  112.         *ptDst++ = *ptSrc++;! A1 c) g8 J9 F/ a& X
  113.         *ptDst++ = *ptSrc++;. L- E7 I$ T  V$ m( y
  114.         *(uint8_t  *)param = MAC_SIZE;, L5 Z. O, G% {
  115.         return true;' u1 Z5 g4 W% J# E" o! n- [7 M
  116.       }
    0 h% z6 J( n6 s' p
  117.       default:return false;
    + H$ g# k! j; C0 x
  118.     }, o2 A% T7 d. O; q3 O! o' F! ^
  119. }
    * m8 Y  ^; s3 J

  120. 9 b5 X1 Y! ?) |7 S' t# S) A
  121. <i>/******************************************************************************
    + U8 e1 y& Y# |
  122. / 函数功能:文件系统Shel指令处理  _, l9 V# ]$ C; T6 E6 w9 x7 R2 c
  123. / 修改日期:2013/9/10 19:04:15
    1 ?2 K$ F& y9 }
  124. / 输入参数:输入当前的程序版本
    9 g& l7 V/ R; N! |( X
  125. / 输出参数:none
    $ _8 |( N) z2 h3 e8 ]
  126. / 使用说明:none
    : ^( m7 v: y( p! |% ^" f2 F
  127. ******************************************************************************/</i>6 ?' z5 D* O/ N, @) X- M
  128. bool Shell_MCU_Service(void * pcBuff, uint16_t len )
    4 j1 }3 E5 |" X
  129. {
    6 ^8 |" M( B7 z1 _/ h4 u1 p
  130.     uint8_t    *ptRxd;          <i>//用于接收指令处理</i>
    ) {& B- n$ I2 g& [4 w
  131.     int         i;
    2 d% J: U9 G% z4 a# i  b7 M2 s
  132.     uint16_t    retval;) \1 U  q+ S: Z4 I( |- Z4 M+ a
  133.     uint8_t     buff[32];' y1 i" z- S, f' ?! u- @* m
  134.    
    1 M. p4 f; j( p( {: Z" x
  135.     <i>//处理指令</i>2 P5 y4 D7 U* _" C
  136.     <i>//--------------------------------------------------------------------------</i>/ K' m/ F6 r# }: A
  137.     ptRxd = (uint8_t *)pcBuff;
    3 [/ f0 K$ L2 t! M* I* K
  138.     3 Q/ h' @% Y8 ~, t6 Y- D
  139.     if(StrComp(ptRxd,"rd ")) <i>//读取FLASH信息</i>
    + n* \8 d! E! X3 r5 H7 ?  ^3 |
  140.     {
    ; ~2 A, C, h2 I9 M
  141.         int wval;: y' D, U9 L/ f
  142.         7 ^4 e# r: A1 I& b, ]2 V
  143.         if(1 != sscanf((void *)ptRxd,"%*s%d",&wval) )return false;
    7 e  ~; X2 z  e% U' g( c
  144.         if( wval>2 )return false;
    ; N0 H) u6 ^, v! k
  145.         if(0==wval) {: ~* @) {1 h) p4 q) ?
  146.             FLASH_ioctl(0,buff);8 }% i8 ]+ j8 T1 a9 d' D
  147.             retval = *(uint16_t *)(buff+1) ;
    1 b8 S- E" a* z. n6 x
  148.             printf("->Flash:\t%dKB\r\n",retval);
    4 k+ g2 W7 ~+ G0 A: x3 d
  149.             return true;+ v' G4 @7 A! r! `/ k
  150.         }: Q( |4 y6 S, h* \0 M* d6 q, I0 \
  151.         else if(1==wval) {/ G& ]* C2 @" t; S% e% r$ o8 t
  152.             FLASH_ioctl(1,buff);
    / K1 v) C. m: Z& j2 G# s5 d' Y
  153.             printf("->MAC:\t ");
      e; n. f$ J6 L7 E; x: y
  154.             for(i=0; i<buff[0]-1; i++){printf("%02X-",buff[i+1]);}2 C5 x$ [# H  j1 G4 s& _0 M/ ]
  155.             printf("%02X\r\n",buff[i+1]);
    6 n+ v) Y$ C1 f* M) B% K! ^
  156.             return true;
    # ?5 P( c6 S( }+ V+ G' r# U, X
  157.         }: H; k2 X+ y: f' m6 j6 B, E
  158.         else return false;
    7 I/ j  h; y# T0 C+ `8 t9 H
  159.     }
    ; [: h$ j/ i; S" W
  160.     else if(StrComp(ptRxd,"help\r\n"))      <i>//指令帮助</i>' m; N" u! V/ `$ E& c
  161.     {" T  @1 [4 Q+ f
  162.         shell_SendStr((void *)CLI_McuMsg.pcHelpStr);
    % e& h1 S) P; h6 n; i: j2 W
  163.         return true;' h6 M$ M, {) u, L+ a) P
  164.     }0 [$ y  }8 A5 |, w1 [8 k+ O; K
  165.     else return false;' g0 w# ?$ o1 H' w
  166. }4 I- M/ b- a! R; {/ i
  167. - x, B1 |' Z; M# W* r# R/ K
  168. <i>/******************************************************************************: y0 R" i4 u/ J" A6 l
  169. ***********************************   END  ************************************
    1 F( r. |  p7 ?1 k
  170. ******************************************************************************/</i>
    . N) S% S4 q1 x& y3 K
  171. #endif
复制代码
! I2 m5 s" k" V8 v, F& ~
5.2 实现步骤

1) 将该文件添加到工程下。

2) 在main.c中用extern 引用McuList,源代码为:

  1. <i>/*---------------------* ' J) q# w- ^- i3 L2 u
  2. *     Shell指令链表
    4 [' q, `2 E9 \" x1 Z& y
  3. *----------------------*/</i>
    / Q" R: K/ n/ A# k7 C3 v+ ]! A/ m1 v
  4. extern Cmd_List_t  McuList;
复制代码
6 {! Y3 _$ B" m1 C2 T! O

3)在main.c初始化时添加:

  1. <i>//----------------------------------------------------------</i>- L- w1 L5 ^; Z- f/ a
  2. <i>//step1: shell初始化</i>3 u0 T; u# r, ]( h) r! l& N* c
  3. shell_Init(115200,ledx_cfg);        <i>//初始化shell接口</i>
    0 ~1 G% Q* F8 x( k1 i
  4. CLI_AddCmd(&McuList);     <i>//添加模块指令到链表</i>
复制代码

" ^9 }0 _3 W. ~0 y# _# L( X

4)编译工程文件。

5)下载到开发板运行即可在终端下看到新支持的CLI指令:

]8CYLJBFL{SSIG7D7`T.png
) b1 f+ f& B0 a( n4 r3 O+ \

7 B* a1 l1 r" p) r* O( y. Z+ F/ L5 K% P
收藏 评论0 发布时间:2022-1-5 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版