|
使用方式:
主要有三个函数:
vLedInit,用来初始化灯的模式,亮度调节,呼吸灯,闪烁,显示1字节数据,四种模式。支持pwm输出控制led,或者用io模拟pwm实现呼吸灯效果。
ucLedTriggerMode,比如当前处于呼吸灯模式,由于响应一些按键,需要灯做出响应,可以用这个实现,用来触发或者永久修改灯的模式
lLedRun,周期运行,暂时只支持1毫秒一次运行。
举例1,IO模式:
LedCtrl_T tLed ;
main()
{
vLedInit(&tLed,0,1,BREATHING,2);//输出0对应最大灯亮度,输出1代表熄灭灯,呼吸灯模式,2秒周期。
while(1)
{
LED_GPIO = lLedRun(&tLed);
vTaskDelay(1);//1ms
}
}
举例2,PWM模式:
LedCtrl_T tLed ;
main()
{
vLedInit(&tLed,255,0,BREATHING,2);//输出255代表最大亮度,0代表熄灭灯,呼吸灯模式,2秒周期。
while(1)
{
set_pwm_val(lLedRun(&tLed));
vTaskDelay(1);//1ms
}
}
- /******************************************************************
- * 文件名: led_ctrl.c
- * 内容简述:
- * 控制led灯的亮灭,可实现4种状态,亮度调整,闪烁,呼吸灯,字节显示
- * 文件历史:
- * 版本号 日期 作者 说明
- ******************************************************************/
- #include "led_ctrl.h"
- #define MIN_BRIGHTNESS_HZ 40 //亮度控制频率,测试电路板上led灯在40hz看起来不闪烁
- #define MAX_TWINKLING_HZ 50 //闪烁频率,赫兹
- #define MIN_TWINKLING_HZ 1 //闪烁频率,赫兹
- #define MAX_BREATHING_S 10 //呼吸灯时间,秒
- #define MIN_BREATHING_S 1 //呼吸灯时间,秒
- #define START_BIT_DELAY_MS 1000 //启动位延时时间,毫秒
- #define ONE_BIT_DELAY_MS 1000 //1位显示时间
- #define STOP_BIT_DELAY_MS 1000 //停止位延时时间,毫秒
- #define BIT_1_TWINKLING_HZ 20 //1的显示频率
- #define BIT_0_TWINKLING_HZ 5 //0的显示频率
- static int32_t lLedBrightnessCtrl(LedCtrl_T *tpLed);
- static int32_t lLedTwinklingCtrl(LedCtrl_T *tpLed);
- static int32_t lLedBreathingCtrl(LedCtrl_T *tpLed);
- static int32_t lLedDisplayByteCtrl(LedCtrl_T *tpLed);
- /******************************************************************
- * 函数名: ledInit()
- * 功 能: 初始化配置
- * 输 入:
- * tpLed:led指针
- * lOnVal:设置点亮电平值,如果是pwm,这两个值的为pwm定时器重装数
- * lOffVal:设置熄灭电平值,如果是pwm,这两个值的为pwm定时器重装数
- * eMode:
- BRIGHTNESS 亮度
- TWINKLING 闪烁
- BREATHING 呼吸灯
- DISPLAYBYTE 字节显示
- * ucValue:
- BRIGHTNESS 亮度范围:0-100,代表0%-100%
- TWINKLING 闪烁范围:Min_TWINKLING - MAX_TWINKLING,频率,单位Hz
- BREATHING 呼吸灯范围:Min_BREATHING - MAX_BREATHING,周期,单位秒
- DISPLAYBYTE 字节显示范围:0x00~0xFF,起始位1秒常亮,低位在前显示,1快闪,0慢闪,停止位2秒常灭
- * 输 出: 无
- */
- void vLedInit(LedCtrl_T *tpLed,int32_t lOnVal,int32_t lOffVal,LED_MODE_E eMode,uint8_t ucValue)
- {
- tpLed->tConfig.lOnVal = lOnVal;
- tpLed->tConfig.lOffVal = lOffVal;
- tpLed->eMode = eMode;
- tpLed->ucValue = ucValue;
- tpLed->tPriData.lTimeCount_ms = 0;
- tpLed->tPriData.lCurDispBitNum = 0;
- tpLed->tPriData.lTimeTrgger_ms = -1;
- tpLed->tPriData.eModeExp = tpLed->eMode;
- tpLed->tPriData.ucValueExp = tpLed->ucValue;
- tpLed->tPriData.eModeBackup = tpLed->eMode;
- tpLed->tPriData.ucValueBackup = tpLed->ucValue;
- }
- /******************************************************************
- * 函数名: vLedTriggerMode()
- * 功 能: 触发led模式,永久修改模式,或者触发一定时间再恢复之前模式
- * 输 入:
- * tpLed:led指针
- * eMode:
- BRIGHTNESS 亮度
- TWINKLING 闪烁
- BREATHING 呼吸灯
- DISPLAYBYTE 字节显示
- * ucValue:
- BRIGHTNESS 亮度范围:0-100,代表0%-100%
- TWINKLING 闪烁范围:Min_TWINKLING - MAX_TWINKLING,频率,单位Hz
- BREATHING 呼吸灯范围:Min_BREATHING - MAX_BREATHING,周期,单位秒
- DISPLAYBYTE 字节显示范围:0x00~0xFF,起始位1秒常亮,低位在前显示,1快闪,0慢闪,停止位2秒常灭
- * lTime:触发新的模式持续时间,单位,毫秒。注意,如果为0,则永久修改模式
- * 输 出: 成功设置,返回0,失败,返回1
- */
- uint8_t ucLedTriggerMode(LedCtrl_T *tpLed,LED_MODE_E eMode,uint8_t ucValue,int32_t lTime_ms)
- {
- if(tpLed->tPriData.lTimeTrgger_ms == -1)
- {
- tpLed->tPriData.eModeExp = eMode;
- tpLed->tPriData.ucValueExp = ucValue;
- if(lTime_ms == 0)
- {
- tpLed->tPriData.eModeBackup = tpLed->eMode;
- tpLed->tPriData.ucValueBackup = tpLed->ucValue;
- }
- else
- {
- tpLed->tPriData.eModeBackup = tpLed->tPriData.eModeExp;
- tpLed->tPriData.ucValueBackup = tpLed->tPriData.ucValueExp;
- }
- tpLed->tPriData.lTimeTrgger_ms = lTime_ms;
- return 0;
- }
- else
- {
- return 1;
- }
- }
- /******************************************************************
- * 函数名: lLedSoftPWMGenerator()
- * 功 能: 模拟PWM发生器
- * 输 入:
- * lTimeCount_ms:定时器时间,可以大于lPeriodSet_ms,会自动计算余数用于调整占空比,毫秒
- * lPeriodSet_ms:周期时间,毫秒
- * lDutyRatio_PCT:百分比,0-100
- * 输 出: 当前输出电平,1高,0低
- */
- static int32_t lLedSoftPWMGenerator(int32_t lTimeCount_ms,int32_t lPeriodSet_ms,uint8_t ucDutyRatioSet_PCT)
- {
- int32_t lHighLevelTime_ms = lPeriodSet_ms * ucDutyRatioSet_PCT / 100;
- if((lTimeCount_ms % lPeriodSet_ms) < lHighLevelTime_ms)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- /******************************************************************
- * 函数名: lLedBrightnessCtrl()
- * 功 能: 亮度控制
- * 输 入:
- * tpLed:led指针
- * 输 出: IO控制量
- */
- static int32_t lLedBrightnessCtrl(LedCtrl_T *tpLed)
- {
- int32_t lReturnVal = 0;
- int32_t lTempCheck = tpLed->tConfig.lOnVal - tpLed->tConfig.lOffVal;
- if(lTempCheck >= -1 && lTempCheck <= 1)//io模式
- {
- int32_t lPeriod_ms = (int32_t)(1000 / MIN_BRIGHTNESS_HZ);
- int32_t lPWMLevel = lLedSoftPWMGenerator(tpLed->tPriData.lTimeCount_ms,lPeriod_ms,tpLed->ucValue);
- lReturnVal = lPWMLevel == 1 ? tpLed->tConfig.lOnVal : tpLed->tConfig.lOffVal;
- tpLed->tPriData.lTimeCount_ms++;
- if(tpLed->tPriData.lTimeCount_ms > lPeriod_ms)
- {
- tpLed->tPriData.lTimeCount_ms = 0;
- }
- }
- else//pwm模式
- {
- if(lTempCheck > 1)
- {
- lReturnVal = tpLed->ucValue / 100 * lTempCheck + tpLed->tConfig.lOffVal;
- }
- else if(lTempCheck < -1)
- {
- lReturnVal = tpLed->ucValue / 100 * -lTempCheck - tpLed->tConfig.lOffVal;
- }
- }
- return lReturnVal;
- }
- /******************************************************************
- * 函数名: lLedTwinklingCtrl()
- * 功 能: 闪烁控制
- * 输 入:
- * tpLed:led指针
- * 输 出: IO控制量
- */
- static int32_t lLedTwinklingCtrl(LedCtrl_T *tpLed)
- {
- int32_t lTemp_Hz = 0;
- int32_t lReturnVal = 0;
- int32_t lPeriod_ms = 0;
- int32_t lPWMLevel = 0;
- lTemp_Hz = tpLed->ucValue < MIN_TWINKLING_HZ ? MIN_TWINKLING_HZ : tpLed->ucValue;
- lTemp_Hz = tpLed->ucValue > MAX_TWINKLING_HZ ? MAX_TWINKLING_HZ : tpLed->ucValue;
- lPeriod_ms = 1000 / lTemp_Hz;
- lPWMLevel = lLedSoftPWMGenerator(tpLed->tPriData.lTimeCount_ms,lPeriod_ms,50);
- lReturnVal = lPWMLevel == 1 ? tpLed->tConfig.lOnVal : tpLed->tConfig.lOffVal;
- tpLed->tPriData.lTimeCount_ms++;
- if(tpLed->tPriData.lTimeCount_ms > lPeriod_ms)
- {
- tpLed->tPriData.lTimeCount_ms = 0;
- }
- return lReturnVal;
- }
- /******************************************************************
- * 函数名: lLedBreathingCtrl()
- * 功 能: 呼吸灯控制
- * 输 入:
- * tpLed:led指针
- * 输 出: IO控制量
- */
- static int32_t lLedBreathingCtrl(LedCtrl_T *tpLed)
- {
- int32_t lPeriod_ms = 0;
- int32_t lRiseUpTime_ms = 0;
- int32_t lReturnVal = 0;
- float fBrightnessPCT = 0.0f;
- lPeriod_ms = tpLed->ucValue < MIN_BREATHING_S ? MIN_BREATHING_S * 1000 : tpLed->ucValue * 1000 ;
- lPeriod_ms = tpLed->ucValue > MAX_BREATHING_S ? MAX_BREATHING_S * 1000 : tpLed->ucValue * 1000 ;
- lRiseUpTime_ms = lPeriod_ms / 2;
- //亮度切换
- if(tpLed->tPriData.lTimeCount_ms <= lRiseUpTime_ms)//由暗变亮
- {
- fBrightnessPCT = (float)(tpLed->tPriData.lTimeCount_ms) / (float)lRiseUpTime_ms;
- }
- else if(tpLed->tPriData.lTimeCount_ms > lRiseUpTime_ms && tpLed->tPriData.lTimeCount_ms <= lPeriod_ms)//由亮变暗
- {
- fBrightnessPCT = (float)(lPeriod_ms - tpLed->tPriData.lTimeCount_ms) / (float)lRiseUpTime_ms;
- }
- else
- {
- fBrightnessPCT = 0.0f;
- tpLed->tPriData.lTimeCount_ms = 0;
- }
- //调光曲线
- fBrightnessPCT = fBrightnessPCT * fBrightnessPCT;
- //亮度控制
- {
- int32_t lTempCheck = tpLed->tConfig.lOnVal - tpLed->tConfig.lOffVal;
- if(lTempCheck >= -1 && lTempCheck <= 1)//io模式
- {
- int32_t lPeriod_ms = (int32_t)(1000 / MIN_BRIGHTNESS_HZ);
- int32_t lPWMLevel = lLedSoftPWMGenerator(tpLed->tPriData.lTimeCount_ms,lPeriod_ms,(uint8_t)(fBrightnessPCT * 100.0f));
- lReturnVal = lPWMLevel == 1 ? tpLed->tConfig.lOnVal : tpLed->tConfig.lOffVal;
- }
- else//pwm模式
- {
- if(lTempCheck > 1)
- {
- lReturnVal = (int32_t)(fBrightnessPCT * (float)lTempCheck + (float)tpLed->tConfig.lOffVal);
- }
- else if(lTempCheck < -1)
- {
- lReturnVal = (int32_t)(fBrightnessPCT * -(float)lTempCheck - (float)tpLed->tConfig.lOffVal);
- }
- }
- }
- tpLed->tPriData.lTimeCount_ms++;
- return lReturnVal;
- }
- /******************************************************************
- * 函数名: lLedDisplayByteCtrl()
- * 功 能: 字节显示控制
- * 输 入:
- * tpLed:led指针
- * 输 出: IO控制量
- */
- static int32_t lLedDisplayByteCtrl(LedCtrl_T *tpLed)
- {
- int32_t lReturnVal = 0;
- if(tpLed->tPriData.lCurDispBitNum == 0)
- {
- tpLed->tPriData.lTimeCount_ms = 0;
- tpLed->tPriData.lCurDispBitNum++;
- }
- else if(tpLed->tPriData.lCurDispBitNum == 1)//起始位,常亮
- {
- lReturnVal = tpLed->tConfig.lOnVal;
- if(tpLed->tPriData.lTimeCount_ms > START_BIT_DELAY_MS)
- {
- tpLed->tPriData.lTimeCount_ms = 0;
- tpLed->tPriData.lCurDispBitNum++;
- }
- }
- else if(tpLed->tPriData.lCurDispBitNum >= 2 && tpLed->tPriData.lCurDispBitNum <= 9)//数据位
- {
- uint8_t ucCurBitDisplayVal = (tpLed->ucValue >> (tpLed->tPriData.lCurDispBitNum - 2)) & 0x01;
- int32_t lPeriod_ms = ucCurBitDisplayVal == 1 ? 1000 / BIT_1_TWINKLING_HZ : 1000 / BIT_0_TWINKLING_HZ;
- int32_t lPWMLevel = lLedSoftPWMGenerator(tpLed->tPriData.lTimeCount_ms,lPeriod_ms,50);
- lReturnVal = lPWMLevel == 1 ? tpLed->tConfig.lOnVal : tpLed->tConfig.lOffVal;
- if(tpLed->tPriData.lTimeCount_ms > ONE_BIT_DELAY_MS)
- {
- tpLed->tPriData.lTimeCount_ms = 0;
- tpLed->tPriData.lCurDispBitNum++;
- }
- }
- else if(tpLed->tPriData.lCurDispBitNum == 10)//停止位
- {
- lReturnVal = tpLed->tConfig.lOffVal;
- if(tpLed->tPriData.lTimeCount_ms > STOP_BIT_DELAY_MS)
- {
- tpLed->tPriData.lTimeCount_ms = 0;
- tpLed->tPriData.lCurDispBitNum++;
- }
- }
- else
- {
- tpLed->tPriData.lCurDispBitNum = 0;
- }
- tpLed->tPriData.lTimeCount_ms++;
- return lReturnVal;
- }
- /******************************************************************
- * 函数名: lLedRun()
- * 功 能: 运行led,并返回IO控制量
- * 输 入:
- * tpLed:led指针
- * 输 出: IO控制量
- */
- int32_t lLedRun(LedCtrl_T *tpLed)
- {
- if(tpLed->tPriData.lTimeTrgger_ms == 0)
- {
- tpLed->eMode = tpLed->tPriData.eModeBackup;
- tpLed->ucValue = tpLed->tPriData.ucValueBackup;
- }
- else if(tpLed->tPriData.lTimeTrgger_ms > 0)
- {
- tpLed->eMode = tpLed->tPriData.eModeExp;
- tpLed->ucValue = tpLed->tPriData.ucValueExp;
- }
- else
- {
- tpLed->tPriData.lTimeTrgger_ms = -1;
- }
- tpLed->tPriData.lTimeTrgger_ms--;
- switch(tpLed->eMode)
- {
- case BRIGHTNESS: //亮度范围:0-100,代表0%-100%
- return lLedBrightnessCtrl(tpLed);
- case TWINKLING: //闪烁范围:Min_TWINKLING - MAX_TWINKLING,频率,单位Hz
- return lLedTwinklingCtrl(tpLed);
- case BREATHING: //呼吸灯范围:Min_BREATHING - MAX_BREATHING,周期,单位秒
- return lLedBreathingCtrl(tpLed);
- case DISPLAYBYTE: //字节显示
- return lLedDisplayByteCtrl(tpLed);
- default:
- return tpLed->tConfig.lOffVal;
- }
- }
复制代码
- /******************************************************************
- * 文件名: led_ctrl.h
- * 内容简述:
- * 控制led灯的亮灭,可实现4种状态,亮度调整,闪烁,呼吸灯,字节显示
- * 文件历史:
- * 版本号 日期 作者 说明
- ******************************************************************/
- #ifndef __LED_CTRL_H
- #define __LED_CTRL_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include <stdint.h>
- /*枚举led驱动模式*/
- typedef enum tagLED_MODE_E
- {
- BRIGHTNESS = 0, //亮度
- TWINKLING, //闪烁
- BREATHING, //呼吸灯
- DISPLAYBYTE //字节显示
- }LED_MODE_E;
- /*根据实际硬件,设置lOnVal和lOffVal,IO为1或者0,PWM控制为定时器重装值*/
- typedef struct tagLedConfig_T
- {
- int32_t lOnVal;
- int32_t lOffVal;
- }LedConfig_T;
- /*运行所需内部变量*/
- typedef struct tagLedPrivateData_T
- {
- int32_t lTimeCount_ms; //内部计时器
- int32_t lCurDispBitNum; //字节显示模式中,用于标记当前显示的是哪位
- int32_t lTimeTrgger_ms; //触发,计时器
- LED_MODE_E eModeExp; //触发,期望模式
- uint8_t ucValueExp; //触发,期望模式值
- LED_MODE_E eModeBackup; //触发,备份当前模式
- uint8_t ucValueBackup; //触发,备份当前值
- }LedPrivateData_T;
- /*描述一个led*/
- typedef struct tagLedCtrl_T
- {
- LED_MODE_E eMode;
- uint8_t ucValue;
- LedConfig_T tConfig;
- LedPrivateData_T tPriData;
- }LedCtrl_T;
- /*外部调用函数*/
- void vLedInit(LedCtrl_T *tpLed,int32_t lOnVal,int32_t lOffVal,LED_MODE_E eMode,uint8_t ucValue);
- uint8_t ucLedTriggerMode(LedCtrl_T *tpLed,LED_MODE_E eMode,uint8_t ucValue,int32_t lTime_ms);
- int32_t lLedRun(LedCtrl_T *tpLed);
- #ifdef __cplusplus
- }
- #endif
- #endif
复制代码 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
如果天空是黑暗的,那就摸黑生存;
如果发出声音是危险的,那就保持沉默;
如果自觉无力发光,那就蜷伏于牆角。
但是,不要习惯了黑暗就为黑暗辩护;
也不要为自己的苟且而得意;
不要嘲讽那些比自己更勇敢的人。
我们可以卑微如尘土,但不可扭曲如蛆虫。
|