文章
关于LED驱动,同样适用于蜂鸣器,使其更适合状态指示
源码
文章中的代码整理
基本思想是不用定时器,参考芯片自己的时钟调整LED闪烁频率
#define LED_TIME_CYCLE 1500 // ms
#define LED_TIME_OUTPUT 150 // ms
typedef enum {
LED_ON,
LED_OFF,
}led_level_def;
typedef struct {
uint16_t last_time_show_cycle; // 状态查询时间
uint16_t set_time_cycle; // 循环时间
uint16_t set_last_time; // 上一次电平输出时间
uint8_t curr_number; // 当前
uint8_t next_number; // 下一个指示次数
void (*led_set)(led_level_def);
}led_para_def;
// LED 设置
void led_set_level(led_level_def level)
{
if(level == LED_ON){
GPIO_ResetBits(GPIOB, GPIO_Pin_13);
}
else{
GPIO_SetBits(GPIOB, GPIO_Pin_13);
}
}
// 参数初始化
led_para_def led_para =
{
.set_time_cycle = (uint16_t)-1,
.curr_number = 0,
.led_set = led_set_level,
};
// 调用频率小于 10 ms
void led_set_handle(led_para_def *p_led_para, uint32_t time)
{
// 设置 LED
if(((uint16_t)(time - p_led_para->set_last_time)) >= p_led_para->set_time_cycle) {
p_led_para->set_last_time = time;
if(p_led_para->curr_number) {
p_led_para->led_set(((p_led_para->curr_number & 1) == 1) ? LED_OFF : LED_ON);
p_led_para->curr_number--;
if(p_led_para->curr_number == 0) {
p_led_para->set_time_cycle = (uint16_t)-1;// 下一个周期不再进入
}
}
}
// 更新当前参数(1.5 s 更新一次)
if(((uint16_t)(time - p_led_para->last_time_show_cycle)) >= LED_TIME_CYCLE){
p_led_para->last_time_show_cycle = time;
if(!p_led_para->curr_number){
uint8_t number = p_led_para->next_number; // 获取当前指示次数
// 限制闪烁次数
if(number < LED_TIME_CYCLE / LED_TIME_OUTPUT / 2){
p_led_para->curr_number = number * 2 - 1;
p_led_para->set_last_time = time;
p_led_para->set_time_cycle = LED_TIME_OUTPUT;
p_led_para->led_set(LED_ON);
}
}
}
}
// number 闪烁次数
void led_show(led_para_def *p_led_para, uint8_t number)
{
p_led_para->next_number = number;
}
改写
Module_LED.h
/*
* Copyright (c) 2020 - ~, HIT_HERO Team
*
* LED MODULE HEAD FILE
* Used in RT-Thread Operate System
*
* Change Logs:
* Date Author Notes Mail
* 2020-06-02 WangXi first version WangXi_chn@foxmail.com
* 2020-07-30 WangXi second version WangXi_chn@foxmail.com
*/
#ifndef _MODULE_LED_H_
#define _MODULE_LED_H_
#define _LED_POSITIVE_POLE //RESET Enable LED
//#define _LED_NEGETIVE_POLE //SET Enable LED
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
typedef enum
{
#ifdef _LED_POSITIVE_POLE
MODULE_LED_ON = 0,
MODULE_LED_OFF
#endif
#ifdef _LED_NEGETIVE_POLE
MODULE_LED_OFF = 0,
MODULE_LED_ON
#endif
}led_level_def;
struct _MODULE_LED
{
/* Property */
rt_base_t pin; /*!< Specifies the LED module pins to be configured.
This parameter is defined by function @ref GET_PIN(GPIOPORT, GPIO_PIN_NUM) */
rt_uint32_t LED_TIME_CYCLE;
rt_uint32_t LED_TIME_OUTPUT;
/* Value */
rt_uint16_t last_time_show_cycle; // 状态查询时间
rt_uint16_t set_time_cycle; // 循环时间
rt_uint16_t set_last_time; // 上一次电平输出时间
rt_uint8_t curr_number; // 当前
rt_uint8_t next_number; // 下一个指示次数
/* Method */
void (*Init)(struct _MODULE_LED *module);
void (*Handle)(struct _MODULE_LED *module);
void (*Set)(struct _MODULE_LED *module,rt_uint8_t number);
};
typedef struct _MODULE_LED MODULE_LED;
/* Glodal Method */
rt_err_t Module_Led_Config(MODULE_LED *Dev_LED);
#endif
/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
Module_LED.c
/*
* Copyright (c) 2020 - ~, HIT_HERO Team
*
* LED MODULE SOUCE FILE
* Used in RT-Thread Operate System
*
* Change Logs:
* Date Author Notes Mail
* 2020-06-02 WangXi first version WangXi_chn@foxmail.com
* 2020-07-30 WangXi second version WangXi_chn@foxmail.com
*/
#include "Module_LED.h"
#include <stdlib.h>
/* User Code Begin*/
static void led_shine_entry(void *parameter){
MODULE_LED* dev_led_1 = (MODULE_LED *)parameter;
dev_led_1->Handle(dev_led_1);
}
void LEDTest(int argc,char **argv)
{
rt_err_t res = RT_EOK;
MODULE_LED dev_led_1 = {GET_PIN(H, 11)};
res = Module_Led_Config(&dev_led_1);
if(res != RT_EOK){
rt_kprintf("Error: Some wrong happened while led config\n");
return;
}
if (argc < 2){
rt_kprintf("Error: Command missing arguments\n");
return;
}
rt_uint32_t num = atoi(argv[1]);
dev_led_1.Set(&dev_led_1,num);
rt_thread_t led_thread = rt_thread_create("ledshine", led_shine_entry, &dev_led_1,
192, RT_THREAD_PRIORITY_MAX - 2, 20);
if (led_thread != RT_NULL){
rt_thread_startup(led_thread);
}
}
MSH_CMD_EXPORT(LEDTest , LEDTest(PH11) <-number>(1~4));
/* User Code End */
/* Static Method */
static void Module_LedInit(MODULE_LED *module);
static void Module_LedSet(MODULE_LED *module,rt_uint8_t number);
static void Module_LedHandle(MODULE_LED *module);
/* Global Method */
rt_err_t Module_Led_Config(MODULE_LED *Dev_LED){
if(Dev_LED->Init==NULL &&
Dev_LED->Set==NULL &&
Dev_LED->Handle==NULL
){
/* Link the Method */
Dev_LED->Init = Module_LedInit;
Dev_LED->Set = Module_LedSet;
Dev_LED->Handle = Module_LedHandle;
}
else{
rt_kprintf("Warning: Module Led is Configed twice\n");
return RT_ERROR;
}
/* Device Init */
Dev_LED->Init(Dev_LED);
return RT_EOK;
}
/* Static Method */
static void Module_LedInit(MODULE_LED *module){
rt_pin_mode(module->pin, PIN_MODE_OUTPUT);
module->set_time_cycle = (rt_uint16_t)-1;
module->curr_number = 0;
}
static void Module_LedSet(MODULE_LED *module,rt_uint8_t number){
module->next_number = number;
}
static void Module_LedHandle(MODULE_LED *module){
/* get system clock */
rt_uint32_t time = rt_tick_get();
/* toggle the LED */
if(((uint16_t)(time - module->set_last_time)) >= module->set_time_cycle) {
module->set_last_time = time;
if(module->curr_number) {
//module->led_set(((module->curr_number & 1) == 1) ? LED_OFF : LED_ON);
rt_pin_write(module->pin, ((module->curr_number & 1) == 1) ? MODULE_LED_OFF : MODULE_LED_ON);
module->curr_number--;
if(module->curr_number == 0) {
module->set_time_cycle = (uint16_t)-1;// 下一个周期不再进入
}
}
}
/* enable the new param */
if(((uint16_t)(time - module->last_time_show_cycle)) >= module->LED_TIME_CYCLE){
module->last_time_show_cycle = time;
if(!module->curr_number){
uint8_t number = module->next_number; // 获取当前指示次数
// 限制闪烁次数
if(number < (module->LED_TIME_CYCLE / module->LED_TIME_OUTPUT / 2)){
module->curr_number = number * 2 - 1;
module->set_last_time = time;
module->set_time_cycle = module->LED_TIME_OUTPUT;
//module->led_set(LED_ON);
rt_pin_write(module->pin, MODULE_LED_ON);
}
}
}
}
/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
使用
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "Module_LED.h"
MODULE_LED dev_led_state = {GET_PIN(H, 10),1500,150};
int main(void)
{
int count = 1;
Module_Led_Config(&dev_led_state);
dev_led_state.Set(&dev_led_state,4);
while (count++)
{
dev_led_state.Handle(&dev_led_state);
}
return RT_EOK;
}
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;
rt_uint32_t PWM_CHANNEL;
rt_uint32_t PWM_FREQ;
rt_uint32_t PWM_DUTY;
rt_uint32_t BEEP_TIME_CYCLE;
rt_uint32_t BEEP_TIME_OUTPUT;
/* Value */
struct rt_device_pwm *pwm_dev;
rt_uint16_t last_time_show_cycle; // 状态查询时间
rt_uint16_t set_time_cycle; // 循环时间
rt_uint16_t set_last_time; // 上一次电平输出时间
rt_uint8_t curr_number; // 当前
rt_uint8_t next_number; // 下一个指示次数
/* Method */
void (*Init)(struct _MODULE_BEEP *module);
void (*Handle)(struct _MODULE_BEEP *module);
void (*Set)(struct _MODULE_BEEP *module,rt_uint8_t number);
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**/
<a name="iB5j3"></a>
## Module_Beep.c
```c
/*
* Copyright (c) 2020 - ~, HIT_HERO Team
*
* BEEP MODULE SOUCE FILE
* Used in RT-Thread Operate System
*
* Change Logs:
* Date Author Notes Mail
* 2020-07-31 WangXi second version WangXi_chn@foxmail.com
*/
#include "Module_Beep.h"
#include <stdlib.h>
/* User Code Begin*/
static void Beep_shine_entry(void *parameter){
MODULE_BEEP* dev_beep_1 = (MODULE_BEEP *)parameter;
dev_beep_1->Handle(dev_beep_1);
}
void BeepTest(int argc,char **argv)
{
rt_err_t res = RT_EOK;
MODULE_BEEP dev_beep_1 = {"pwm1",4,2000,20,1500,15};
res = Module_Beep_Config(&dev_beep_1);
if(res != RT_EOK){
rt_kprintf("Error: Some wrong happened while BEEP config\n");
return;
}
if (argc < 2){
rt_kprintf("Error: Command missing arguments\n");
return;
}
rt_uint32_t num = atoi(argv[1]);
dev_beep_1.Set(&dev_beep_1,num);
rt_thread_t BEEP_thread = rt_thread_create("beepshine", Beep_shine_entry, &dev_beep_1,
192, RT_THREAD_PRIORITY_MAX - 2, 20);
if (BEEP_thread != RT_NULL){
rt_thread_startup(BEEP_thread);
}
}
MSH_CMD_EXPORT(BeepTest , BeepTest(PH11) <-number>(1~4));
/* User Code End */
/* Static Method */
static void Module_BeepInit(MODULE_BEEP *module);
static void Module_BeepSet(MODULE_BEEP *module,rt_uint8_t number);
static void Module_BeepHandle(MODULE_BEEP *module);
static void Module_BeepControl(MODULE_BEEP *module,BEEP_STATION station);
/* Global Method */
rt_err_t Module_Beep_Config(MODULE_BEEP *Dev_Beep){
if(Dev_Beep->Init==NULL &&
Dev_Beep->Set==NULL &&
Dev_Beep->Handle==NULL &&
Dev_Beep->Control==NULL
){
/* Link the Method */
Dev_Beep->Init = Module_BeepInit;
Dev_Beep->Set = Module_BeepSet;
Dev_Beep->Handle = Module_BeepHandle;
Dev_Beep->Control = Module_BeepControl;
}
else{
rt_kprintf("Warning: Module BEEP is Configed twice\n");
return RT_ERROR;
}
/* Device Init */
Dev_Beep->Init(Dev_Beep);
return RT_EOK;
}
/* Static Method */
static void Module_BeepInit(MODULE_BEEP *module){
rt_uint32_t PWM_period = 1000000000/module->PWM_FREQ;
rt_uint32_t PWM_pulse = PWM_period/100*module->PWM_DUTY;
module->pwm_dev = (struct rt_device_pwm *)rt_device_find(module->PwmDevName);
if (module->pwm_dev == RT_NULL)
rt_kprintf("beep init failed! can't find pwm_beep device!\n");
rt_pwm_set(module->pwm_dev, module->PWM_CHANNEL, PWM_period, PWM_pulse);
module->set_time_cycle = (rt_uint16_t)-1;
module->curr_number = 0;
}
static void Module_BeepSet(MODULE_BEEP *module,rt_uint8_t number){
module->next_number = number;
}
static void Module_BeepHandle(MODULE_BEEP *module){
/* get system clock */
rt_uint32_t time = rt_tick_get();
/* toggle the BEEP */
if(((uint16_t)(time - module->set_last_time)) >= module->set_time_cycle) {
module->set_last_time = time;
if(module->curr_number) {
//rt_pin_write(module->pin, ((module->curr_number & 1) == 1) ? MODULE_BEEP_OFF : MODULE_BEEP_ON);
module->Control(module,((module->curr_number & 1) == 1) ? MODULE_BEEP_OFF : MODULE_BEEP_ON);
module->curr_number--;
if(module->curr_number == 0) {
module->set_time_cycle = (uint16_t)-1;// 下一个周期不再进入
}
}
}
/* enable the new param */
if(((uint16_t)(time - module->last_time_show_cycle)) >= module->BEEP_TIME_CYCLE){
module->last_time_show_cycle = time;
if(!module->curr_number){
uint8_t number = module->next_number; // 获取当前指示次数
// 限制闪烁次数
if(number < (module->BEEP_TIME_CYCLE / module->BEEP_TIME_OUTPUT / 2)){
module->curr_number = number * 2 - 1;
module->set_last_time = time;
module->set_time_cycle = module->BEEP_TIME_OUTPUT;
module->Control(module,MODULE_BEEP_ON);
}
}
}
}
static void Module_BeepControl(MODULE_BEEP *module,BEEP_STATION station){
switch(station){
case MODULE_BEEP_ON:{
rt_pwm_enable(module->pwm_dev, module->PWM_CHANNEL);
break;
}
case MODULE_BEEP_OFF:{
rt_pwm_disable(module->pwm_dev, module->PWM_CHANNEL);
break;
}
}
}
/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
使用
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "Module_Beep.h"
MODULE_BEEP dev_beep_1 = {"pwm4",3,2000,20,2000,100};
int main(void)
{
int count = 1;
Module_Beep_Config(&dev_beep_1);
dev_beep_1.Set(&dev_beep_1,4);
while (count++)
{
dev_beep_1.Handle(&dev_beep_1);
}
return RT_EOK;
}