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

【经验分享】实用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管理, 调试模式设置, 命令帮助指令, 复位指令等基础功能


    3 r8 F" @2 V9 ~! d( J3 [) N4 n8 s: Y

    $ M' ]! K2 j% Y

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

0 m! r- J$ [! G8 O

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>/*---------------------*
    * o: W+ }1 R: I" N$ F8 V
  2. *     指正函数定义/ {2 n: i; [! A' U4 f1 f
  3. *----------------------*/</i>
    , |8 \/ z+ h6 `  d1 \  @( \" T
  4. typedef void    (*pvFunDummy)(void);; O* v7 F1 V; P! z) G

  5. . I) Z+ X( f( l  L1 ^8 [( a( P
  6. <i>//输入整行,输出逻辑</i>
    & W- s- Z$ \* h8 I" q; {
  7. typedef void    (*pvFunVoid) (void);+ D5 ]2 P) L( v2 |& s
  8. typedef void    (*pvFunBool) (bool     bVal);
    ) D% T; u, p+ I3 w. x$ m
  9. typedef void    (*pvFunChar) (uint8_t  cVal);0 w6 `6 K# U" Y* x  C* w) {
  10. typedef void    (*pvFunShort)(uint16_t sVal);
    & `/ R3 W0 t7 I7 V- j9 j
  11. typedef void    (*pvFunWord) (uint32_t wVal);
    9 ^9 m8 }) e, I4 p5 H+ J
  12. ! r8 ]* W0 i8 |
  13. <i>//输入整行,输出逻辑</i>
    + h# q9 C7 Z6 y1 f( g
  14. typedef bool    (*pbFunVoid) (void);
    * N* g+ R  }3 {2 j# l- Z
  15. typedef bool    (*pbFunBool) (bool     bVal);
    & E4 z! ~' z6 f
  16. typedef bool    (*pbFunChar) (uint8_t  cVal);( z# L. K1 w' U" t  d& X7 B
  17. typedef bool    (*pbFunShort)(uint16_t sVal);
    & p3 n, H( e. i% x$ n9 X0 X' J
  18. typedef bool    (*pbFunWord) (uint32_t wVal);+ X3 z' ]4 ^) C3 n
  19. / x) i3 ]' b+ c
  20. <i>//输入整形指针,输出逻辑</i>- [3 l  G% \  g7 |
  21. typedef bool    (*pbFun_pVoid) (void * pVoid);
    - f* F  Y& M; {9 v5 T
  22. typedef bool    (*pbFun_pChar) (uint8_t  * pStr);7 O+ j# \' t: l% D( O  Q% q% V
  23. typedef bool    (*pbFun_pShort)(uint16_t * pShor);
    3 C6 o5 [4 d5 c2 A, S
  24. typedef bool    (*pbFun_pWord) (uint32_t * pWord);
    5 g) b. u! W& x6 E% D3 F

  25. , D$ p9 y- D5 Y* U, q* @
  26. <i>//输入数据帧,输出逻辑</i>8 h! A8 R* p+ D
  27. typedef bool    (*pbFun_Buffx)(void * pcBuff, uint16_t len );, e8 U' f6 J- i' T( ^) i6 S8 O+ R
  28. typedef bool    (*pbFun_Bytex)(uint8_t * pcByte, uint16_t len );( _" b8 y' ^4 r* D
  29. <i>/*---------------------* ( e# J; c( c* n+ z- ]4 E
  30. *    TTYx 句柄结构
    : l2 ~2 C- \% Q2 F( F9 m0 G
  31. *----------------------*/</i>% C3 V' M+ h, b0 a/ l
  32. typedef struct TTYx_HANDLE_STRUCT
    " b& v" u1 |3 i7 i% s1 E: b' R1 _
  33. {9 C! K$ D- h) K% U+ R+ N3 ]
  34.     const char  * const name;       <i>//驱动器名</i>" @, p+ r: a( T2 }3 R0 v# @
  35.     const uint16_t      rxSize;     <i>//接收大小</i>, `  A) ^- {/ T
  36.     const uint16_t      txSize;     <i>//发送大小</i>. ~+ z2 s, x  n4 u0 P4 w7 d, V
  37.    
    ; u2 W* z- v2 \9 u
  38.     <i>//------------------------------------------------------</i>
    ' w- e6 O( m9 r* b- N6 y  T
  39.     <i>//step1: 用户可用API</i>
    8 G2 q$ p' o8 o  K* f) t
  40.     const pvFunWord     init;           <i>//初始化.</i>7 j3 C# X; |$ B# A  N: F5 k
  41.     const pbFun_Bytex   api_TxdFrame;   <i>//发送数据帧. (发送帧)</i>: j6 x3 i' P: c
  42.     const pbFunChar     api_TxdByte;    <i>//发送数据字节</i>) `/ m. M9 n. Z: ~8 a, {3 {7 Y0 z. `
  43.    
    + g6 s6 A, U7 \4 E2 d) C
  44.     <i>//------------------------------------------------------</i>
    : a* V/ C7 c0 `: s3 q
  45.     <i>//step2: 注入回调函数</i>+ d1 O+ k; o% `# Z; |4 g
  46.     pbFun_Bytex         inj_RcvFrame;   <i>//(ISR)接收数据帧. (接收帧)</i>! h& Y4 F4 i2 r1 X  C, i+ Y
  47.     pvFunDummy          inj_TxdReady;   <i>//(ISR)发送完毕回调</i>
    ; V2 U! \) `, u6 `% v+ c
  48.     5 N9 Q2 \) G3 v$ q7 g6 ^  D$ X' ]
  49.     <i>//------------------------------------------------------</i>* E% m! p1 ^2 ^$ h
  50.     <i>//step3: 接收回调函数</i>$ @& k: Y; h$ ~. c. W' ~
  51.     struct TTYx_HANDLE_STRUCT * pvNext; <i>//连接到下一个指令 </i>/ h+ s. W: T2 L6 L
  52. }TTYx_HANDLE;
