1、需求分析
需求:设计一个LED驱动程序:1、支持0-100Hz频率闪烁 2、常亮、常灭 3、指定频率(0-100Hz)闪烁或亮指定一段时间
潜在需求:1、需要能同时处理多个LED,也就是同时控制多个GPIO口的LED灯 2、LED控制需要支持多线程操作 3、LED可以动态增删
2、程序设计
程序实现上首先考虑0~100Hz范围(事实上超过100Hz的闪烁,人眼就很难分辨了),而且要支持多个LED控制,那么可以用一个定时器,定时1ms,处理LED链表上的所有LED,通过链表上每个LED结点自己记录自己的亮灭计时,来控制LED灯。
有了这个想法设计链表上LED节点结构体如下
typedef uint64_t led_time_t;
typedef struct led_handle {
int gpio;
int always;
int periodic;
int counter;
int period;
int used;
led_time_t time;
led_time_t on_time;
led_time_t total_time;
struct list_head list;
}*led_handle_t;
有了节点结构体,现在要考虑往链表上添加和删除led节点,设计链表头结构体如下:
typedef struct led_control
{
SemaphoreHandle_t mutex;
struct list_head head;
}led_ctrl_t;
然后,就需要创建LED、销毁LED、添加LED、删除LED接口,设计如下:
创建LED:需要初始化LED的GPIO,分配 led_handle_t 作为控制句柄,供后续操作。
销毁LED:就是创建的反向操作,释放掉GPIO,释放掉句柄。
添加LED:添加LED,根据上面需求,需要有三个参数,分别表示周期,也就是闪烁频率;闪烁时亮灭时间比,类似PWM的占空比;还有时长。这里设计注意,假如是常亮、常灭,周期就指定为0Hz,占空比为100,同时通过设置 led->always 为1,指示一直常亮。参数都设置完成之后,就添加到LED全局链表上,需要注意加锁。
删除LED:添加的反向操作,从链表上把LED删除掉,注意要加锁
led_ctrl_t led_ctrl; //全局定义LED链表头
void led_set(led_handle_t led, led_state_e state)
{
gpio_set_level(led->gpio, state);
}
led_handle_t led_create(int gpio_num)
{
led_handle_t led;
led = (led_handle_t)heap_caps_malloc(sizeof(*led), MALLOC_CAP_SPIRAM);
if (!led) {
ESP_LO


677

被折叠的 条评论
为什么被折叠?



