文章

关于LED驱动,同样适用于蜂鸣器,使其更适合状态指示

状态指示灯.pdf

源码

文章中的代码整理
基本思想是不用定时器,参考芯片自己的时钟调整LED闪烁频率

  1. #define LED_TIME_CYCLE 1500 // ms
  2. #define LED_TIME_OUTPUT 150 // ms
  3. typedef enum {
  4. LED_ON,
  5. LED_OFF,
  6. }led_level_def;
  7. typedef struct {
  8. uint16_t last_time_show_cycle; // 状态查询时间
  9. uint16_t set_time_cycle; // 循环时间
  10. uint16_t set_last_time; // 上一次电平输出时间
  11. uint8_t curr_number; // 当前
  12. uint8_t next_number; // 下一个指示次数
  13. void (*led_set)(led_level_def);
  14. }led_para_def;
  15. // LED 设置
  16. void led_set_level(led_level_def level)
  17. {
  18. if(level == LED_ON){
  19. GPIO_ResetBits(GPIOB, GPIO_Pin_13);
  20. }
  21. else{
  22. GPIO_SetBits(GPIOB, GPIO_Pin_13);
  23. }
  24. }
  25. // 参数初始化
  26. led_para_def led_para =
  27. {
  28. .set_time_cycle = (uint16_t)-1,
  29. .curr_number = 0,
  30. .led_set = led_set_level,
  31. };
  32. // 调用频率小于 10 ms
  33. void led_set_handle(led_para_def *p_led_para, uint32_t time)
  34. {
  35. // 设置 LED
  36. if(((uint16_t)(time - p_led_para->set_last_time)) >= p_led_para->set_time_cycle) {
  37. p_led_para->set_last_time = time;
  38. if(p_led_para->curr_number) {
  39. p_led_para->led_set(((p_led_para->curr_number & 1) == 1) ? LED_OFF : LED_ON);
  40. p_led_para->curr_number--;
  41. if(p_led_para->curr_number == 0) {
  42. p_led_para->set_time_cycle = (uint16_t)-1;// 下一个周期不再进入
  43. }
  44. }
  45. }
  46. // 更新当前参数(1.5 s 更新一次)
  47. if(((uint16_t)(time - p_led_para->last_time_show_cycle)) >= LED_TIME_CYCLE){
  48. p_led_para->last_time_show_cycle = time;
  49. if(!p_led_para->curr_number){
  50. uint8_t number = p_led_para->next_number; // 获取当前指示次数
  51. // 限制闪烁次数
  52. if(number < LED_TIME_CYCLE / LED_TIME_OUTPUT / 2){
  53. p_led_para->curr_number = number * 2 - 1;
  54. p_led_para->set_last_time = time;
  55. p_led_para->set_time_cycle = LED_TIME_OUTPUT;
  56. p_led_para->led_set(LED_ON);
  57. }
  58. }
  59. }
  60. }
  61. // number 闪烁次数
  62. void led_show(led_para_def *p_led_para, uint8_t number)
  63. {
  64. p_led_para->next_number = number;
  65. }

改写

使LED状态灯成为独立的模块,且符合模块组件设计

