LED 闪烁控制软件模块

来自谷雨文档中心
Erjin讨论 | 贡献2019年12月9日 (一) 16:25的版本 (led闪烁模块说明初版结束)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转至: 导航搜索

LED闪烁功能,作为常用需求。将其归纳为软件模块,与其他项目或工程共享原代码。

1 文件组成

功能模块由六个文件组成,分别承载不同作用。

文件名称 作用
bsp_status_led.c 对应用层函数进行定义
bsp_status_led.h 对应用层函数进行声明
ledConfig.c 对硬件操作接口进行抽象
ledConfig.h 对硬件操作接口进行声明
hal_led.c 对硬件接口进行定义
hal_led.h 对硬件接口进行声明

在LED闪烁功能模块中,用到硬件包括一个GPIO引脚,一个定时器。开发者需要根据自身硬件情况,自行选择相应的硬件。并将这些硬件按要求实现相应的函数。这些函数在hal_led.h与hal_led.c文件中进行声明与定义。

1.1 hal_led.h与hal_led.c

 1 /*定时器超时回调函数指针*/
 2 typedef void (*fnTimerTimeoutCb_t)(bool);
 3 
 4 //******************************************************************************
 5 // function declare
 6 /*Create a timer*/
 7 void HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb);
 8 
 9 /*Start timer*/
10 void HalLed_TimerStart(uint32_t ms, void *pContext);
11 /*Stop timer*/
12 void HalLed_TimerStop(void);
13 /*Pin init*/
14 void HalLed_PinInit(void);
15 /*Pin set */
16 void HalLed_PinSet(bool level);

各函数功能及形参解释说明,如下表所示。

函数名 解释
HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb) 创建一个定时器,且定时器能达到秒级的周期。

pFnTimeoutCb:是定时器超时回调函数指针

HalLed_Timerstart(uint32_t ms, void *pContext) 启动定时器。

ms:是定时周期

pContext:传入的参数指针,会在超时回调函数中使用

HalLed_Timerstop(void) 停止定时器
HalLed_PinInit(void) 初始化与LED相连的GPIO引脚,并保持LED灭状态
HalLed_PinSet(void) 设置GPIO的高低电平,即控制LED亮灭。

level:true ->LED亮

false -> LED灭

 1 //******************************************************************************
 2 // fn : HalLed_TimerInit
 3 //
 4 // brief: Create a time object for blink led
 5 //
 6 // param : pFnTimeoutCb -> the timeout cb
 7 //
 8 // return : none
 9 void HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb)
10 {
11 
12 }
13 
14 //******************************************************************************
15 // fn : HalLed_TimerStart
16 //
17 // brief: Start timer
18 //
19 // param : ms -> the timeout ,unit = ms
20 //
21 // return : none
22 void HalLed_TimerStart(uint32_t ms,void *pContext)
23 {
24   
25 }
26 
27 //******************************************************************************
28 // fn : HalLed_TimerStop
29 //
30 // brief: Stop timer
31 //
32 // param : ms -> the timeout ,unit = ms
33 //
34 // return : none
35 void HalLed_TimerStop(void)
36 {
37 
38 }
39 
40 //******************************************************************************
41 // fn : HalLed_PinInit
42 //
43 // brief: Pin init
44 //
45 // param : none
46 //
47 // return : none
48 void HalLed_PinInit(void)
49 {
50 
51 }
52 
53 //******************************************************************************
54 // fn : HalLed_PinInit
55 //
56 // brief: Pin set 
57 //
58 // param : level -> true -> open,false -> off
59 //
60 // return : none
61 void HalLed_PinSet(bool level)
62 {
63   
64 }

1.2 ledConfig.h与ledConfig.c

ledConfig.h与ledConfig.c是对LED闪烁模块的硬件进行抽象,即hal_led.h与hal_led.c中定义的功能函数。

 1 /*定时器初始化函数指针*/
 2 typedef void (*fnTimerInit_t)(fnTimerTimeoutCb_t);
 3 /*定时器启动函数指针*/
 4 typedef void (*fnTimerStart_t)(uint32_t ms,void*pContext);
 5 
 6 /*定时器停止函数指针*/
 7 typedef void (*fnTimerStop_t)(void);
 8 
 9 /*Led 引脚初始化函数指针*/