复制代码
可注入的命令脚本(CLI)实现, p. m6 a* c! b( b; B0 z2 P, q
  • 命令CLI也是一个结构体对象:
    0 X0 ~% d/ p3 T" u- t( g' b
# n  e' O# O( S7 `6 L+ q* ~% C

4 _5 o- k( _2 V/ _5 I  F, ~6 R* d
% e) M" R+ A  F$ q6 L& c& @
  1. <i>/*---------------------* - a, z7 j7 k  Y# G. ]/ \% N
  2. *       CLI指令
    / c! E- X) s. B: r  Z
  3. *----------------------*/</i>" ?; n" r  f! r) f! t* i
  4. typedef struct
    4 s9 H* ?# X' R+ [
  5. {
    ' A& V# e- h: E* i: o; h
  6. const char * const  pcCmdStr;     <i>//指令字符串(只能为小写字母)</i>
    - {* z6 W* C" @; X9 F
  7. const char * const  pcHelpStr;     <i>//指令描述,必须以:"\r\n结束". 比如:"help: Returns a list\r\n".</i>$ i# F6 ]. z% ]0 ?" e
  8. const pFunHook      pxCmdHook;     <i>//指向回调函数的指针,处理成功返回真否者返回0;</i>
    ! s" i5 ~8 k  v* h" \% P6 ]
  9. uint8_t             ucExpParam;     <i>//指令期望的参数个数</i>! I3 j4 V" P2 Z3 b% G' o! W7 G
  10. const MEDIA_HANDLE *phStorage;      <i>//指向存储介质,没有的话填充NULL  </i>- s. X* c4 z* I9 P
  11. }Cmd_Typedef_t;
