本帖最后由 黑皮男 于 2017-5-24 19:29 编辑
- ]# }# U6 h% y+ z/ b* Q" y$ Z' Q5 p d
基本情况: 手上已经有了好几块STM32,NUCLEO_F303,NUCLEO_L073,NUCLEO_L476,NUCLEO_F412。感谢社区,收集了这么多板子,满满的幸福感啊。之前也通过串口和NUCLEO进行了交互,但是在后续调试的过程中发现问题很多,经常死机。由于当时码代码水平有限,也就只能那样了,随着逐渐的深入学习码代码,相比之前来说,可以实现更多的功能了,也能更容易的理解各位大咖写的代码了。现在再来发表一片试用的帖子,这次不是使用一块板子,而是两块,L073和L476。所搭建的代码同时支持这两块开发板,实现了串口命令行。先来张效果图, [$ v) x3 Z$ a& F& c1 ?
# N9 v, q+ P, b代码结构:% r- ~8 `8 A: M4 N4 ^2 L
ecode2 |6 `$ O) K4 H* z* C1 l
|-common
$ V* }9 O9 z$ H |-drivers
( `# g' D) L4 R$ e2 l |-library& B% k* `. z* c9 u
|-OS
' K2 l2 R" T/ b2 r |-FreeRTOS
$ b6 B" K" f4 @- X ~ |-platform0 j8 G" Z: G4 A! Y5 q$ G
|-targets
% l$ i) b5 [7 k+ [# N; F |-TARGET_STM32L0, ]$ b4 T- ]6 u7 f
|-BSP' M9 A% O- U, ^3 a
|-CMSIS0 [1 A8 A x6 f# m
|-common5 e/ }: t, K% g! l& n6 _+ N
|-NUCLEO_L073" ]' o; H6 I9 H5 A( M
|-STM32L0xx_HAL_Driver
3 b d/ Y9 t# Z |-TARGET_STM32L4
& [7 [/ z7 \. W |-BSP
, @6 p7 S ^! w' Q3 s |-CMSIS
' n4 P: H- Y* p7 R0 E, a- J |-common
! f, r* V- r+ Q) C0 C* a% u( P. J |-NUCLEO_L4761 a) c% @7 @* d& G
|-STM32L4xx_HAL_Driver
+ D; J2 x: p$ v9 C8 G
3 W* _) F3 O. W |-user) p' m7 E% V1 L4 z+ Z, P
以上列出了主要的代码目录,借鉴了一下mbed,整个target来决定目标板。target目录主要是对不同的目标板进行封装,然后提供统一的接口函数。1 o8 o( }7 E2 t
所有平台相关的代码都在platform目录中,目前实现的功能有命令行,pwm,serial,timer,platform_driver。像mbed这样的软件平台提供的接口函数很友好,所以这里也借鉴了一下,例如pwm功能,有period_us,period_ms,period_pulsewidth_us,period_pulsewidth_ms这样的接口,对于使用很方便,虽然都是借鉴,但是这也是一种进步,看的多了,也就慢慢会写了,以后就会慢慢行程自己的习惯。
: Y& ?( g8 @' q h. m 此外不得不说,前人都趟过不知几遍浑水所总结的经验,真的没有必要自己再从头走一遍,拿来用,这样才能更快的完成新功能,这次所完成的命令行是基于双向量表来完成的,这里借鉴了一下linux平台下的list实现方法,真的是太经典了,自己之前写了一些简单的链表结构,感觉很混乱,还是大咖们写的经典啊。/ j, d: u0 ]0 ?
命令行的实现: `! I5 l9 X4 z$ ~7 F
命令行其实就是对一串字符串进行解析,然后根据解析的结果找到对应的函数并执行。这个就是最基本的思路。
+ [3 ]0 `8 L6 \1 F4 R! q- s 实现命令行可以分解成,字符串输入,字符指令和参数解析,命令匹配和执行这几部分。4 A7 }3 l8 @; `: l, u
先看一下命令行的结构体,+ l" U- M* y5 h. Y; {6 u, c' I
- struct ecode_cli_dev{3 q% d; G f" j! N) ^3 G2 x0 D) l
- struct list_head cli_entry;//强大的链表功能由此实现
" C) H. Q1 B) i* A3 u0 q - const char *name;5 C5 _# ~ P3 E- J
- int rxlen;" E8 b8 m4 f' n5 ]# Y1 h
- char rxbuf[CLI_BUF_SIZE];, Y# [7 N7 J& V* h& [8 h
- struct stdioex_device *stdio;//由此获取数据的输入输出句柄
1 b. i4 i# [% J3 F0 q - int flag;
' `$ o: j" \) A/ q7 Y - void *private_data;//一些私有数据,尚未用到, x4 q- B5 O+ r _: u: y, y
- };
复制代码 然后是命令的结构体* [3 F9 X! Q m7 e0 a. ~
- struct cli_command{9 w6 G# }, v9 |& [6 y& ~: f
- const char *name;
' A1 m% w d' b - const cli_command_handle_t handle;* |% b/ g" p5 w n: z
- const char *help;' V& O6 I& o. \4 @
- };
. ] I" H8 d+ H$ T- z5 U! i9 o - _7 r$ f$ I5 G
- struct cli_commands_list{" S$ N$ d# n1 P& Q& T4 W. o
- struct list_head entry;//强大的链表功能& c) e8 v' b. J# I
- struct cli_command *commands;" V' U# g' p6 A( d5 t2 a: \
- };
复制代码 $ g9 e. p, X- ~. \3 a/ g
p* s: U$ m# n) H# r
接下来看一下命令匹配部分,(又开始贴代码了 ),list_for_each,强大的list由此开始,首先是串口数据接收,接收完一行数据后,解析出指令的命令名称和参数,命令名称传入此函数进行命令匹配,如果命令名匹配成功则进行执行相应的命令。这里的每个链表节点都是指向一个命令数组,每个数组中都是不等数量的命令。
7 c5 y) v+ S! {+ d- struct cli_command * ecode_cli_match_command(const char *name)
5 l3 ^5 l9 N4 s" b& S6 A) ^ - {
1 x7 S3 F, |7 w - struct list_head *commands;
, ^1 }( k( v% G% r# a - struct cli_command *command=NULL;+ i/ g" ?9 D$ b9 w
- ( R5 ]% e% t3 J4 W1 t
- list_for_each(commands, &cli_commands_head); E; l2 L1 F U( G, b9 l+ i0 U4 w$ ^
- {
- ^8 d9 n; y% c( [+ E | - command = ((struct cli_commands_list *)commands)->commands;7 L% l* ^: n4 x+ O% n. d3 I. b
- if(command!=NULL)+ w& |2 C$ D6 ^# T3 v/ i2 k
- {
8 r# N- A! R, m# R - while(command->name!=NULL)2 Y6 V# \4 j. b; D3 U; [3 [
- {( g, b( L6 x9 ~6 f
- if(0==strcmp(command->name, name))
H; h K( N1 S% r ~. F - {
J. d/ u3 ^2 }7 x3 l - return command;3 s& w' x* H1 R! E! i# H: b
- }- _% ^3 r+ X5 H! i7 b2 o/ L
- command++;" Z4 h4 z4 B3 i. y2 Z% _5 @
- }- m0 t* a. ~4 D
- 8 U! H) `# d( C* U! F9 j
- }
: o9 |* P3 g- N8 V0 I2 N) u - }
" h+ x m# w2 k' h' |3 |- [ - return NULL;
, I0 ]8 v+ a4 T; T3 I - }
复制代码
2 w' Y3 L2 @8 e4 y$ }+ P1 z: \, A3 r! t8 `4 J; {
完整的代码放到了github上了http://github.com/ArnoYuan/ecode,有点大,就不上附件了,剩下的代码也不一一介绍了。
6 ]+ B2 d$ F$ n' v) k# N5 w K
6 c! Q6 {$ W* W; g9 K非常感谢QianFan (相关gcc+makefile编译的帖子https://www.stmcu.org.cn/module/foru ... 53&highlight=ubuntu,虽然是在ubuntu环境下编译,但是windows也可以搭建出linux的编译环境,需要交叉编译工具gcc,git附带的linux命令行和mingw的make),参考了其相关的帖子,支持了gcc+makefile编译,同时也能够使用printf,只不过nano.specs目前还不能使能,虽然我的makefile写的不怎么样,每次都会重新编译,但还是能用的。
8 O9 ^' Q/ \4 S# j( x" x# {
# J- r+ O1 b' W% W' \! n& C. _: c1 v; c& A T3 f: L8 j
& s) x6 }" j/ y; }1 f# g7 p1 h* R9 X6 e& V% w) t( @
|
这个还是有的,只是简单的回显,没做过多处理
其实uboot已经支持stm32了,可以弄一个
可以 考虑一下