Module_LED.h

  1. /*
  2. * Copyright (c) 2020 - ~, HIT_HERO Team
  3. *
  4. * LED MODULE HEAD FILE
  5. * Used in RT-Thread Operate System
  6. *
  7. * Change Logs:
  8. * Date Author Notes Mail
  9. * 2020-06-02 WangXi first version WangXi_chn@foxmail.com
  10. * 2020-07-30 WangXi second version WangXi_chn@foxmail.com
  11. */
  12. #ifndef _MODULE_LED_H_
  13. #define _MODULE_LED_H_
  14. #define _LED_POSITIVE_POLE //RESET Enable LED
  15. //#define _LED_NEGETIVE_POLE //SET Enable LED
  16. #include <rtthread.h>
  17. #include <rtdevice.h>
  18. #include <board.h>
  19. typedef enum
  20. {
  21. #ifdef _LED_POSITIVE_POLE
  22. MODULE_LED_ON = 0,
  23. MODULE_LED_OFF
  24. #endif
  25. #ifdef _LED_NEGETIVE_POLE
  26. MODULE_LED_OFF = 0,
  27. MODULE_LED_ON
  28. #endif
  29. }led_level_def;
  30. struct _MODULE_LED
  31. {
  32. /* Property */
  33. rt_base_t pin; /*!< Specifies the LED module pins to be configured.
  34. This parameter is defined by function @ref GET_PIN(GPIOPORT, GPIO_PIN_NUM) */
  35. rt_uint32_t LED_TIME_CYCLE;
  36. rt_uint32_t LED_TIME_OUTPUT;
  37. /* Value */
  38. rt_uint16_t last_time_show_cycle; // 状态查询时间
  39. rt_uint16_t set_time_cycle; // 循环时间
  40. rt_uint16_t set_last_time; // 上一次电平输出时间
  41. rt_uint8_t curr_number; // 当前
  42. rt_uint8_t next_number; // 下一个指示次数
  43. /* Method */
  44. void (*Init)(struct _MODULE_LED *module);
  45. void (*Handle)(struct _MODULE_LED *module);
  46. void (*Set)(struct _MODULE_LED *module,rt_uint8_t number);
  47. };
  48. typedef struct _MODULE_LED MODULE_LED;
  49. /* Glodal Method */
  50. rt_err_t Module_Led_Config(MODULE_LED *Dev_LED);
  51. #endif
  52. /************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/

Module_LED.c

  1. /*
  2. * Copyright (c) 2020 - ~, HIT_HERO Team
  3. *
  4. * LED MODULE SOUCE FILE
  5. * Used in RT-Thread Operate System
  6. *
  7. * Change Logs:
  8. * Date Author Notes Mail
  9. * 2020-06-02 WangXi first version WangXi_chn@foxmail.com
  10. * 2020-07-30 WangXi second version WangXi_chn@foxmail.com
  11. */
  12. #include "Module_LED.h"
  13. #include <stdlib.h>
  14. /* User Code Begin*/
  15. static void led_shine_entry(void *parameter){
  16. MODULE_LED* dev_led_1 = (MODULE_LED *)parameter;
  17. dev_led_1->Handle(dev_led_1);
  18. }
  19. void LEDTest(int argc,char **argv)
  20. {
  21. rt_err_t res = RT_EOK;
  22. MODULE_LED dev_led_1 = {GET_PIN(H, 11)};
  23. res = Module_Led_Config(&dev_led_1);
  24. if(res != RT_EOK){
  25. rt_kprintf("Error: Some wrong happened while led config\n");
  26. return;
  27. }
  28. if (argc < 2){
  29. rt_kprintf("Error: Command missing arguments\n");
  30. return;
  31. }
  32. rt_uint32_t num = atoi(argv[1]);
  33. dev_led_1.Set(&dev_led_1,num);
  34. rt_thread_t led_thread = rt_thread_create("ledshine", led_shine_entry, &dev_led_1,
  35. 192, RT_THREAD_PRIORITY_MAX - 2, 20);
  36. if (led_thread != RT_NULL){
  37. rt_thread_startup(led_thread);
  38. }
  39. }
  40. MSH_CMD_EXPORT(LEDTest , LEDTest(PH11) <-number>(1~4));
  41. /* User Code End */
  42. /* Static Method */
  43. static void Module_LedInit(MODULE_LED *module);
  44. static void Module_LedSet(MODULE_LED *module,rt_uint8_t number);
  45. static void Module_LedHandle(MODULE_LED *module);
  46. /* Global Method */
  47. rt_err_t Module_Led_Config(MODULE_LED *Dev_LED){
  48. if(Dev_LED->Init==NULL &&
  49. Dev_LED->Set==NULL &&
  50. Dev_LED->Handle==NULL
  51. ){
  52. /* Link the Method */
  53. Dev_LED->Init = Module_LedInit;
  54. Dev_LED->Set = Module_LedSet;
  55. Dev_LED->Handle = Module_LedHandle;
  56. }
  57. else{
  58. rt_kprintf("Warning: Module Led is Configed twice\n");
  59. return RT_ERROR;
  60. }
  61. /* Device Init */
  62. Dev_LED->Init(Dev_LED);
  63. return RT_EOK;
  64. }
  65. /* Static Method */
  66. static void Module_LedInit(MODULE_LED *module){
  67. rt_pin_mode(module->pin, PIN_MODE_OUTPUT);
  68. module->set_time_cycle = (rt_uint16_t)-1;
  69. module->curr_number = 0;
  70. }
  71. static void Module_LedSet(MODULE_LED *module,rt_uint8_t number){
  72. module->next_number = number;
  73. }
  74. static void Module_LedHandle(MODULE_LED *module){
  75. /* get system clock */
  76. rt_uint32_t time = rt_tick_get();
  77. /* toggle the LED */
  78. if(((uint16_t)(time - module->set_last_time)) >= module->set_time_cycle) {
  79. module->set_last_time = time;
  80. if(module->curr_number) {
  81. //module->led_set(((module->curr_number & 1) == 1) ? LED_OFF : LED_ON);
  82. rt_pin_write(module->pin, ((module->curr_number & 1) == 1) ? MODULE_LED_OFF : MODULE_LED_ON);
  83. module->curr_number--;
  84. if(module->curr_number == 0) {
  85. module->set_time_cycle = (uint16_t)-1;// 下一个周期不再进入
  86. }
  87. }
  88. }
  89. /* enable the new param */
  90. if(((uint16_t)(time - module->last_time_show_cycle)) >= module->LED_TIME_CYCLE){
  91. module->last_time_show_cycle = time;
  92. if(!module->curr_number){
  93. uint8_t number = module->next_number; // 获取当前指示次数
  94. // 限制闪烁次数
  95. if(number < (module->LED_TIME_CYCLE / module->LED_TIME_OUTPUT / 2)){
  96. module->curr_number = number * 2 - 1;
  97. module->set_last_time = time;
  98. module->set_time_cycle = module->LED_TIME_OUTPUT;
  99. //module->led_set(LED_ON);
  100. rt_pin_write(module->pin, MODULE_LED_ON);
  101. }
  102. }
  103. }
  104. }
  105. /************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/

使用

  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #include <board.h>
  4. #include "Module_LED.h"
  5. MODULE_LED dev_led_state = {GET_PIN(H, 10),1500,150};
  6. int main(void)
  7. {
  8. int count = 1;
  9. Module_Led_Config(&dev_led_state);
  10. dev_led_state.Set(&dev_led_state,4);
  11. while (count++)
  12. {
  13. dev_led_state.Handle(&dev_led_state);
  14. }
  15. return RT_EOK;
  16. }
  • 蜂鸣器较为复杂,涉及到无源蜂鸣器,需要驱动pwm设备

    Module_Beep.h

    ```c /*
    • Copyright (c) 2020 - ~, HIT_HERO Team *
    • BEEP MODULE HEAD FILE
    • Used in RT-Thread Operate System *
    • Change Logs:
    • Date Author Notes Mail
    • 2020-07-31 WangXi second version WangXi_chn@foxmail.com */

      ifndef MODULE_BEEP_H

      define MODULE_BEEP_H

