4 D6 `( ^6 F/ h! w; r/ m1 ?8 q! B3 d 当自己慢慢的可以独立写代码的时候,就会觉得已经学会了。特别是自己能独立完成一些简单的项目之后感觉自己可以出师了。慢慢的随着各种项目的锻炼,写代码的能力也会慢慢提高。写到最后就会发现,其实好多项目都是不同的代码重新组合,一个功能写好之后,在每个项目中都可以用。比如写好了一个串口功能之后,那个项目用到了串口,直接将以前写好的代码拷贝过去就完了,最后开发项目就变成了一个拼积木的过程。, c) M6 m; n8 o" P: R3 V
' P0 a' E* f5 |. D% r/ w) d8 `! V
这时候基本写代码好像就失去了最开始学习的激情,写代码就变成了一个体力活了,基本也不用动脑了,都是复制粘贴了。写代码的能力好像也很难在突破了,感觉到了瓶颈。这时候就很难找到视频或者书籍或者老师教自己如何突破这个瓶颈。此时如果想要自己的代码水平更进一步,要怎么做呢,下面我就将自己的经验分享一下。 + u; C: M- P/ X0 ^ j9 L; o/ Y
在自己写完一个功能之后,如果想知道自己写的怎么样,最好的办法就是找一个别人写的同样功能的代码去比较。看看自己写的和别人写的有什么区别。找代码的时候,不能网上随便找一个,因为你不知道你找到的代码是初学者写的还是高手写的。容易被误导,这时就要找大家比较认可的,代码风格比较好的去比较。我一般找到都是某原子和某火的代码。下面就通过一个简单的LED代码来分析比较一下。 - D, h0 a/ |! p3 u 9 Y3 G: r8 T4 L 首先看某原子的代码 4 h4 Q: N& D& {3 z/ m% L 5 p' w1 s0 t/ w! V, m# S 这是 led.h 的代码+ O, i- _0 w0 j6 d4 J# x
3 I3 X% |* L4 [7 i- q2 p' e
/ ^6 ^! ]5 }( f- ] 这是 led.c 的代码 3 K6 Q3 U9 F! q0 Q6 R, w 9 Z1 |9 M5 r) f6 l) a' j) x $ K$ Y/ X$ ?3 p0 P led.h里面用到的位操作是在sys.h头文件中定义了。 : V, O2 O* b- [4 }9 ]5 l% K" x4 k( s! @# Z8 U! X, P3 K
" A7 |- S' d! l# c1 K' t8 s
这个初始化代码看起来非常简洁,首先使能用到的IO口时钟,然后初始化相应的IO口。在初始化函数中一眼就能看出两个LED分别是PA2和PD8口。代码理解起来非常容易。 / F) s& u, i/ R+ B9 s7 C; a2 J! P 2 \/ G. k" l7 j) [5 M4 y6 x5 n 接下来看某火的代码 7 P9 G# c4 Y& X/ A" k& s5 ^6 q 头文件 bsp_led.h 1 Y0 e* a# t( k0 z! K D& n% K* c. Z8 Z- x$ Q1 a- |; w1 Z) p* x) w; [0 E
" Z( W) D6 T6 g4 M C文件 bsp_led.c, _5 t8 V4 e3 K4 Y) e
# K- |* t; F' S, _ M* k! J. T2 q2 b3 q5 N
7 y' {7 i& L$ R 首先从文件名字就能发现区别,上面的是led.h,下面的是bsp_led.h。前面加了一个bsp,这个bsp是什么意思呢?BSP即Board Support Package,板级支持包。也就是这个文件是和当前硬件系统有关的。然后在看头文件中的内容,发现在头文件中,把LED用到的IO口和具体引脚重新定义了一个名字。然后在C文件中初始化LED口的时候,用的都是新的名字。初始化的流程也是先使能用到的IO口的时钟,在初始化用到的相关IO口。但是从初始化代码中很难看出,当前使用的LED口是哪个端口。代码看起来感觉就比较费劲。2 H) s b6 d: O: a3 F
6 }8 S, a& P; y 为什么一个简单的LED功能,风格却相差这么大呢?这两种风格你自己的代码更接近于哪一种呢?从我自身来说,刚开始的时候比较喜欢上面的那种风格,简单明了,代码写起来很容易。但是随着写代码的时间增加,逐渐开始喜欢下面的这种风格。代码也由上面的风格逐渐转换为下面这种风格了,下面就分别讨论一下这两种风格的差异。 ; O2 R& H }5 v3 Y, b7 u4 D# e- V5 f
刚开始写代码的时候,第一种风格比较适合,写起来比较简单,容易理解,代码出现问题时查找起来也更加方便快速。但是随着项目的增加和需求的各种变化,就会发现,第一种代码修改起来比较麻烦,比如LED口发生了变化,那么头文件和和初始化函数都需要修改,变动一次要修改好几个地方,修改的时候容易漏掉有些地方,导致调试起来各种问题不断,增加了调试的难度。这时就想,能不能值修改一个地方,就能把LED口用到的地方都修改过来。此时就需要用到第二种代码的方式了。在头文件中将LED用到的端口和时钟都抽象出来,重新定义一个名字。在初始化代码的时候,初始化的只是是LED口,至于这个LED具体对应到哪个口,直接在头文件中定义就行。这时候初始化代码就不需要修改了。% S8 d# U& x: B }