10 typedef void (*fnPinInit_t)(void);
11 /*Led 引脚高低电平设置函数指针*/
12 typedef void (*fnPinLevelSet_t)(bool level);
13 
14 //******************************************************************************
15 // Name : ledBlinkCfg_t
16 //
17 // Brief : 描述LED闪烁控制接口函数
18 typedef struct
19 {
20   fnTimerInit_t    fnTimerInit;
21   fnTimerStart_t   fnTimerStart;
22   fnTimerStop_t    fnTimerStop;
23   fnPinInit_t      fnPinInit;
24   fnPinLevelSet_t  fnPinLevelSet;
25   
26 }ledModuleCfg_t;
27   
28 extern ledModuleCfg_t  ledModule;

hal_led.h就是根据ledConfig.h声明函数接口进行定义的。

其中结构体ledModuleCfg_t就是对硬件层进行抽象。其中包括定时器定义,定时器启动,定时器停止,引脚gpio初始化,引脚高低电平设置。

1 /*led operate interface*/
2 ledModuleCfg_t  ledModule = {
3   .fnTimerInit   = HalLed_TimerInit,
4   .fnTimerStart  = HalLed_TimerStart,
5   .fnTimerStop   = HalLed_TimerStop,
6   .fnPinInit     = HalLed_PinInit,
7   .fnPinLevelSet = HalLed_PinSet
8 };

1.3 bsp_status_led.h 与bsp_status_led.c

这两个文件是开发者可以调用函数的声明与定义。开发者可以调用相应函数对LED闪烁状态进行设置。led支持如下6种状态。

 1 typedef enum
 2 {
 3   LED_STATUS_OFF,          //关闭
 4   LED_STATUS_ON,           //常亮
 5   LED_STATUS_BLINK1,       //闪烁1,周期200ms,占空比50:亮100,灭100
 6   LED_STATUS_BLINK2,       //闪烁2,周期1000,占空比10:亮100,灭900
 7   LED_STATUS_BLINK3,       //闪烁3,周期1000,占空比50:亮500,灭500
 8   LED_STATUS_BLINK4,       //闪烁4,周期2000,占空比5: 亮100,灭1900
 9   LED_STATUS_END
10 }eLEDStatus;

当然开发者也可以,根据自己的需求,对led闪烁状态进行修改。包括周期,占空比。具体修改的地方在bsp_status_led.c文件头部。各个闪烁状态由宏定义定义,如下。

 1 #define LED_BLINK1_PERIOD   200
 2 #define LED_BLINK1_DUTY     50
 3 #define LED_BLINK1_ON_MS    100
 4 #define LED_BLINK1_OFF_MS   (LED_BLINK1_PERIOD - LED_BLINK1_ON_MS)
 5 
 6 #define LED_BLINK2_PERIOD   1000
 7 #define LED_BLINK2_DUTY     10
 8 #define LED_BLINK2_ON_MS    100
 9 #define LED_BLINK2_OFF_MS   (LED_BLINK2_PERIOD - LED_BLINK2_ON_MS)
10 
11 #define LED_BLINK3_PERIOD   1000
12 #define LED_BLINK3_DUTY     50
13 #define LED_BLINK3_ON_MS    500
14 #define LED_BLINK3_OFF_MS   (LED_BLINK3_PERIOD - LED_BLINK3_ON_MS)
15 
16 #define LED_BLINK4_PERIOD   2000
17 #define LED_BLINK4_DUTY     5
18 #define LED_BLINK4_ON_MS    100
19 #define LED_BLINK4_OFF_MS   (LED_BLINK4_PERIOD - LED_BLINK4_ON_MS)
1.3.1 闪烁次数定义

在代码中,各个闪烁状态都有相应的次数限制。其中0表示此状态闪烁结束,将进行下一个状态,0xFF表示永久闪烁,直到当前状态被人为改变,即闪烁次数被置零,或改为其他数值;或被弹出。

1 #define LED_BLINK_STOP      0
2 #define LED_BLINK_FOREVER   0xFF
1.3.2 应用函数声明

在用户层提供了两种方式。一种是普通模式,一种是栈模式。