enum _BEEP_STATION { MODULE_BEEP_ON = 0, MODULE_BEEP_OFF }; typedef enum _BEEP_STATION BEEP_STATION ;

include

include

include

struct _MODULE_BEEP { / Property / char * PwmDevName;

  1. rt_uint32_t PWM_CHANNEL;
  2. rt_uint32_t PWM_FREQ;
  3. rt_uint32_t PWM_DUTY;
  4. rt_uint32_t BEEP_TIME_CYCLE;
  5. rt_uint32_t BEEP_TIME_OUTPUT;
  6. /* Value */
  7. struct rt_device_pwm *pwm_dev;
  8. rt_uint16_t last_time_show_cycle; // 状态查询时间
  9. rt_uint16_t set_time_cycle; // 循环时间
  10. rt_uint16_t set_last_time; // 上一次电平输出时间
  11. rt_uint8_t curr_number; // 当前
  12. rt_uint8_t next_number; // 下一个指示次数
  13. /* Method */
  14. void (*Init)(struct _MODULE_BEEP *module);
  15. void (*Handle)(struct _MODULE_BEEP *module);
  16. void (*Set)(struct _MODULE_BEEP *module,rt_uint8_t number);
  17. void (*Control)(struct _MODULE_BEEP *module,BEEP_STATION station);

}; typedef struct _MODULE_BEEP MODULE_BEEP;

