[DemoCode下载] PWM通过中断实现呼吸灯的方法

[复制链接]
1267|5
 楼主| 643757107 发表于 2024-2-19 21:17 | 显示全部楼层 |阅读模式
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * $Revision: 10 $
  5. * $Date: 18/07/17 6:05p $
  6. * @brief
  7. *           Change duty cycle of output waveform to show breathing effect of
  8.                          Red LED.
  9. *
  10. * SPDX-License-Identifier: Apache-2.0
  11. * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
  12. *
  13. ******************************************************************************/
  14. #include <stdio.h>
  15. #include "NuMicro.h"

  16. /*---------------------------------------------------------------------------------------------------------*/
  17. /* Macro, type and constant definitions                                                                    */
  18. /*---------------------------------------------------------------------------------------------------------*/
  19. #define PWM_Prescaler       48
  20. #define PWM_Period          1999

  21. /*---------------------------------------------------------------------------------------------------------*/
  22. /* Global variables                                                                                        */
  23. /*---------------------------------------------------------------------------------------------------------*/
  24. volatile uint8_t    g_u8Forward = 1;
  25. volatile uint32_t g_u32BreathingCount = 0;

  26. void SYS_Init(void)
  27. {
  28.     /*---------------------------------------------------------------------------------------------------------*/
  29.     /* Init System Clock                                                                                       */
  30.     /*---------------------------------------------------------------------------------------------------------*/
  31.     /* Enable HIRC clock */
  32.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  33.     /* Waiting for HIRC clock ready */
  34.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  35.     /* Switch HCLK clock source to HIRC and HCLK source divide 1 */
  36.     CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

  37.     /* Enable PWM1 module clock */
  38.     CLK_EnableModuleClock(PWM1_MODULE);

  39.     /*---------------------------------------------------------------------------------------------------------*/
  40.     /* PWM clock frequency configuration                                                                       */
  41.     /*---------------------------------------------------------------------------------------------------------*/
  42.     /* Set PLL clock as 96 MHz from HIRC/4 */
  43.     CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC_DIV4, 96000000);

  44.     /* Waiting for PLL clock ready */
  45.     CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);

  46.     /* Select HCLK clock source as PLL and and HCLK clock divider as 2 */
  47.     CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV0_HCLK(2));

  48.     /* PWM clock frequency can be set equal or double to HCLK by choosing case 1 or case 2 */
  49.     /* case 1.PWM clock frequency is set equal to HCLK: select PWM module clock source as PCLK */
  50. //    CLK_SetModuleClock(PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK0, 0);

  51.     /* case 2.PWM clock frequency is set double to HCLK: select PWM module clock source as PLL */
  52.     CLK_SetModuleClock(PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PLL, NULL);
  53.     /*---------------------------------------------------------------------------------------------------------*/

  54.     /* Reset PWM1 module */
  55.     SYS_ResetModule(PWM1_RST);

  56.     /* Update System Core Clock */
  57.     SystemCoreClockUpdate();

  58.     /*---------------------------------------------------------------------------------------------------------*/
  59.     /* Init I/O Multi-function                                                                                 */
  60.     /*---------------------------------------------------------------------------------------------------------*/
  61.     /* Set PC.4 multi-function pins for PWM1 Channel 1 for Red LED */
  62.     SYS->GPC_MFPL = (SYS->GPC_MFPL & (~SYS_GPC_MFPL_PC4MFP_Msk)) |
  63.                     SYS_GPC_MFPL_PC4MFP_PWM1_CH1;
  64. }

  65. void PWM_Init()
  66. {
  67.     /*---------------------------------------------------------------------------------------------------------*/
  68.     /* Init PWM1                                                                                               */
  69.     /*---------------------------------------------------------------------------------------------------------*/
  70.     /* Set prescaler of PWM1 Channel 1 as PWM_Prescaler for Red LED */
  71.     PWM_SET_PRESCALER(PWM1, 1, PWM_Prescaler - 1);
  72.     /* Set period of PWM1 Channel 1 as PWM_Period for Red LED */
  73.     PWM_SET_CNR(PWM1, 1, PWM_Period);
  74.     /* Set compare of PWM1 Channel 1 as 0 for Red LED */
  75.     PWM_SET_CMR(PWM1, 1, 0);
  76.     /* Set Counter Type */
  77.     PWM_SET_ALIGNED_TYPE(PWM1, BIT1, PWM_UP_COUNTER);
  78.     /* Set Zero Point Output Low, Compare Up Point Output Nothing, Period Point Output High, Compare Down Point Output High */
  79.     PWM_SET_OUTPUT_LEVEL(PWM1, BIT1, PWM_OUTPUT_LOW, PWM_OUTPUT_HIGH, PWM_OUTPUT_NOTHING, PWM_OUTPUT_NOTHING);
  80.     /* Enable PWM1 Output path for channel 1 */
  81.     PWM_EnableOutput(PWM1, BIT1);
  82.     /* Enable PWM1 channel 1 period interrupt */
  83.     PWM_EnablePeriodInt(PWM1, 1, 0);
  84.     NVIC_EnableIRQ(PWM1_IRQn);

  85.     /* Start PWM1 Counter */
  86.     PWM_Start(PWM1, BIT1);
  87. }

  88. void PWM1_IRQHandler(void)
  89. {
  90.     /* Increase LED brightness */
  91.     if(g_u8Forward == 1)
  92.     {
  93.         if(g_u32BreathingCount < PWM_Period)
  94.             g_u32BreathingCount++;
  95.         else
  96.             g_u8Forward = 0;
  97.     }
  98.     /* Decrease LED brightness */
  99.     else
  100.     {
  101.         if(g_u32BreathingCount > 0)
  102.             g_u32BreathingCount--;
  103.         else
  104.             g_u8Forward = 1;
  105.     }

  106.     /* Set compare of PWM1 Channel 1 for Red LED */
  107.     PWM_SET_CMR(PWM1, 1, g_u32BreathingCount);

  108.     /* Clear PWM1 channel 1 period interrupt flag */
  109.     PWM_ClearPeriodIntFlag(PWM1, 1);
  110. }

  111. /*---------------------------------------------------------------------------------------------------------*/
  112. /*  Main Function                                                                                          */
  113. /*---------------------------------------------------------------------------------------------------------*/
  114. int32_t main(void)
  115. {
  116.     /* Unlock protected registers */
  117.     SYS_UnlockReg();

  118.     /* Init System, IP clock and multi-function I/O */
  119.     SYS_Init();

  120.     /* Lock protected registers */
  121.     SYS_LockReg();

  122.     /* Init PWM1 to drive RGB LED */
  123.     PWM_Init();

  124.     while(1);
  125. }


 楼主| 643757107 发表于 2024-2-19 21:17 | 显示全部楼层
这个方法可以让程序自动完成修改占空比。
捉虫天师 发表于 2024-2-27 22:18 | 显示全部楼层
这就不用在主函数中修改了,中断中修改。
天灵灵地灵灵 发表于 2024-2-28 15:31 | 显示全部楼层
呼吸灯是一个很不错的PWM学习项目。
夜晚有三年 发表于 2025-9-11 14:07 | 显示全部楼层
配置定时器中断,中断中更新 PWM 占空比,递增到最大后递减,循环往复,使 LED 亮度渐变实现呼吸效果
波尔街道的松柏 发表于 2025-10-17 10:57 | 显示全部楼层
配置定时器定时中断,中断服务程序中更新 PWM 占空比。初始化时设初始占空比,中断中逐步增减占空比(如从 0 增到最大再减到 0 循环),每次更新后写入 PWM 输出寄存器。通过控制增减步长和中断频率,调节呼吸灯的明暗变化速度和过渡平滑度。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

223

主题

3972

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部