关注分享主机优惠活动
国内外VPS云服务器

实现Breathing Light的C语言(HAL库)(Breathing Light C程序)

摘要:我不会详细解释块。 单击此处了解有关呼吸光的更多信息。 定时器底部回调初始化参数的说明。 退货是不可能的。 没有解释。 这是定时器中断处理函数的参数。 退货是不可能的。 没有呼吸灯。 请注意,电平反转是不可能的,因为中断生成得太快。 上面的代码是呼吸灯引脚的中断处理函数。 电平反转。

1、呼吸灯原理

通过控制并不断改变灯光的亮度,可以实现呼吸灯。 如果变化的频率超过24帧,肉眼看来会逐渐变暗、变亮。

2、通过PWM控制亮度

PWM设置一定时间内亮度的占空比。 如果百分比很亮,则人眼看起来很亮,反之亦然。 我们不会详细讨论 PWM 模块。 让我们详细了解一下呼吸灯的 PWM。

/* * 描述:呼吸灯 PWM 初始化* 参数: * 无 * 返回值: * 无 */void bspBreathLedTIMInit(void){ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; 0 }; g_breathled_tim_handle.Instance = TIM2; g_breathled_tim_handle.Init.Prescaler = 83; g_breathled_tim_handle.Init.CounterMode = TIM_COUNTERMODE_UP;d = (BREATHLED_PWM_VALUE - 1); g_breathled_tim_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; g_breathled_tim_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&g_breathled_tim_handle) HAL_OK) { Error_Handler(); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if ( HAL_TIM_ConfigClockSource (&g_breathled_tim_handle) , &sClockSourceConfig) != HAL_OK) { Error_Handler(); if (HAL_TIM_PWM_Init(&g_breathled_tim_handle) != HAL_OK) { Error_Handler(); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMO DE_DISABLE同步(&g_breathled_tim_handle,&sMasterConfig)! HAL_OK) { Error_Handler(); sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; 如果 (HAL_TIM_PWM_ConfigChannel(&g_breathled_tim_handle, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { ); ct ; BREATHLED_GPIO_CLK_ENABLE(); /* TIM2 GPIO 设置 * PA3 [ k4]-----> TIM2_CH4 */ GPIO_InitStruct.Pin = BREATHLED_GPIO_GREEN_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ _VERY_HIGH; GPIO_InitStruct 。 Alternative = GPIO_AF1_TIM2; HAL_GPIO_Init(BREATHLED_GPIO_TYPE, &GPIO_InitStruct); HAL_TIM_Base_Start_IT(&g_breathled_tim_handle);}

我使用 PA3 引脚和定时器 2 进行实验。 时钟频率为84MHz,预分频器设置为(84-1)=83,这里的周期设置为(10000-1)=9999。定时器的周期为(83 + 1) * (9999 + 1) / 84000000 = 0.01s = 10ms。 根据自己的实际情况计算出这个频率,并尽量设置成看起来流畅,不会对系统造成太多的干扰。

/* * 描述:初始化回调底层的定时器 * 参数: * None * 返回值: * None */void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base){ if (htim_base->Instance == TIM2) { __HAL_RCC_TIM2_CLK_ENABLE () ; HAL_NVIC_SetPriority(TIM2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(TIM2_IRQn); }}/* * 描述:定时器中断处理函数* 参数: * 无* 返回值: * 无*/void TIM2_IRQHandler(&g_breathled_tim_handle) ); HAL_TIM_PeriodElapsedCallback(&g_breathled_tim_handle);}void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ /* 用户代码开始回调 0 */ /* 用户代码结束回调 0 */ if (htim[ k4]>Instance == TIM11) { HAL_IncTick() ; } //呼吸光 else if (htim->Instance == TIM2) {//请注意,由于中断生成得太快,因此不可能反转。 //Invert LED level HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_3); } /* USER CODE BEGIN Callback 1 */ /* USER CODE END Callback 1 */}

以上代码是反转呼吸灯端子电平的中断处理函数。 是。 一旦设置了占空比参数,定时器就会自动触发中断并反转电平。

3.呼吸灯亮度曲线 //PWM设置的周期值 #define BREATHLED_PWM_VALUE 10000 //呼吸灯x轴变暗或变亮的步数 #define BREATHLED_X_DIVIDE 100 //总步数 呼吸灯X Axis #define BREATHLED_X_TOTAL (BREATHLED_X_DIVIDE * 2)//Y轴呼吸灯比例 #define BREATHLED_Y_RATIO (BREATHLED_PWM_VALUE / BREATHLED_X_DIVIDE)//亮度变化频率,即帧数(毫秒) #define BREATHLED_FRAMES_MS10

一些宏通过定义, BREATHLED_PWM_VALUE 值由 PWM 设置为高于周期值。 BREATHLED_X_DIVIDE 是 X 轴,是 X 轴变暗或变亮的步数。 BREATHLED_X_TOTAL 是 x 轴上一个周期内变暗和变亮步骤的总数。 BREATHLED_Y_RATIO 是 y 轴比率。 BREATHLED_FRAMES_MS 亮度变化频率。 请注意,该值必须大于 24 帧,或小于 40 毫秒。 为了让它更平滑,适当增加帧数会让呼吸光看起来更平滑。

3.1 直线折线

y = 10000 表示占空比为 100%,x 轴为时间。

/* * 描述:呼吸灯功能,y轴值取自x轴* 参数: * [in] x x轴,时间* 返回值: * y轴值,PWM值* / static unsigned int BreathLedCurve(unsigned int x){ unsigned int y; if (x < BREATHLED_X_DIVIDE) { y = BREATHLED_Y_RATIO * x; } else { y = -BREATHLED_Y_RATIO * (x - BREATHLED_X_TOTAL); } / * * 描述:呼吸灯过程 * 参数: * 无 * 返回值: * 无 */void BreathLedProgress(void){ static unsigned int time_x = 0; unsigned int pwm_value_y = 0 while (1) { time_x = (time_x + 1 ) % BREATHLED_X_TOTAL; = BreathLedcurve(time_x); // 改变值班占用率 __hal_tim_setcompare(&g_breathled_tim_handle, tim_channel_4, pwm_value_y); Time_x % Breathled_x_divide == 0) {syslay(500);}}}

实现如下如何:见上文。 然而,人眼的感知不是线性的。 这是因为,在昏暗的区域中,即使光通量变化很小,人眼也会感知到很大的光通量变化,但在光通量相对较大的区域中,会感知到很大的光通量变化。 即使在跳跃时,人眼感知到的光通量也不会发生太大变化。 简单理解就是,人眼对暗亮度敏感,但对亮度的多少不敏感。 我尝试的时候发现,由亮到暗的时候感觉很长,由暗到亮的时候感觉很短,突然感觉好像变亮了。 这条曲线是有缺陷的。

3.2 呼吸光曲线

从上图可以看出,当亮度由暗变亮时,程序的呼吸光曲线应该如图3所示。 ,这里我们使用二次曲线。 如果可能的话,可以使用sin函数,但效果可能类似。 然而,由于 sin 函数比二次方程需要更多的计算,因此我们决定根据计算将其实现为二次曲线。 通过这条曲线,你可以感受到与直线折线相同的效果。 因此,还需要减少由暗到亮变化时亮度变化的频率,使其在人眼看来平滑。

如果您愿意,您可以下载呼吸光曲线代码。 或者,有能力的人可以参考上面的代码来实现曲线。

未经允许不得转载:主机频道 » 实现Breathing Light的C语言(HAL库)(Breathing Light C程序)

评论 抢沙发

评论前必须登录!