前言2 E% K! `. ^4 \- d. W+ A5 t3 E
本文接着上一篇文章的内容带大家学习如何编写一个完整的LED代码。; ^8 u5 u2 X1 x' _7 N# v8 Y
; |; R9 J! R9 ^6 m8 p3 X9 Z一、头文件以及宏定义的编写4 T9 \5 T& q _8 O% P
led.c
0 F, ^6 Z3 K, s7 _
, M7 t+ j% h6 ~ i( x: a
7 ]! W. i* N8 L在led.c中我们只需要包含.h文件即可/ H h- D# L8 c$ H- A0 _$ V* K0 q
led.h
! k" w' x4 T& g3 c+ g' N9 g* r
6 @& p' H5 r! {- #ifndef _LED_H_
9 R. `( Y5 Z s% y - #define _LED_H_
4 L* e# [! j1 n" j7 K
6 o* Z! O; X; t! Y- #include "main.h"
' b/ I. B( U B* F/ ^% `5 Z
* y' N* l8 G, @: Y- #define u8 unsigned char6 F) L; _. `! U
- #define u16 unsigned short
8 t4 y! D$ W4 [. w, j! q - #define u32 unsigned int
c1 x- a$ a2 C1 ~3 y4 Q& E - 6 x d k2 O; T* X6 f
- //灯LED2的IO定义
. d* T# Q- C7 t7 d - #define LED2_RESET() HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET) //设置LED2低电平. F# F& U; G7 P8 ]& K5 P
- #define LED2_SET() HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET) //设置LED2高电平" Z5 r8 |5 r# v, r
- 2 L, z z( M; q: U6 W
- //灯LED1的IO定义1 o) O* T2 e, {. b( a3 U
- #define LED1_RESET() HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET) //设置LED1低电平2 s" @9 C) K5 n) a H* [
- #define LED1_SET() HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET) //设置LED1高电平
% V8 S4 _1 ? U3 n1 Y4 x
复制代码
; s8 L2 I- g( ?7 ^. Gled.h中的定义比较多一些,需要对LED的端口进行定义方便使用,移植时只需要改写后面的代码即可使用。
- J; v: H7 I R5 u. i还需要对常用的数据类型进行宏定义,方便书写代码。
) q4 J6 f9 M: z* c& c8 e+ N. D( T- z
% N1 X+ K" W' k# C+ M4 K K二、框架式管理代码的精华:结构体6 a9 F3 T1 N+ m+ E& ~5 f' h
led.h
, @) d5 L# q4 h2 D& f
9 { J1 X- Q \& v: Y- typedef struct/ F/ Q, `& ^0 j+ ~; E/ W0 y! Q4 W/ d
- {" |; r4 R' n# S
- u8 sw; //开关* W8 F: A7 g7 w3 s+ R5 |; L
- u32 pre; //周期
# s0 g& i8 `( w/ H7 W' O - : } w, }. c! R; c3 \ B4 T. E
- } BRE_t;& g8 ?1 F2 d4 P: O1 e& b
9 } ^7 _) d! k6 [# G% l( T+ }# m- typedef struct+ x+ |9 |- e/ W0 B1 q
- {! H! {" J/ `3 a, f: X3 g
- u8 sw; //开关
- u# x0 t) Q# F5 c4 g - u32 pre; //周期0 }. ~/ q7 X- V2 ?; j; d
- ; L" n7 N7 l* ] F7 P l1 U* @
- } BLK_t;; R9 p' U6 Y( J
( a. w( _. C" T+ K: `- typedef struct* I$ V5 T; A- v- o
- {' B$ t O% Q/ U) e$ b
- BRE_t bre; //呼吸灯
1 D5 h+ ^2 S; Q) U# w3 \$ [6 S - BLK_t blk; //闪烁灯) X8 F) `, ?; H, F- d8 H4 e& A# o
, S- U6 U/ T6 r X i- } LED_DATA;# A% n0 N5 l, a
- # g" U6 O! Y$ t" U5 K- m
- extern LED_DATA ledData; //灯属性封装
复制代码 ' Z& S" p* e$ x/ P% \
在led.h文件中我们定义了三个结构体,一个是管理呼吸灯属性的结构体,一个是管理闪烁灯属性的结构体。这两个结构体里面分别定义了开关变量和周期变量,通过修改开关变量可以改变LED灯的亮灭,改变周期变量可以让LED灯的呼吸频率和闪烁频率改变。+ s; D( C/ z4 I9 ^2 n5 k- e
最后一个结构体作为统筹管理的结构体,他里面定义了呼吸灯结构体变量和闪烁灯结构体变量,方便调试运行。
- Y6 l8 q% Z X0 O# ?; W% Y# o3 r% A0 k; Y
三、函数的编写0 @- _9 {! _+ ^
- void LED_Init(void); //初始化调用
; F3 U: E* N. b# t4 e$ T - void LED_Task(void); //后台轮询调用: s6 H) x B' d% y) R$ o# K5 Q6 U
- void LED_TIM_Handle(void); //定时调用
复制代码
' z# j5 p' y$ R E9 ^( v通常我们编写这三个函数7 M3 @- {! K6 B' a5 N4 D8 M% G) J
Init做一些LED灯的初始化比如开关的状态和周期的大小。3 P8 k( M1 l: Q4 m- {
Task函数一般放在while(1)里面轮询调用
$ O! g8 K! ^5 a! S$ y" l1 u1 WHandle函数则放在定时器里面中断调用: k; K% k1 m( R/ l
. J' C& I2 S2 i) ~! R, E
; ~- N9 a. ?" j" M
* b0 L% d- e( P7 {; D; G* Y |