代码拉取完成,页面将自动刷新
同步操作将从 cot软件包/cotLed 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/**
**********************************************************************************************************************
* @file cot_led.c
* @brief 该文件提供LED灯控制功能
* @author const_zpc any question please send mail to const_zpc@163.com
* @version V1.0.0
* @date 2023-11-05
*
**********************************************************************************************************************
* 源码路径:https://gitee.com/cot_package/cot_led.git 具体问题及建议可在该网址填写 Issue
*
*
**********************************************************************************************************************
*/
/* Includes ----------------------------------------------------------------------------------------------------------*/
#include "cot_led.h"
#include <string.h>
#include <stdarg.h>
// 呼吸灯软件模拟PWM频率(HZ)
#define BREATHE_PWM_RATE 50
/* Private typedef ---------------------------------------------------------------------------------------------------*/
/* Private define ----------------------------------------------------------------------------------------------------*/
#define BREATHE_PWM_PERIOD (1000 / BREATHE_PWM_RATE)
/* Private macro -----------------------------------------------------------------------------------------------------*/
#define TIME_MAX_VAL (uint32_t)0xffff
#define TIME_ADD(tic, time) (TIME_MAX_VAL - (tic) < (time) ? ((tic) = 0xffff) : (tic += time))
#define LED_ABS(a) ((a) > 0 ? (a) : -(a))
#define FILL_STATE_BITS(state, sbit, ebit) {int bit; for (bit = (sbit); bit < (ebit); bit++) (state)[bit / 8] |= (0x01 << (bit % 8));}
#define SET_STATE_BITS(state, bit) {(state)[bit / 8] |= (0x01 << (bit % 8));}
/* Private variables -------------------------------------------------------------------------------------------------*/
static cotLedCfg_t *sg_pLedTable = NULL;
static size_t sg_ledNum = 0;
/* Private function prototypes ---------------------------------------------------------------------------------------*/
/* Private function --------------------------------------------------------------------------------------------------*/
/**
* @brief 按键初始化
*
* @param[in] pCfgTable 指示灯数组表指针
* @param[in] num 指示灯数组元素数目
* @return 0,成功; -1,失败
*/
int cotLed_Init(cotLedCfg_t pCfgTable[], size_t num)
{
uint8_t led;
sg_pLedTable = pCfgTable;
sg_ledNum = num;
for (led = 0; led < num; led++)
{
memset(&sg_pLedTable[led].proc, 0, sizeof(cotLedProc_t));
}
return 0;
}
/**
* @brief 设置LED的亮灭状态
*
* @param[in] led 指定指示灯
* @param[in] state 亮灭状态
* @return 0,成功; -1,失败
*/
int cotLed_SetState(led_t led, cotLedState_e state)
{
if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum)
{
return -1;
}
sg_pLedTable[led].proc.interval = 100;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.data.state[0] = (state == COT_LED_ON ? 0x01 : 0x00);
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = 1;
sg_pLedTable[led].proc.count = 0;
sg_pLedTable[led].proc.isSetCount = 0;
sg_pLedTable[led].proc.defState = 0;
sg_pLedTable[led].proc.isPwm = 0;
return 0;
}
/**
* @brief 设置LED的亮灭状态及持续时间
*
* @attention 时间应为控制任务调度周期的倍数
* @param[in] led 指定指示灯
* @param[in] state 亮灭状态
* @param[in] time 持续时间, 单位毫秒
* @return 0,成功; -1,失败
*/
int cotLed_SetStateWithTime(led_t led, cotLedState_e state, uint16_t time)
{
if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum)
{
return -1;
}
sg_pLedTable[led].proc.interval = time;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.data.state[0] = (state == COT_LED_ON ? 0x01 : 0x00);
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = 1;
sg_pLedTable[led].proc.count = 1;
sg_pLedTable[led].proc.isSetCount = 1;
sg_pLedTable[led].proc.defState = (state == COT_LED_ON ? 0 : 1);
sg_pLedTable[led].proc.isPwm = 0;
return 0;
}
/**
* @brief 点亮LED
*
* @param[in] led 指定指示灯
* @return 0,成功; -1,失败
*/
int cotLed_ON(led_t led)
{
return cotLed_SetState(led, COT_LED_ON);
}
/**
* @brief 熄灭LED
*
* @param[in] led 指定指示灯
* @return 0,成功; -1,失败
*/
int cotLed_OFF(led_t led)
{
return cotLed_SetState(led, COT_LED_OFF);
}
/**
* @brief 翻转指定LED亮灭状态
*
* @param led 指定指示灯
* @return 0,成功; -1,失败
*/
int cotLed_Toggle(led_t led)
{
if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum)
{
return -1;
}
sg_pLedTable[led].proc.interval = 100;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.data.state[0] = sg_pLedTable[led].proc.data.state[0] == 0 ? 0x01 : 0x00;
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = 1;
sg_pLedTable[led].proc.count = 0;
sg_pLedTable[led].proc.isSetCount = 0;
sg_pLedTable[led].proc.defState = 0;
sg_pLedTable[led].proc.isPwm = 0;
return 0;
}
/**
* @brief 设置LED为闪烁状态
*
* @attention 时间应为控制任务调度周期的倍数
* @param[in] led 指定指示灯
* @param[in] time 闪烁亮灭间隔时间, 单位毫秒
* @return 0,成功; -1,失败
*/
int cotLed_Twinkle(led_t led, uint16_t time)
{
if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum)
{
return -1;
}
sg_pLedTable[led].proc.interval = time;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.data.state[0] = 0x01;
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = 2;
sg_pLedTable[led].proc.count = 0;
sg_pLedTable[led].proc.isSetCount = 0;
sg_pLedTable[led].proc.defState = 0;
sg_pLedTable[led].proc.isPwm = 0;
return 0;
}
/**
* @brief 设置LED为闪烁状态及次数, 最后次数完成后的亮灭状态
*
* @note 一亮一灭为一次闪烁
* @attention 时间应为控制任务调度周期的倍数
* @param[in] led 指定指示灯
* @param[in] time 闪烁亮灭间隔时间, 单位毫秒
* @param[in] count 闪烁次数
* @param[in] defState 闪烁次数完成后的亮灭状态
* @return 0,成功; -1,失败
*/
int cotLed_TwinkleWithCount(led_t led, uint16_t time, uint8_t count, cotLedState_e defState)
{
if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum)
{
return -1;
}
sg_pLedTable[led].proc.interval = time;
sg_pLedTable[led].proc.tic = 0;
// 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果
sg_pLedTable[led].proc.data.state[0] = defState == COT_LED_ON ? 0x01 : 0x02;
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = 2;
sg_pLedTable[led].proc.count = count;
sg_pLedTable[led].proc.isSetCount = 1;
sg_pLedTable[led].proc.defState = defState == COT_LED_ON ? 1 : 0;
sg_pLedTable[led].proc.isPwm = 0;
return 0;
}
/**
* @brief 为多个LED设置为跑马灯
*
* @note
* @param[in] led LED组
* @param[in] ledNum LED数目
* @param[in] time LED亮时间
* @return 0,成功; -1,失败
*/
int cotLed_Marquee(led_t led[], uint8_t ledNum, int32_t time)
{
if (sg_pLedTable == NULL || sg_ledNum == 0)
{
return -1;
}
for (uint8_t i = 0; i < ledNum; i++)
{
if (led[i] < sg_ledNum)
{
memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM);
sg_pLedTable[led[i]].proc.interval = time;
sg_pLedTable[led[i]].proc.tic = 0;
SET_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i);
sg_pLedTable[led[i]].proc.offset = 0;
sg_pLedTable[led[i]].proc.validBits = ledNum;
sg_pLedTable[led[i]].proc.count = 0;
sg_pLedTable[led[i]].proc.isSetCount = 0;
sg_pLedTable[led[i]].proc.defState = 0;
sg_pLedTable[led[i]].proc.isPwm = 0;
}
}
return 0;
}
/**
* @brief 为多个LED设置为跑马灯及次数, 最后次数完成后的亮灭状态
*
* @note
* @param[in] led LED组
* @param[in] ledNum LED数目
* @param[in] time LED亮时间
* @param[in] count 跑马灯次数
* @param[in] defState 跑马灯次数完成后的亮灭状态
* @return 0,成功; -1,失败
*/
int cotLed_MarqueeWithCount(led_t led[], uint8_t ledNum, int32_t time, uint8_t count, cotLedState_e defState)
{
if (sg_pLedTable == NULL || sg_ledNum == 0)
{
return -1;
}
for (uint8_t i = 0; i < ledNum; i++)
{
if (led[i] < sg_ledNum)
{
memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM);
sg_pLedTable[led[i]].proc.interval = time;
sg_pLedTable[led[i]].proc.tic = 0;
SET_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i);
sg_pLedTable[led[i]].proc.offset = 0;
sg_pLedTable[led[i]].proc.validBits = ledNum;
sg_pLedTable[led[i]].proc.count = count;
sg_pLedTable[led[i]].proc.isSetCount = 1;
sg_pLedTable[led[i]].proc.defState = defState == COT_LED_ON ? 1 : 0;
sg_pLedTable[led[i]].proc.isPwm = 0;
}
}
return 0;
}
/**
* @brief 为多个LED设置为流水灯
*
* @note
* @param[in] led LED组
* @param[in] ledNum LED数目
* @param[in] time LED亮时间
* @return 0,成功; -1,失败
*/
int cotLed_Waterfall(led_t led[], uint8_t ledNum, int32_t time)
{
if (sg_pLedTable == NULL || sg_ledNum == 0)
{
return -1;
}
for (uint8_t i = 0; i < ledNum; i++)
{
if (led[i] < sg_ledNum)
{
memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM);
sg_pLedTable[led[i]].proc.interval = time;
sg_pLedTable[led[i]].proc.tic = 0;
FILL_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i, ledNum);
sg_pLedTable[led[i]].proc.offset = 0;
sg_pLedTable[led[i]].proc.validBits = ledNum + 1;
sg_pLedTable[led[i]].proc.count = 0;
sg_pLedTable[led[i]].proc.isSetCount = 0;
sg_pLedTable[led[i]].proc.defState = 0;
sg_pLedTable[led[i]].proc.isPwm = 0;
}
}
return 0;
}
/**
* @brief 为多个LED设置为流水灯及次数, 最后次数完成后的亮灭状态
*
* @note
* @param[in] led LED组
* @param[in] ledNum LED数目
* @param[in] time LED亮时间
* @param[in] count 流水灯次数
* @param[in] defState 流水灯次数完成后的亮灭状态
* @return 0,成功; -1,失败
*/
int cotLed_WaterfallWithCount(led_t led[], uint8_t ledNum, int32_t time, uint8_t count, cotLedState_e defState)
{
if (sg_pLedTable == NULL || sg_ledNum == 0)
{
return -1;
}
for (uint8_t i = 0; i < ledNum; i++)
{
if (led[i] < sg_ledNum)
{
memset(sg_pLedTable[led[i]].proc.data.state, 0, LED_STATE_BYTE_NUM);
sg_pLedTable[led[i]].proc.interval = time;
sg_pLedTable[led[i]].proc.tic = 0;
FILL_STATE_BITS(sg_pLedTable[led[i]].proc.data.state, i, ledNum);
sg_pLedTable[led[i]].proc.offset = 0;
sg_pLedTable[led[i]].proc.validBits = ledNum + 1;
sg_pLedTable[led[i]].proc.count = count;
sg_pLedTable[led[i]].proc.isSetCount = 1;
sg_pLedTable[led[i]].proc.defState = defState == COT_LED_ON ? 1 : 0;
sg_pLedTable[led[i]].proc.isPwm = 0;
}
}
return 0;
}
/**
* @brief 设置指定LED为呼吸灯模式
*
* @attention LED控制任务必须为1ms周期
* @param[in] led 指定指示灯
* @param[in] period 呼吸周期,即多久完成一次呼吸;单位毫秒
* @return 0,成功; -1,失败
*/
int cotLed_Breathe(led_t led, uint16_t period)
{
if (sg_pLedTable == NULL || sg_ledNum == 0)
{
return -1;
}
if (led < sg_ledNum)
{
sg_pLedTable[led].proc.interval = period / 2 / BREATHE_PWM_PERIOD;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.data.state[0] = 0; // 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = 2;
sg_pLedTable[led].proc.count = 0;
sg_pLedTable[led].proc.isSetCount = 0;
sg_pLedTable[led].proc.defState = 0;
sg_pLedTable[led].proc.isPwm = 1;
sg_pLedTable[led].proc.data.pwm.onTime = 0;
sg_pLedTable[led].proc.data.pwm.tic = 0;
sg_pLedTable[led].proc.pwmDir = 1;
}
return 0;
}
/**
* @brief 设置指定LED为呼吸灯模式及次数, 最后次数完成后的亮灭状态
*
* @attention LED控制任务必须为1ms周期
* @param[in] led 指定指示灯
* @param[in] period 呼吸周期,即多久完成一次呼吸;单位毫秒
* @param[in] count 次数
* @param[in] defState 次数完成后的亮灭状态
* @return 0,成功; -1,失败
*/
int cotLed_BreatheWithCount(led_t led, uint16_t period, uint8_t count, cotLedState_e defState)
{
if (sg_pLedTable == NULL || sg_ledNum == 0)
{
return -1;
}
if (led < sg_ledNum)
{
sg_pLedTable[led].proc.interval = period / 2 / BREATHE_PWM_PERIOD;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.data.state[0] = 0; // 根据默认状态最后一次闪烁时状态设置相反状态达到较好的闪烁效果
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = 2;
sg_pLedTable[led].proc.count = count;
sg_pLedTable[led].proc.isSetCount = 1;
sg_pLedTable[led].proc.defState = defState == COT_LED_ON ? 1 : 0;
sg_pLedTable[led].proc.isPwm = 1;
sg_pLedTable[led].proc.data.pwm.onTime = 0;
sg_pLedTable[led].proc.data.pwm.tic = 0;
sg_pLedTable[led].proc.pwmDir = 1;
}
return 0;
}
/**
* @brief 设置LED的自定义状态
*
* @attention 时间应为控制任务调度周期的倍数
* @param[in] led 指定指示灯
* @param[in] ... 亮灭时间参数:
* > 0, 亮的持续时间
* < 0, 灭的持续时间
* = 0, 可变参数设置结束
* @return 0,成功; -1,失败
*/
int cotLed_Custom(led_t led, ...)
{
uint8_t bits;
uint8_t offset = 0;
uint8_t validBits = 0;
va_list timeList;
int32_t time;
uint16_t interval = 0xffff;
if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum)
{
return -1;
}
va_start(timeList, led);
do
{
time = va_arg(timeList, int32_t);
if (time != 0 && LED_ABS(time) < interval)
{
interval = (uint16_t)LED_ABS(time);
}
} while (time != 0);
va_end(timeList);
validBits = 0;
offset = 0;
memset(sg_pLedTable[led].proc.data.state, 0, sizeof(sg_pLedTable[led].proc.data.state));
va_start(timeList, led);
do
{
time = va_arg(timeList, int32_t);
if (LED_ABS(time) != 0)
{
bits = (uint16_t)LED_ABS(time) / interval;
if (time > 0)
{
for (int i = 0; i < bits; i++)
{
sg_pLedTable[led].proc.data.state[offset / 8] |= 0x01 << (offset % 8);
offset++;
}
}
else
{
for (int i = 0; i < bits; i++)
{
sg_pLedTable[led].proc.data.state[offset / 8] |= 0x00 << (offset % 8);
offset++;
}
}
validBits += bits;
}
} while (time != 0);
va_end(timeList);
sg_pLedTable[led].proc.interval = interval;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = validBits;
sg_pLedTable[led].proc.count = 0;
sg_pLedTable[led].proc.isSetCount = 0;
sg_pLedTable[led].proc.defState = 0;
sg_pLedTable[led].proc.isPwm = 0;
return 0;
}
/**
* @brief 设置LED的自定义状态及次数, 最后次数完成后的亮灭状态
*
* @attention 时间应为控制任务调度周期的倍数
* @param[in] led 指定指示灯
* @param[in] count 自定义状态次数,0表示无次数限制
* @param[in] defState 自定义状态次数完成后的亮灭状态
* @param[in] ... 亮灭时间参数:
* > 0, 亮的持续时间
* < 0, 灭的持续时间
* = 0, 可变参数设置结束
* @return 0,成功; -1,失败
*/
int cotLed_CustomWithCount(led_t led, uint8_t count, cotLedState_e defState, ...)
{
uint8_t bits;
uint8_t offset = 0;
uint8_t validBits = 0;
va_list timeList;
int32_t time;
uint16_t interval = 0xffff;
if (sg_pLedTable == NULL || sg_ledNum == 0 || led >= sg_ledNum)
{
return -1;
}
va_start(timeList, defState);
do
{
time = va_arg(timeList, int32_t);
if (time != 0 && LED_ABS(time) < interval)
{
interval = (uint16_t)LED_ABS(time);
}
} while (time != 0);
va_end(timeList);
validBits = 0;
offset = 0;
memset(sg_pLedTable[led].proc.data.state, 0, sizeof(sg_pLedTable[led].proc.data.state));
va_start(timeList, defState);
do
{
time = va_arg(timeList, int32_t);
if (LED_ABS(time) != 0)
{
bits = (uint16_t)LED_ABS(time) / interval;
if (time > 0)
{
for (int i = 0; i < bits; i++)
{
sg_pLedTable[led].proc.data.state[offset / 8] |= 0x01 << (offset % 8);
offset++;
}
}
else
{
for (int i = 0; i < bits; i++)
{
sg_pLedTable[led].proc.data.state[offset / 8] |= 0x00 << (offset % 8);
offset++;
}
}
validBits += bits;
}
} while (time != 0);
va_end(timeList);
sg_pLedTable[led].proc.interval = interval;
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.offset = 0;
sg_pLedTable[led].proc.validBits = validBits;
sg_pLedTable[led].proc.count = count;
sg_pLedTable[led].proc.isSetCount = count == 0 ? 0 : 1;
sg_pLedTable[led].proc.defState = defState == COT_LED_ON ? 1 : 0;
sg_pLedTable[led].proc.isPwm = 0;
return 0;
}
static cotLedState_e ReadPwmLedState(cotLedProc_t *pLed)
{
cotLedState_e eLedState;
if (pLed->data.pwm.tic < pLed->data.pwm.onTime)
{
eLedState = COT_LED_ON;
}
else
{
eLedState = COT_LED_OFF;
}
if (pLed->data.pwm.tic >= BREATHE_PWM_PERIOD)
{
pLed->data.pwm.tic = 0;
}
return eLedState;
}
static void CtrlPwmLedState(cotLedProc_t *pLed)
{
if (pLed->tic > pLed->interval)
{
pLed->tic = 0;
if (pLed->pwmDir)
{
pLed->data.pwm.onTime++;
if (pLed->data.pwm.onTime >= BREATHE_PWM_PERIOD)
{
pLed->pwmDir = 0;
}
}
else
{
pLed->data.pwm.onTime--;
if (pLed->data.pwm.onTime == 0)
{
pLed->pwmDir = 1;
if (pLed->count > 0)
{
pLed->count--;
}
}
}
}
}
/**
* @brief LED控制周期任务
*
* @param[in] sysTime 系统运行时间, 单位毫秒
* @return 0,成功; -1,失败
*/
int cotLed_Ctrl(uint32_t sysTime)
{
uint16_t led;
static uint32_t s_sysTimeBak = 0;
if (sg_pLedTable == NULL || sg_ledNum == 0)
{
return -1;
}
if (s_sysTimeBak == 0)
{
s_sysTimeBak = sysTime;
}
for (led = 0; led < sg_ledNum; led++)
{
TIME_ADD(sg_pLedTable[led].proc.tic, (sysTime - s_sysTimeBak));
if (sg_pLedTable[led].proc.isSetCount)
{
if (sg_pLedTable[led].proc.count == 0)
{
sg_pLedTable[led].proc.curState = sg_pLedTable[led].proc.defState ? COT_LED_ON : COT_LED_OFF;
}
else
{
if (sg_pLedTable[led].proc.isPwm)
{
sg_pLedTable[led].proc.curState = ReadPwmLedState(&sg_pLedTable[led].proc);
}
else
{
sg_pLedTable[led].proc.curState = (cotLedState_e)((sg_pLedTable[led].proc.data.state[sg_pLedTable[led].proc.offset / 8] >> (sg_pLedTable[led].proc.offset % 8)) & 0X01);
}
}
}
else
{
if (sg_pLedTable[led].proc.isPwm)
{
sg_pLedTable[led].proc.curState = ReadPwmLedState(&sg_pLedTable[led].proc);
}
else
{
sg_pLedTable[led].proc.curState = (cotLedState_e)((sg_pLedTable[led].proc.data.state[sg_pLedTable[led].proc.offset / 8] >> (sg_pLedTable[led].proc.offset % 8)) & 0X01);
}
}
if (sg_pLedTable[led].proc.isPwm)
{
TIME_ADD(sg_pLedTable[led].proc.data.pwm.tic, (sysTime - s_sysTimeBak));
CtrlPwmLedState(&sg_pLedTable[led].proc);
}
else
{
if (sg_pLedTable[led].proc.tic >= sg_pLedTable[led].proc.interval)
{
sg_pLedTable[led].proc.tic = 0;
sg_pLedTable[led].proc.offset++;
if (sg_pLedTable[led].proc.offset >= sg_pLedTable[led].proc.validBits)
{
sg_pLedTable[led].proc.offset = 0;
if (sg_pLedTable[led].proc.count > 0)
{
sg_pLedTable[led].proc.count--;
}
}
}
}
}
for (led = 0; led < sg_ledNum; led++)
{
sg_pLedTable[led].pfnLedCtrl(sg_pLedTable[led].proc.curState ? COT_LED_ON : COT_LED_OFF);
}
s_sysTimeBak = sysTime;
return 0;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。