普通模式中,开发者只需调用LED_Set函数,即可对当前led状态进行设置。状态结束后,led处在灭状态,等待用户进行下个状态设置。而在栈模式中,开发者调用LED_StackPush函数时,会将led状态压入栈中,并设置led状态。当led闪烁状态结束后,继续之前led状态,直到栈空为至。当然在这个过程中开发者也可以调用LED_Set函数,对当前led闪烁状态进行设置。只是led闪烁状态结束后会继续栈的上个led状态,而不会继续LED_Set函数调用前的状态。

 1 /*initial led module*/
 2 void LED_Init(void);
 3 /*set the led status*/
 4 void LED_Set(eLEDStatus,uint8_t times);
 5 
 6 #ifdef LED_PRORITY_EN
 7 /*push the led status to ledstack.it will be placed at the top*/
 8 bool LED_StackPush(eLEDStatus,uint8_t times);
 9 
10 /*pop the top node from ledstack*/
11 void LED_StackPop(void);
12 
13 /*clear stack*/
14 void LED_StackClear(void);
15 #endif

其中与栈有关的函数是通过宏LED_PRORITY_EN来控制。

函数名 解释
void LED_Init(void) 对LED闪烁模块进行初始化。在任何函数调用之前进行调用
void LED_Set( eLEDStatus status,uint8_t times) 设置led闪烁状态

status:设置的led状态

times:闪烁次数

bool LED_StackPush(eLEDStatus status, uint8_t times) 设置led闪烁状态,并压入栈中

status:设置的led状态

times:闪烁次数

void LED_StackPop(void) 弹出栈顶状态
void LED_StackClear(void) 清空栈里所有led状态,并将led设置灭状态
  1 /*blink status*/
  2 /*
  3 {
  4   1.period  -> 闪烁周期
  5   2.duty    -> 引脚高电平占整个周期的百分比
  6   3.times   -> 闪烁次数
  7 }
  8 */
  9 #define LED_BLINK1_PERIOD   200
 10 #define LED_BLINK1_DUTY     50
 11 #define LED_BLINK1_ON_MS    100
 12 #define LED_BLINK1_OFF_MS   (LED_BLINK1_PERIOD - LED_BLINK1_ON_MS)
 13 
 14 #define LED_BLINK2_PERIOD   1000
 15 #define LED_BLINK2_DUTY     10
 16 #define LED_BLINK2_ON_MS    100
 17 #define LED_BLINK2_OFF_MS   (LED_BLINK2_PERIOD - LED_BLINK2_ON_MS)
 18 
 19 #define LED_BLINK3_PERIOD   1000
 20 #define LED_BLINK3_DUTY     50
 21 #define LED_BLINK3_ON_MS    500
 22 #define LED_BLINK3_OFF_MS   (LED_BLINK3_PERIOD - LED_BLINK3_ON_MS)
 23 
 24 #define LED_BLINK4_PERIOD   2000
 25 #define LED_BLINK4_DUTY     5
 26 #define LED_BLINK4_ON_MS    100
 27 #define LED_BLINK4_OFF_MS   (LED_BLINK4_PERIOD - LED_BLINK4_ON_MS)
 28 
 29 
 30 #define LED_BLINK_STOP      0
 31 #define LED_BLINK_FOREVER   0xFF
 32 
 33 #define LED_ON              true
 34 #define LED_OFF             false
 35 
 36 //******************************************************************************
 37 // typedef area
 38 //
 39 /*定义当前led工作状态信息*/
 40 typedef struct
 41 {
 42   bool    ledLevelFlag;    //true -> high,false -> low
 43   uint8_t ledPointer;
 44 }ledBlinkInfo_t;
 45 
 46 #ifdef LED_PRORITY_EN
 47 //定义LED状态的栈空间
 48 typedef struct
 49 {
 50   uint8_t stack[LED_STATUS_END];   //栈的最大空间
 51   uint8_t num;                     //栈当前含有元素个数
 52   
 53 }ledStack_t;
 54 #endif
 55 
 56 //******************************************************************************
 57 // variable define
 58 //
 59 
 60 static uint8_t ledBlinkTimesTable[LED_STATUS_END] = {0x00};
 61 
 62 static ledBlinkInfo_t ledInfo = {LED_OFF,0x00}; 
 63 #ifdef LED_PRORITY_EN
 64 static  ledStack_t ledStack = {{0x00},0x00};
 65 
 66 #endif
 67 //******************************************************************************
 68 // function define
 69 //
 70 /*定时次的超时回调函数*/
 71 static void ledTimeoutCb(bool level);
 72 
 73 /*获取led定时时间*/
 74 static uint16_t ledGetBlinkTime(bool level);
 75 
 76 //******************************************************************************
 77 // fn : LED_Init
 78 //
 79 // brief : initial led module
 80 //
 81 // param : none
 82 //
 83 // return : none
 84 void LED_Init(void)
 85 {
 86   ledModule.fnTimerInit(ledTimeoutCb);
 87   ledModule.fnPinInit();
 88   ledInfo.ledLevelFlag = LED_OFF;
 89   ledInfo.ledPointer = NULL;
 90   memset(ledBlinkTimesTable,0,LED_STATUS_END);
 91   
 92 #ifdef LED_PRORITY_EN
 93   memset(&ledStack,0,sizeof(ledStack_t));
 94   LED_StackPush(LED_STATUS_ON,0xFF);
 95   LED_StackPush(LED_STATUS_BLINK3,0xFF);
 96 #else
 97   LED_Set(LED_STATUS_BLINK3,0xFF);
 98 #endif
 99 }