/ Glodal Method / rt_err_t Module_Beep_Config(MODULE_BEEP *Dev_Beep);

endif

/** (C) COPYRIGHT 2020 WANGXI **END OF FILE**/

  1. <a name="iB5j3"></a>
  2. ## Module_Beep.c
  3. ```c
  4. /*
  5. * Copyright (c) 2020 - ~, HIT_HERO Team
  6. *
  7. * BEEP MODULE SOUCE FILE
  8. * Used in RT-Thread Operate System
  9. *
  10. * Change Logs:
  11. * Date Author Notes Mail
  12. * 2020-07-31 WangXi second version WangXi_chn@foxmail.com
  13. */
  14. #include "Module_Beep.h"
  15. #include <stdlib.h>
  16. /* User Code Begin*/
  17. static void Beep_shine_entry(void *parameter){
  18. MODULE_BEEP* dev_beep_1 = (MODULE_BEEP *)parameter;
  19. dev_beep_1->Handle(dev_beep_1);
  20. }
  21. void BeepTest(int argc,char **argv)
  22. {
  23. rt_err_t res = RT_EOK;
  24. MODULE_BEEP dev_beep_1 = {"pwm1",4,2000,20,1500,15};
  25. res = Module_Beep_Config(&dev_beep_1);
  26. if(res != RT_EOK){
  27. rt_kprintf("Error: Some wrong happened while BEEP config\n");
  28. return;
  29. }
  30. if (argc < 2){
  31. rt_kprintf("Error: Command missing arguments\n");
  32. return;
  33. }
  34. rt_uint32_t num = atoi(argv[1]);
  35. dev_beep_1.Set(&dev_beep_1,num);
  36. rt_thread_t BEEP_thread = rt_thread_create("beepshine", Beep_shine_entry, &dev_beep_1,
  37. 192, RT_THREAD_PRIORITY_MAX - 2, 20);
  38. if (BEEP_thread != RT_NULL){
  39. rt_thread_startup(BEEP_thread);
  40. }
  41. }
  42. MSH_CMD_EXPORT(BeepTest , BeepTest(PH11) <-number>(1~4));
  43. /* User Code End */
  44. /* Static Method */
  45. static void Module_BeepInit(MODULE_BEEP *module);
  46. static void Module_BeepSet(MODULE_BEEP *module,rt_uint8_t number);
  47. static void Module_BeepHandle(MODULE_BEEP *module);
  48. static void Module_BeepControl(MODULE_BEEP *module,BEEP_STATION station);
  49. /* Global Method */
  50. rt_err_t Module_Beep_Config(MODULE_BEEP *Dev_Beep){
  51. if(Dev_Beep->Init==NULL &&
  52. Dev_Beep->Set==NULL &&
  53. Dev_Beep->Handle==NULL &&
  54. Dev_Beep->Control==NULL
  55. ){
  56. /* Link the Method */
  57. Dev_Beep->Init = Module_BeepInit;
  58. Dev_Beep->Set = Module_BeepSet;
  59. Dev_Beep->Handle = Module_BeepHandle;
  60. Dev_Beep->Control = Module_BeepControl;
  61. }
  62. else{
  63. rt_kprintf("Warning: Module BEEP is Configed twice\n");
  64. return RT_ERROR;
  65. }
  66. /* Device Init */
  67. Dev_Beep->Init(Dev_Beep);
  68. return RT_EOK;
  69. }
  70. /* Static Method */
  71. static void Module_BeepInit(MODULE_BEEP *module){
  72. rt_uint32_t PWM_period = 1000000000/module->PWM_FREQ;
  73. rt_uint32_t PWM_pulse = PWM_period/100*module->PWM_DUTY;
  74. module->pwm_dev = (struct rt_device_pwm *)rt_device_find(module->PwmDevName);
  75. if (module->pwm_dev == RT_NULL)
  76. rt_kprintf("beep init failed! can't find pwm_beep device!\n");
  77. rt_pwm_set(module->pwm_dev, module->PWM_CHANNEL, PWM_period, PWM_pulse);
  78. module->set_time_cycle = (rt_uint16_t)-1;
  79. module->curr_number = 0;
  80. }
  81. static void Module_BeepSet(MODULE_BEEP *module,rt_uint8_t number){
  82. module->next_number = number;
  83. }
  84. static void Module_BeepHandle(MODULE_BEEP *module){
  85. /* get system clock */
  86. rt_uint32_t time = rt_tick_get();
  87. /* toggle the BEEP */
  88. if(((uint16_t)(time - module->set_last_time)) >= module->set_time_cycle) {
  89. module->set_last_time = time;
  90. if(module->curr_number) {
  91. //rt_pin_write(module->pin, ((module->curr_number & 1) == 1) ? MODULE_BEEP_OFF : MODULE_BEEP_ON);
  92. module->Control(module,((module->curr_number & 1) == 1) ? MODULE_BEEP_OFF : MODULE_BEEP_ON);
  93. module->curr_number--;
  94. if(module->curr_number == 0) {
  95. module->set_time_cycle = (uint16_t)-1;// 下一个周期不再进入
  96. }
  97. }
  98. }
  99. /* enable the new param */
  100. if(((uint16_t)(time - module->last_time_show_cycle)) >= module->BEEP_TIME_CYCLE){
  101. module->last_time_show_cycle = time;
  102. if(!module->curr_number){
  103. uint8_t number = module->next_number; // 获取当前指示次数
  104. // 限制闪烁次数
  105. if(number < (module->BEEP_TIME_CYCLE / module->BEEP_TIME_OUTPUT / 2)){
  106. module->curr_number = number * 2 - 1;
  107. module->set_last_time = time;
  108. module->set_time_cycle = module->BEEP_TIME_OUTPUT;
  109. module->Control(module,MODULE_BEEP_ON);
  110. }
  111. }
  112. }
  113. }
  114. static void Module_BeepControl(MODULE_BEEP *module,BEEP_STATION station){
  115. switch(station){
  116. case MODULE_BEEP_ON:{
  117. rt_pwm_enable(module->pwm_dev, module->PWM_CHANNEL);
  118. break;
  119. }
  120. case MODULE_BEEP_OFF:{
  121. rt_pwm_disable(module->pwm_dev, module->PWM_CHANNEL);
  122. break;
  123. }
  124. }
  125. }
  126. /************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/

使用

  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #include <board.h>
  4. #include "Module_Beep.h"
  5. MODULE_BEEP dev_beep_1 = {"pwm4",3,2000,20,2000,100};
  6. int main(void)
  7. {
  8. int count = 1;
  9. Module_Beep_Config(&dev_beep_1);
  10. dev_beep_1.Set(&dev_beep_1,4);
  11. while (count++)
  12. {
  13. dev_beep_1.Handle(&dev_beep_1);
  14. }
  15. return RT_EOK;
  16. }