复制代码
5 z: u: {* g; M5 b9 C& t$ n

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

  1. const Cmd_Typedef_t CLI_WizMsg=
    - g  i* S" ?; e, i+ x1 Y" r  X4 ?) E
  2. {6 E0 [. P* U, I/ V% y' }
  3.     <i>//识别关键字</i>
    & n$ X/ `# [3 N/ P# }+ J$ f
  4.     .pcCmdStr   = "wiz",
    & d. ^& n1 P9 h8 `" X/ A
  5.     <i>//帮助内容</i>: J1 c  p# }7 H/ E' R
  6.     .pcHelpStr  =
      h# R/ y' p7 s) U
  7.     "[WIZ contorls]\r\n"
    8 [) m) I3 t* O. F: @+ U: c- h( P  a
  8. " wiz help\r\n"
    . r* @* ], @" _5 x; b
  9. " wiz rd info\r\n"
    , S1 K4 e- n& P& G, b. i
  10. " wiz reset\r\n"( L+ A+ y' G7 s
  11. " wiz wr ip <D0>.<D1>.<D2>.<D3>\r\n"/ X7 g5 \# _8 n  f$ H8 `
  12. " wiz wr mask <D0>.<D1>.<D2>.<D3>\r\n"
    - C4 X6 o! ^+ Q6 @8 P! p$ n
  13. " wiz wr way <D0>.<D1>.<D2>.<D3>\r\n"% h1 K/ W7 T$ d6 r: ^
  14. " wiz wr mac <H0>-<H1>-<H2>-<H3>-<H4>-<H5>\r\n"
    % e& F* V! \% i" L7 B
  15. " wiz wr port <udp> <bak> <vol> <pic>\r\n"9 J. e2 X3 r8 p8 z0 Q
  16. " wiz wr sip <D0>.<D1>.<D2>.<D3> <port>\r\n"
    ' M! V) |# r3 r1 |3 k1 V
  17. " wiz wr cip <D0>.<D1>.<D2>.<D3> <port>\r\n"
    # K8 w. P; e3 e5 T+ F3 d1 E, U, f1 E
  18. " wiz load default\r\n"/ a3 J3 b1 M/ M$ K" j
  19. "[WIZ Test mode]\r\n"
    . K  s0 F) r, h  x/ N/ H; ^3 D
  20. " wiz loop open\r\n": ]) D: ~" F: @  c0 J& n
  21. " wiz loop close\r\n"
    0 O: K0 m0 y" E' {
  22. "\r\n",
    9 e9 j3 I% Q4 m. {& T$ g

  23. ( }2 N- p' d/ \9 G$ X% c# Q) {
  24. <i>//处理函数</i>
      ]( P" z( {6 t0 I2 F" ^- P5 ^
  25. .pxCmdHook  = &Shell_WIZ_Service,        <i>//见实体函数</i>
    + a9 `; X8 A3 `: L7 Z

  26. 4 d9 A9 _6 ?. q3 o
  27. <i>//附带数据</i>
    ! g( ]! v% K  ^
  28. .ucExpParam = 0,# U$ W) }6 w! X* u& e+ n

  29. 1 Y8 ]/ T5 ]" E' B: [6 N
  30.   #ifdef SHELL_USE_YMODEM  8 {" z$ C' P! a2 T& t$ M; A7 m
  31.     <i>//存储介质</i>
    ' M0 X8 g9 p& Q$ S+ n! g
  32.     .phStorage  = NULL,
    / G/ ~# Q" J4 e
  33.   #endif
    " g) {: K* j' N# Q2 O
  34. };# ~$ I# h9 E/ X5 }# O* J; _; T, y
  35. <i>/*---------------------*
    1 ?# X( Y( B( H" D+ C
  36. *       CLI 链表节
    ' t& O* @, e6 V1 @& Y
  37. *----------------------*/</i>  w: R. F% i0 t! r, w
  38. Cmd_List_t  WizList   = { &CLI_WizMsg,   NULL,}; <i>//Shell指令的头</i>
复制代码
0 Q  E7 |7 _  b7 \9 |

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