100 //******************************************************************************
101 // fn : LED_Init
102 //
103 // brief : set the led status
104 //
105 // param : ledStatus -> 设置led状态
106 //         times     -> Led闪烁次数,0xFF 表示一直执行,直到下一次状态改变
107 //
108 // return : none
109 void LED_Set(eLEDStatus ledStatus, uint8_t times)
110 {
111   if(LED_STATUS_END <= ledStatus)
112   {
113     return ;
114   }
115 //  if(times == LED_BLINK_STOP)
116 //  {
117 //    return;
118 //  }
119   
120   ledInfo.ledPointer = ledStatus;
121   ledInfo.ledLevelFlag = LED_OFF;
122   ledBlinkTimesTable[ledStatus] = times;
123   ledModule.fnTimerStop();
124   
125   if(LED_BLINK_STOP == times)
126   {
127     ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
128     return;
129   }
130   
131   switch(ledStatus)
132   {
133   case LED_STATUS_OFF:
134     {
135       ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);   
136     }
137     break;
138   case LED_STATUS_ON:
139     {
140       ledInfo.ledLevelFlag = LED_ON;
141       ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
142     }
143     break;
144   case LED_STATUS_BLINK1:
145     {
146       ledInfo.ledLevelFlag = LED_ON;
147       ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
148       ledModule.fnTimerStart(LED_BLINK1_ON_MS,&ledInfo.ledLevelFlag);
149     }
150     break;
151   case LED_STATUS_BLINK2:
152     {
153       ledInfo.ledLevelFlag = LED_ON;
154       ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
155       ledModule.fnTimerStart(LED_BLINK2_ON_MS,&ledInfo.ledLevelFlag);      
156     }
157     break;
158   case LED_STATUS_BLINK3:
159     {
160       ledInfo.ledLevelFlag = LED_ON;
161       ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
162       ledModule.fnTimerStart(LED_BLINK3_ON_MS,&ledInfo.ledLevelFlag);
163     }
164     break;
165   case LED_STATUS_BLINK4:
166     {
167       ledInfo.ledLevelFlag = LED_ON;
168       ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
169       ledModule.fnTimerStart(LED_BLINK4_ON_MS,&ledInfo.ledLevelFlag);      
170     }
171     break;
172   default :
173     return;
174   }
175   
176 }
177 #ifdef LED_PRORITY_EN
178 //******************************************************************************
179 // fn : LED_StackPush
180 //
181 // brief : push the led status to ledstack.it will be placed at the top
182 //
183 // param : ledStatus -> 设置led状态
184 //         times     -> Led闪烁次数,0x00 表示一直执行,直到下一次状态改变
185 //
186 // return : none
187 bool LED_StackPush(eLEDStatus ledStatus,uint8_t times)
188 {
189   if(LED_STATUS_END <= ledStatus)
190   {
191     return false;
192   }
193   
194   if(times == LED_BLINK_STOP)
195   {
196     return false;
197   }
198   
199   if(ledStack.num > LED_STATUS_END)
200   {
201     return false;
202   }
203   
204   ledStack.stack[ledStack.num] = ledStatus;
205   ledStack.num++;
206   LED_Set(ledStatus,times);
207   
208   return true;
209 }
210 //******************************************************************************
211 // fn : LED_StackPop
212 //
213 // brief : pop the top node from ledstack
214 //
215 // param : none
216 //
217 // return : none
218 void LED_StackPop(void)
219 {
220   if(ledStack.num == 0)
221   {
222     return;
223   }
224   
225   ledStack.num -= 1;
226   //停止当前LED状态
227   ledInfo.ledLevelFlag = LED_OFF;
228   ledModule.fnTimerStop();  
229   ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
230   
231   if(ledStack.num)
232   {
233     eLEDStatus led_id = (eLEDStatus)ledStack.stack[ledStack.num - 1];
234     uint8_t times = ledBlinkTimesTable[led_id];
235     if(times == LED_BLINK_STOP)
236     {
237       LED_StackPop();
238     }
239     else
240     {
241       LED_Set(led_id,times);
242     }
243   }
244 }
245 
246 //******************************************************************************
247 // fn : LED_StackClear
248 //
249 // brief : clear the stack of led
250 //
251 // param : none
252 //
253 // return : none
254 void LED_StackClear(void)
255 {
256   ledStack.num = 0;
257   //停止当前LED状态
258   ledInfo.ledLevelFlag = LED_OFF;
259   ledModule.fnTimerStop();  
260   ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
261 }
262 
263 #endif
264 //******************************************************************************
265 // static functions define area
266 //
267 //******************************************************************************
268 // fn : ledTimeoutCb
269 //
270 // brief : the timeout callback to the led
271 //
272 // param : level -> true:pin high;false:pin low
273 //
274 // return : none
275 static void ledTimeoutCb(bool level)
276 {
277   uint16_t ms = 0;
278   if(level == LED_ON)
279   {
280     ledInfo.ledLevelFlag = LED_OFF;
281   }
282   else
283   {
284     ledInfo.ledLevelFlag = LED_ON;
285     if(LED_BLINK_FOREVER != ledBlinkTimesTable[ledInfo.ledPointer])
286     {
287       ledBlinkTimesTable[ledInfo.ledPointer] -= 1;
288       if(ledBlinkTimesTable[ledInfo.ledPointer] == LED_BLINK_STOP)
289       {
290 #ifdef LED_PRORITY_EN
291         LED_StackPop();   //弹出当前led状态
292         return;
293 #else
294         return;
295 #endif
296       }
297     }
298   }
299   ms = ledGetBlinkTime(ledInfo.ledLevelFlag);
300   ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
301   ledModule.fnTimerStart(ms,&ledInfo.ledLevelFlag);  
302 }
303 //******************************************************************************
304 // fn : ledGetBlinkTime
305 //
306 // brief : Get the time with led status
307 //
308 // param : level -> true:pin high;false:pin low
309 //
310 // return : time
311 static uint16_t ledGetBlinkTime(bool level)
312 {
313   uint16_t ms = 0;
314   switch(ledInfo.ledPointer)
315   {
316   case LED_STATUS_BLINK1:
317     ms = level ? LED_BLINK1_ON_MS : LED_BLINK1_OFF_MS;
318     break;
319   case LED_STATUS_BLINK2:
320     ms = level ? LED_BLINK2_ON_MS : LED_BLINK2_OFF_MS;
321     break;
322   case LED_STATUS_BLINK3:
323     ms = level ? LED_BLINK3_ON_MS : LED_BLINK3_OFF_MS;
324     break;
325   case LED_STATUS_BLINK4:
326     ms = level ? LED_BLINK4_ON_MS : LED_BLINK4_OFF_MS;
327     break;
328   default:
329     break;
330   }
331   return ms;
332   
333 }

本PDF由谷雨文档中心自动生成,点击下方链接阅读最新内容。

取自“http://doc.iotxx.com/index.php?title=LED_闪烁控制软件模块&oldid=2508