芯源 CW32L010 低功耗呼吸灯驱动代码

该代码已经在项目上推广应用,有需要自取。不多说,直接贴代码,代码中已注释比较清晰,有疑问或不对的地方,欢迎评论区留言。


1、呼吸灯参数配置相关

//呼吸灯感应时模式枚举值
	typedef enum {
			LED_PWM_ACT_OPEN,        //感应时射灯正常点亮
			LED_PWM_ACT_CLOSE        //感应时呼吸灯关闭
	} Led_Pwm_ACT_Status;
	
	//设置为感应时呼吸灯关闭
	#define LED_PWM_ACT_STATUS_SET  LED_PWM_ACT_CLOSE
	
	
		
  // 呼吸灯参数, ;理论一个呼吸循环周期4.5秒
	#define MIN_DUTY       100     // 最小占空比计数(25%)
	#define MAX_DUTY       1000    // 最大占空比计数(100%)
	#define DUTY_STEP      3       // 占空比变化步长
	#define UPDATE_INTERVAL 1     // 占空比更新间隔(定时器周期数)
	#define BREATH_PERIOD_US     1000   // 周期改为10ms(10000us)

	#define  LED_PWM_GPIO_PIN      GPIO_PIN_5       //指示灯绿,PWM输出, 呼吸灯效
	#define  LED_PWM_GPIO_Port     CW_GPIOA

	//呼吸灯工作状态枚举值
	typedef enum {
			LED_PWM_IDLE,        //已初始化,但未开启
			LED_PWM_ON_FIXED,    //固定占空比,常亮无呼吸效果
			LED_PWM_ON_BREATH,   //呼吸灯效果
			LED_PWM_DISABLE      //禁用呼吸指示灯,硬件失能,适用于无指示灯
	} PwmState;

2、硬件初始化

//呼吸灯PB5初始化
void LED_PEM_Conf_Init(void)
{
	PB05_DIGTAL_ENABLE();
    PB05_DIR_OUTPUT();
    PB05_PUSHPULL_ENABLE();
    PB05_AFx_GTIM1CH2();  // 配置PB05复用为GTIM1 CH2
		
	//GTIM定时器初始化
	GTIM_InitTypeDef GTIM_InitStruct = {0};
    GTIM_OCModeCfgTypeDef GTIM_OCModeCfgStruct = {DISABLE,DISABLE,0};

    /* 定时器时基配置(保持1MHz计数频率) */
    GTIM_InitStruct.AlignMode = GTIM_ALIGN_MODE_EDGE;          // 边沿对齐模式
    GTIM_InitStruct.ARRBuffState = GTIM_ARR_BUFF_EN;           // 使能自动重装载缓冲
    GTIM_InitStruct.Direction = GTIM_DIRECTION_UP;             // 向上计数
    GTIM_InitStruct.EventOption = GTIM_EVENT_NORMAL;           // 正常事件模式
    GTIM_InitStruct.Prescaler = 8 - 1;                         // 关键修改:8分频(8MHz/8=1MHz)
    GTIM_InitStruct.PulseMode = GTIM_PULSE_MODE_DIS;           // 禁用单次脉冲模式
    GTIM_InitStruct.ReloadValue = BREATH_PERIOD_US - 1;                  // 周期值=1000-1=999(1ms周期)
    GTIM_InitStruct.UpdateOption = GTIM_UPDATE_DIS;             // 使能更新事件
    GTIM_TimeBaseInit(CW_GTIM1, &GTIM_InitStruct);             // 初始化定时器
    
    /* 配置CH2通道为PWM模式 */
    GTIM_OCModeCfgStruct.FastMode = DISABLE;                    // 禁用快速模式
    GTIM_OCModeCfgStruct.OCMode = GTIM_OC_MODE_PWM1;            // PWM模式1
    GTIM_OCModeCfgStruct.OCPolarity = GTIM_OC_POLAR_NONINVERT;  // 输出极性非反相(高电平有效)
    GTIM_OCModeCfgStruct.PreloadState = DISABLE;                // 使能预装载
    GTIM_OC2ModeCfg(CW_GTIM1, &GTIM_OCModeCfgStruct);           // 配置CH2通道
    
    /* 设置初始占空比并使能输出 */
    GTIM_SetCompare2(CW_GTIM1, PosWidth - 1);  // 初始CH2占空比100%
    GTIM_OC2Cmd(CW_GTIM1, ENABLE);             // 使能CH2输出
    //GTIM_ITConfig(CW_GTIM1, GTIM_IT_UPDATA, ENABLE);  // 使能更新中断
	//NVIC_SetPriority(GTIM1_IRQn, 0);           // 高优先级确保响应及时
	//NVIC_EnableIRQ(GTIM1_IRQn);              //只产生PWM不触发中断;
    GTIM_Cmd(CW_GTIM1, ENABLE);                // 启动定时器
}

3、呼吸灯定时刷新PWM占空比,实现呼吸效果

//呼吸灯更新占空比
void LED_PWM_CTR_SUB(void){
		/* 静态计数器控制更新频率 */
							
				/* 根据方向调整占空比 */
				if(Dir)  // 方向1:占空比增大(从25%到100%)
				{
						PosWidth += DUTY_STEP;
						if(PosWidth >= MAX_DUTY)
						{
								PosWidth = MAX_DUTY;
								Dir = 0;  // 到达最大值,切换方向
						}
				}else{ // 方向0:占空比减小(从100%到25%)
						PosWidth -= DUTY_STEP;
						if(PosWidth <= MIN_DUTY)
						{
								PosWidth = MIN_DUTY;
								Dir = 1;  // 到达最小值,切换方向
						}
				}
				/* 更新PWM占空比 */
				GTIM_SetCompare2(CW_GTIM1, PosWidth - 1);   //CH2  占空比更新
}