3. 环境准备
' Y% y0 F/ s1 n5 |$ ?$ a3.1 硬件开发环境
  • STM32F103系列开发板一块, 带USART1接口。
  • USB转串口线一根。0 [; H3 U7 Y& I3 x0 B8 _0 r9 O
    0 A  I8 D! T, D  R/ B1 [" b
3.2 软件开发环境
  • MDK4.72或以上
  • SecureCRT串口超级终端# [+ d2 `; b7 Q
    8 a6 d$ f6 f% [/ H) e; y; E3 Z
3.3 软件配置

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

4. 代码介绍
* B/ C  [+ s7 _! P; F5 A4.1 目录结构□ XC_SHELL
( `% W: Q7 y; C% t7 U
  1. ├──┬── BSP_LIB    BSP库,硬件相关驱动代买# `! }, P% x( G/ M# D
  2. │  ├──── bsp_ledx.c   基础LED驱动      
    2 E$ x( U/ J" E* F
  3. │  └──── bsp_tty0.c   调试串口驱动
      T/ B: P0 n1 B( o2 o
  4. │! M# u8 Q3 C' K* \" p. S
  5. ├──┬──MDK-ARM     工程文件1 Y5 h+ P! c" Z0 x2 b
  6. │  └──── Project.uvproj3 l1 j4 O& ?& V7 ^( t  }
  7. │
    + P1 |4 U. K7 ^. ?4 S4 l
  8. ├──┬──SHELL_CFG   SHELL配置头文件) H; c. e$ r4 R/ J$ e$ I
  9. │  └──── user_eval.h
    $ ~3 ^  N7 B8 p* \9 Y$ ^
  10. │
    ' n/ v# N2 Q2 O. ?7 o
  11. ├──┬──SHELL_CORE  SHELL内核文件0 y, D, u/ b* R" \2 M/ u! b& A
  12. │  ├──── xc_shell.c   SHELL内核文件
    ( g! |0 j. ]; H4 V+ B. v
  13. │  ├──── xc_ymodem.c  Ymodem传输协议(默认关闭,在xc_shell.h中启动)
    . a8 l2 J) b. |" E8 C
  14. │  ├──── xc_iap.c     Flash的IAP操作,需要bsp_flash.c驱动支持6 {' ^# Q% C) p" J% i& j) W4 e+ k, P
  15. │  └──── shell_iap.c  shell的用户脚本模板
    # b1 K: O" r$ @' D( Z0 ?: Y
  16. │
    2 @% l; @: E2 g6 p* c6 @
  17. ├──┬──SHELL_INC   SHELL头文件4 G1 `3 y6 H+ X( C
  18. │  ├──── bsp_type.h   驱动结构定义
    2 w4 U# L( g1 U0 p- p
  19. │  ├──── xc_shell.h   SHELL头文件: c7 r: }1 X6 b% \! D0 J$ J
  20. │  └──── xconfig.h    硬件无关配置文件0 R1 p; o0 v$ B# ]; Z1 l. \
  21. │6 X( y# Y3 x; k% G, ?7 }, S& K
  22. ├──┬──STM32F10x_StdPeriph_Lib_V3.5.0  STM32的标准外设库
    + y' t: d. W3 I( M6 x6 _; C
  23. │  └──── ......
    4 H( C& C4 o8 `, X
  24. │# p9 _- v" X. R- X
  25. └──┬──USER        用户文件   
      D" m# p1 V  ?) x
  26.    ├─ .....      
    8 I1 y" o' M; K2 n' D
  27.    └──── main.c        main文件
复制代码
% V0 R( Z6 [$ |
4.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)*********************************
    . @7 d+ n8 O4 g# d! ?
  2. **                                 g7 u: c& \- y
  3. **                                 FIVE工作组
    : L- \! D5 e* a, X5 o: D7 C
  4. **
    ) @* g+ R9 \3 G! j6 P; X* j
  5. **---------------------------------File Info------------------------------------5 w2 a+ F2 M/ o0 b
  6. ** File Name:               shell_mcu.c' e) M0 L; s9 M
  7. ** Last modified Date:      2017/9/17 15:13:57' ]6 g2 Q  L/ x4 q5 j$ \" Q" t
  8. ** Last Version:            V1.0
    & V# }& o! U: U5 s& A7 J6 i
  9. ** Description:             shell测试9 o. P* W1 ]! U" y9 Q) P- |
  10. **
    2 Y  c! \" I  e4 o& y/ `; f& q; l
  11. **------------------------------------------------------------------------------$ o( U/ Q; I; |) X* Q( h2 j) V
  12. ** Created By:              wanxuncpx
    $ H( U' `3 n  G& I" Z
  13. ** Created date:            2017/9/17 15:14:08
    ; H# O. ]" |; F; y% w
  14. ** Version:                 V1.0
    2 i# ^7 q1 R/ T& p. r
  15. ** Descriptions:            none
    " E8 x8 L0 w) D
  16. **------------------------------------------------------------------------------% R  A" m. ~4 N# ^9 T: Z
  17. ** HW_CMU:                  STM32F103
    1 |8 U/ @) m3 g  J& L- @
  18. ** Libraries:               STM32F10x_StdPeriph_Lib_V3.5.0
    6 b0 a8 n! ]: v# w: D- B1 p( H
  19. ** version                  V3.5
    / k7 Z' V. z) m: e0 R) M! o
  20. *******************************************************************************/</i>1 H. g& I% I6 f7 x+ g- e/ C+ p
  21. $ R0 Z  ]/ q3 g; v
  22. <i>/******************************************************************************
    - D6 \! _+ l! D4 N  w! n
  23. 更新说明:
    % E( K( `1 i: {0 @* _
  24. ******************************************************************************/</i>) ~" w) U  {! J4 ?* d

  25. # y* \. D7 Y5 S3 }' h- U5 O9 t. Y! p
  26. <i>/******************************************************************************3 z: ]: x/ X  E2 ^
  27. *********************************  编 译 控 制 ********************************& K, O% z6 A( x/ o5 E! j$ E
  28. ******************************************************************************/</i>
    : c  F9 B1 Q3 H! k/ s- |! h1 p
  29. #define MCU_SHELL               //注释掉时屏蔽iap shell功能% D! O& e- b0 w, o7 H3 r
  30.   L; o( j" t8 @8 ?" J' C2 Z
  31. #include "xc_shell.h"       //Shell支持文件,含bool,uint8_t..以及串口数据收发操作
      x0 H+ y. e  H5 W
  32. <i>/******************************************************************************4 t, p$ h- R- J$ n. p" \' z- z, \
  33. ********************************* 文件引用部分 ********************************
    9 c5 Y" h3 R% N$ U# I
  34. ******************************************************************************/</i>0 c; t6 T+ _6 A
  35. <i>/*---------------------*
    # Z; C4 C4 b$ c  Q) T& [) ^& n
  36. *     模块驱动引用
    ( M! M; L+ s" f! C! S; z
  37. *----------------------*/</i>- H# C: W7 k( _9 |9 f
  38. <i>//#include "net_w5500.h"</i>( C% L; d7 J3 F: K; _) {# y8 O+ n

  39. 8 H$ F1 ~, y9 K: b2 |
  40. #ifdef MCU_SHELL+ ^3 u) W) l! [- w9 D1 I
  41. <i>/******************************************************************************1 ]2 l# z( N+ x8 \* Y7 l; e8 F
  42. ********************************** Shell实例 **********************************
    3 K& P3 K  l, ?: D. h  w" A9 R" ~) a
  43. ******************************************************************************/</i>/ D$ H5 W4 v. U+ R2 t$ G3 O
  44. <i>/*---------------------*
    ; S$ }( J* r! N9 l
  45. *      CLI指令服务2 }5 Y$ x0 S3 G& x! j
  46. *----------------------*/</i>
    4 K" k) c- O4 J! g6 _8 L- i
  47. extern bool Shell_MCU_Service(void * pcBuff, uint16_t len );2 |; A: X* v" X$ e' u3 r& V
  48. 8 p3 e/ g2 F* w* n
  49. <i>/*---------------------*
    : x" {& W1 ~* e" x" x+ i, l
  50. *       CLI 结构$ |* L: l  b# i& k/ }) U9 n. ?
  51. *----------------------*/</i>
    + {7 t" u# x8 g7 V# S2 s) j
  52. const Cmd_Typedef_t CLI_McuMsg=
    $ C6 K0 S9 P! N" q7 i& r
  53. {
    ; F1 x5 u. D. A1 g9 n$ m
  54.     <i>//识别关键字</i>. k+ p6 b  X6 b% P/ o
  55.     "mcu",( a1 Y8 n9 v9 G) z  E  ~
  56.     3 J. |* `+ ~+ f) m) B5 P
  57.     <i>//帮助内容</i>+ r6 S9 b& {( c
  58. "[mcu contorls]\r\n"
    ! L/ S$ a% U+ S( N
  59. " mcu rd <d>\t\t- Read FLASH information.\r\n"
    / S( h& J5 k: F4 X5 i/ @
  60. "\r\n",- R, d6 H" @, U/ ?9 I! h

  61. 0 H% \4 m4 F3 l/ ^
  62. <i>//处理函数</i>6 s  T$ u$ i7 X" F* w6 h+ s. [  n
  63. &Shell_MCU_Service," z% M; \" t' H0 Y% Q0 J$ Z: o
  64. - D+ Q9 X2 C" F+ `. }, @
  65. <i>//附带数据</i>
    4 `, x$ x5 {$ \( p( B
  66. 0,
    * G$ f) w/ o; a
  67.   #ifdef SHELL_USE_YMODEM  
    9 p- |* ]- M; {3 ~  }
  68.     <i>//存储介质</i>* A" |* M4 n- ~8 I8 F$ P# y9 F
  69.     NULL,
    ( j$ |- A1 x, J6 G! W  B6 X
  70.   #endif5 Y7 b% K& a3 K  T
  71. };) @3 z* B* w- R2 v3 ]; y6 n

  72. ; J+ O# x5 {  _5 m9 t/ E+ y7 ]
  73. <i>/*---------------------*
    . r& P! H' [6 }6 d7 x
  74. *     CLI链表节(输出): B2 ]& r5 c4 [2 v6 B' v" q
  75. *----------------------*/</i>
    8 @9 H3 z# O9 \; `3 \  Q0 d) v4 Y
  76. Cmd_List_t  McuList  = {&CLI_McuMsg      ,NULL}; <i>//IAP指令链表</i>3 f+ x& T2 T; F: F$ H7 K) _9 h  L
  77. 6 e3 B7 S. p3 w/ t9 @8 Z
  78. <i>/******************************************************************************
    ; h- c6 C) \9 H9 y- b% K$ N
  79. ********************************* 函 数 声 明 *********************************
    ! H8 O1 Y+ w& L  a9 y9 k" \
  80. ******************************************************************************/</i>
    ) y( g# C) u# U  A, I5 f# N9 c' S$ T
  81. <i>/******************************************************************************
    ( ~& v4 O/ G: d; c0 \
  82. / 函数功能:STM32F103控制函数
    + u' K1 _& ]9 _* c/ L! D
  83. / 修改日期:2015/7/14 20:22:02
    9 G1 p6 A# d- ?& o& v
  84. / 输入参数:none& g- m" ?, a: J) \1 m) Y4 M
  85. / 输出参数:none. H8 U' S4 O+ t& I! x8 l
  86. / 使用说明:需要执行约10s$ v: u% ^! X9 }" U
  87. ******************************************************************************/</i>( s5 W( |' J! Q6 N3 k
  88. static bool FLASH_ioctl(uint8_t cmd,void * param)
    ; j8 t2 k) A# {+ D& O, _& {
  89. {
    & q" V0 R. E0 F0 T2 [  E
  90.     #define UID_ADDR            0x1FFFF7E0  //闪存容量寄存器,值对应KB单位
    6 ]0 \* l) ?5 y! [9 i- ?
  91.     #define MAC_ADDR            0x1FFFF7E8  //MCU的唯一ID号,共12个字节0 \- s# c, {/ z  L6 t& {) R* F# V
  92.     #define UID_SIZE            2           //UID的字节数, X6 V3 q& |$ l
  93.     #define MAC_SIZE            12          //MAC的字节数5 l: z3 r$ Z8 o! a# \

  94. & l: s/ p6 D* J7 @# ^6 ~
  95.     <i>//step1: 检查参数</i>% E$ Z$ _8 \- q& O2 _
  96.     if(!param)return false;
    - a5 f. b" v$ W8 d: U, u
  97.         
    + e2 g  Q. j5 N8 b4 j2 q6 X
  98.     <i>//step2: 处理数据</i>
    ! H- n3 {* p5 S
  99.     switch(cmd){
    6 @$ J4 G) K( [0 _. Z) k6 _% K% R
  100.       case 0 : {       <i>//获取FLASH的的UID</i>
    1 h- K  |$ c0 _
  101.         uint16_t * ptDst = (uint16_t *)((uint32_t)param+1);
    1 t; O8 M* A2 t& @! j. U3 @/ S
  102.         
    8 U  G- g) c; t' A8 F) d7 `7 M1 u* H
  103.         *ptDst = *(uint16_t *)UID_ADDR;
    6 b2 i; ?" z1 \
  104.         *(uint8_t  *)param =  UID_SIZE;
    ! q% m, |* O' I' e' G$ P1 c: o
  105.         return true;
    8 O7 D% B) h8 [! j5 s
  106.       }
    * q# G, x) j4 h: Z  v$ T; \
  107.       case 1 : {       <i>//获取芯片的MAC地址</i>
      ?" n7 M4 ~8 V" `# }
  108.         uint32_t * ptDst = (uint32_t *)((uint32_t)param+1);- `- U; j7 Y- e+ E& i$ M: b$ W
  109.         uint32_t * ptSrc = (uint32_t *)MAC_ADDR;
    : F- a' f3 `( R4 p6 J- `5 B
  110.     % Y! ~7 `2 Q; |4 q' Y' ~2 ~
  111.         *ptDst++ = *ptSrc++;; L+ z6 V4 X* c
  112.         *ptDst++ = *ptSrc++;5 \/ {6 J+ Z- N; n
  113.         *ptDst++ = *ptSrc++;
    4 u( E* o+ P/ l5 ~  k/ I
  114.         *(uint8_t  *)param = MAC_SIZE;
    ! ^( h, e. Y) ]
  115.         return true;  S! K  B; N0 y7 J, R2 f
  116.       }. _8 q! ]. S+ }6 C  `1 i% N. g0 c
  117.       default:return false;
    ' w6 o1 O( _9 m  d
  118.     }8 r& r/ |3 ?7 g# q) ?: g7 G
  119. }$ S) t# I* n; G. _' u5 e/ V- V; {  N5 g
  120. ) C1 N0 x/ J) ]+ V8 C7 w
  121. <i>/******************************************************************************# i# t* g1 s1 \; R
  122. / 函数功能:文件系统Shel指令处理" u) V) w, B/ ~% }1 h$ t3 s
  123. / 修改日期:2013/9/10 19:04:15+ `: ^* E% L- i3 p) x# ^% W3 o
  124. / 输入参数:输入当前的程序版本
    + P2 Q0 f% L8 d+ j" e
  125. / 输出参数:none# C0 y  I2 f1 g* R% ?; M; w3 U0 e+ f: C
  126. / 使用说明:none
    3 t$ F8 u1 p- h1 g
  127. ******************************************************************************/</i>
    6 k( Y# w( o% B2 L0 n5 K
  128. bool Shell_MCU_Service(void * pcBuff, uint16_t len )
    6 l$ l3 y( z6 {1 j
  129. {( a. j0 Y8 [8 I6 x
  130.     uint8_t    *ptRxd;          <i>//用于接收指令处理</i>
    ! w  K: m# d( W' B( c+ M
  131.     int         i;! |0 l& _9 g0 m( H
  132.     uint16_t    retval;
    ; u; a5 _( f8 K& \9 Y% R* r( ]
  133.     uint8_t     buff[32];- A" Z9 E/ t+ A# d
  134.    
    . U7 ]3 O9 u% g9 C8 w" @
  135.     <i>//处理指令</i>8 F4 s9 X2 R. \
  136.     <i>//--------------------------------------------------------------------------</i>0 }" D, f3 p& F$ X3 e7 C
  137.     ptRxd = (uint8_t *)pcBuff;- M, ^: u1 O' z
  138.     ' B3 ~0 p& v. H' g- o+ L, ~2 z
  139.     if(StrComp(ptRxd,"rd ")) <i>//读取FLASH信息</i>+ @' G) X2 E3 p3 O9 j
  140.     {7 V7 z& m2 R- Q' I
  141.         int wval;
    $ S6 E) [# i6 L" \- T
  142.         
    : O8 r" p0 T$ k7 y+ f7 g
  143.         if(1 != sscanf((void *)ptRxd,"%*s%d",&wval) )return false;
    $ z8 t" Y+ G' f$ t
  144.         if( wval>2 )return false;
    6 Q( D. p1 r0 I, f3 r' l2 j- T
  145.         if(0==wval) {
    % H0 f4 Q. a6 k! g; y
  146.             FLASH_ioctl(0,buff);
    , K/ v% A" d+ @7 ], K
  147.             retval = *(uint16_t *)(buff+1) ;! `& v; w" x6 b
  148.             printf("->Flash:\t%dKB\r\n",retval);
    1 S$ I' H) ]3 o1 q- u' Z3 O
  149.             return true;
    4 C8 M9 T( F# i  a- ]" r2 o5 ?
  150.         }- ^% M* l( T5 w8 V8 W0 W
  151.         else if(1==wval) {& S" H/ e1 i" ~: {1 D/ p
  152.             FLASH_ioctl(1,buff);8 ~8 y, t$ C* U. y$ i4 A
  153.             printf("->MAC:\t ");: `6 W; Z* @/ v( n7 u
  154.             for(i=0; i<buff[0]-1; i++){printf("%02X-",buff[i+1]);}
    6 _/ v8 y' J7 Y
  155.             printf("%02X\r\n",buff[i+1]);
    3 M6 o; H3 i5 S3 `- A  [: E
  156.             return true;
    - y) n7 Y; K/ |
  157.         }
    ( t5 U! U. Q9 j' E: N5 ]
  158.         else return false;
    $ b9 n( ^; T) k% K# L) _: d
  159.     }. o6 |- p9 ^; R, n# R1 z
  160.     else if(StrComp(ptRxd,"help\r\n"))      <i>//指令帮助</i>6 y1 d) z5 q- B, h/ h7 t) l1 `" `& k6 s/ ^
  161.     {/ Z7 V/ R2 ~2 t
  162.         shell_SendStr((void *)CLI_McuMsg.pcHelpStr);
    " C. h' k4 g" E7 L
  163.         return true;, R" ]6 Z% I3 U: K, S4 C3 h7 M
  164.     }
    7 x9 u5 U, B8 B' v1 h
  165.     else return false;
    2 Z* u; c$ j6 Y7 x: L' v0 @
  166. }
    1 s/ @) l2 U. Y& K) ^+ ?, k
  167. ( H9 u7 ?% u5 g5 B% `" C
  168. <i>/******************************************************************************
    ) T7 T; f+ n! Y4 A+ x$ @# D% r0 ^; R% m
  169. ***********************************   END  ************************************1 A, H! B) o& F
  170. ******************************************************************************/</i>
    0 W9 Y) d7 \# D( X/ m. H" c' _# s/ E
  171. #endif
复制代码
8 V) P" m. p6 n; r1 Z, v+ K
5.2 实现步骤

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

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

  1. <i>/*---------------------*
    1 N  n. b1 Z' @  d
  2. *     Shell指令链表5 G$ D/ h/ Q9 a( E( L
  3. *----------------------*/</i>
    ; k# y8 q  z% F4 }' W. |* m5 F' F
  4. extern Cmd_List_t  McuList;
复制代码

4 X; I( |& W3 K" A5 K1 b" C

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

  1. <i>//----------------------------------------------------------</i>+ r1 g# \5 o; p0 U4 M" c9 K
  2. <i>//step1: shell初始化</i>
    5 z% N' f* _, Y3 ]. D) |
  3. shell_Init(115200,ledx_cfg);        <i>//初始化shell接口</i>
    6 ]/ I8 m' p" T+ Z8 Q
  4. CLI_AddCmd(&McuList);     <i>//添加模块指令到链表</i>
复制代码
  j# u: v1 H1 v, a8 `

4)编译工程文件。

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

]8CYLJBFL{SSIG7D7`T.png

! |% i, V: }6 k3 Z& F+ n
+ d3 H+ h" r- b/ L3 Q6 x# C# H+ d( A( ?: \
赞 收藏 评论0 发布时间:2022-1-5 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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