// 新增:开启呼吸灯
void BreathLED_Start(void)
{
    // 恢复PWM输出
    GTIM_OC1Cmd(CW_GTIM1, ENABLE);
    // 恢复初始占空比
    PosWidth = MAX_DUTY;
    Dir = 0;
    GTIM_SetCompare1(CW_GTIM1, PosWidth - 1);
}

// 新增:关闭呼吸灯
void BreathLED_Stop(void)
{
    // 关闭PWM输出,可选择保持熄灭或常亮
    GTIM_OC2Cmd(CW_GTIM1, DISABLE);
    // 确保LED熄灭
    PB05_SETLOW();  // 根据硬件电路可能需要改为PB05_SETHIGH()
}

4、使用中断的方式定时更新占空比,这里使用的RTC闹钟

//配置时钟
void RCC_Conf_Init(void)
{
    IWDT_InitTypeDef IWDT_InitStruct = {0};

	/* HSI和 LSI使能 */
    SYSCTRL_HSI_Enable(SYSCTRL_HSIOSC_DIV6);   //48/6=8;  HSIOSC = 8MHz; HSI = 8MHz;
    SYSCTRL_LSI_Enable();

    /* 1. 设置HCLK和PCLK的分频系数 */
    SYSCTRL_HCLKPRS_Config(SYSCTRL_HCLK_DIV1);
    SYSCTRL_PCLKPRS_Config(SYSCTRL_PCLK_DIV1);
  
    SYSCTRL_SystemCoreClockUpdate(8000000);    //更新系统核心时钟
		
    /* 2. 配置外设时钟 */
    __SYSCTRL_IWDT_CLK_ENABLE();      //IWDT时钟使能
    __SYSCTRL_GPIOA_CLK_ENABLE();     //GPIOA时钟使能
	__SYSCTRL_GPIOB_CLK_ENABLE();     //GPIOB时钟使能
	__SYSCTRL_GTIM1_CLK_ENABLE();     // GTIM1时钟使能
	//__SYSCTRL_I2C_CLK_ENABLE();       //IIC时钟使能
	__SYSCTRL_RTC_CLK_ENABLE();       // RTC时钟使能	
	//__SYSCTRL_UART1_CLK_ENABLE();     //UART1时钟使能
		
	//初始化IWDT
	IWDT_InitStruct.IWDT_ITState = ENABLE;
    IWDT_InitStruct.IWDT_OverFlowAction = IWDT_OVERFLOW_ACTION_RESET;   //超时复位, IWDT_OVERFLOW_ACTION_INT只触发中断,须手动复位;
    IWDT_InitStruct.IWDT_Pause = IWDT_SLEEP_CONTINUE;          //休眠状态保持持续计数
    IWDT_InitStruct.IWDT_Prescaler = IWDT_Prescaler_DIV512;    // IWDT使用LSI为计时时钟,分频后计时间隔为15.6ms
    IWDT_InitStruct.IWDT_ReloadValue = IWDT_2_SECS;            // 2s,超时未喂狗将溢出
    IWDT_InitStruct.IWDT_WindowValue = 0xFFF;   //设置窗口值,0xFFF表示关闭窗口功能,任何时候都可以喂狗;其他值,计数器值小于窗口值时才能喂狗;

    IWDT_Init(&IWDT_InitStruct);
}

5、interrupts_cw32l010.c 中中断处理函数实现


/**
 * @brief This funcation handles RTC
 */
void RTC_IRQHandler(void)
{
    /* USER CODE BEGIN */
		USER_RTC_IRQHandler();  //用户程序,实现10MS定时
    /* USER CODE END */
}

6、处理中断,然后在while中根据cnt_wakeup标志位,定时调用LED_PWM_CTR_SUB()函数:

//RTC中断服务函数(每10ms触发一次,翻转指示灯)
void USER_RTC_IRQHandler(void)
{
		
    // 检查自动唤醒中断标志
    if(RTC_GetITState(RTC_IT_AWTIMER) != RESET)
    {
        // 清除中断标志
				//
				RTC_ClearITPendingBit(RTC_IT_AWTIMER);
        cnt_wakeup = 1;  //累计唤醒次数
				                      // 开启全局中断
    }
		
}

7、低功耗实现,在循环结束后,喂狗休眠,休眠前为了实现更低的功耗,可能需要按需关闭不必要的外设,特别是时钟,并确保相关引脚的电平状态正常。唤醒后需重新配置相关外设和时钟。

int32_t main(void)
{
	//初始化代码,执行一次的代码在下方:

    //循环执行
	while(1){
		if(cnt_wakeup){
			cnt_wakeup = 0;
			//10MS RTC定时时间到了>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
			tick_10ms++;	
			if(tick_10ms % 5 == 0){
			    //每50毫秒执行一次的任务****************
							
			}		
			//每10ms 执行一次的任务写下方***************
						
	    }
		//定时喂狗:每次唤醒都喂狗一次
		IWDT_Refresh();   //100MS喂狗一次;使用大于做判断比取模更合理,避免中断导致的累加
				
		//休眠判断
		if(cnt_wakeup == 0 && cnt_gpio_int == 0) __WFI();  //  无待处理中断,进入低功耗,等待中断唤醒	
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值