[DemoCode下载] 新唐M051学习之(3)-PWM

[复制链接]
 楼主| neeringstu 发表于 2016-8-11 17:25 | 显示全部楼层 |阅读模式
今天学习PWM,把M051的手册中关于PWM的那一章反反复复看了好几遍,还是看的云里雾里,最后竟然看的打起盹来。后来觉的差不多了,打算动手写个呼吸灯程序,巩固一下学习成果。
      顾名思义,灯光在微电脑控制之下完成由亮到暗又由暗变亮的逐渐变化,感觉像是在呼吸。
      LED等插在P2.0口上(PWM0) 。如下图。



/*********************************************************************************************
  1. 程序名:  PWM实验   用PWM制作呼吸灯
  2. 编写人:  闪闪发光的金子
  3. 编写时间:2014年2月21日
  4. 硬件支持:M0516LNB 12MHz晶体
  5. 接口说明:    P2.0接LED正极
  6. ---------------------------------------------------

  7. #include <stdio.h>
  8. #include <M051Series.h>
  9. #define PLLCON_SETTING      SYSCLK_PLLCON_50MHz_XTAL
  10. #define PLL_CLOCK           50000000

  11.     uint16_t g_u16PWMValue;
  12.    
  13. void SYS_Init(void)
  14. {
  15. /*---------------------------------------------------------------------------------------------------------*/
  16. /* Init System Clock                                                                                       */
  17. /*---------------------------------------------------------------------------------------------------------*/
  18.     /* Unlock protected registers */
  19.     SYS_UnlockReg();

  20.     /* Enable External XTAL (4~24 MHz) */
  21.     SYSCLK->PWRCON |= SYSCLK_PWRCON_XTL12M_EN_Msk;

  22.     /* Waiting for 12MHz clock ready */
  23.     SYS_WaitingForClockReady( SYSCLK_CLKSTATUS_XTL12M_STB_Msk);

  24.     /* Switch HCLK clock source to XTAL */
  25.     SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_XTAL;

  26.     /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware.*/
  27.     SYSCLK->PLLCON|= SYSCLK_PLLCON_PD_Msk;

  28.     /* Set PLL frequency */        
  29.     SYSCLK->PLLCON = PLLCON_SETTING;

  30.     /* Waiting for clock ready */
  31.     SYS_WaitingForClockReady(SYSCLK_CLKSTATUS_PLL_STB_Msk);

  32.     /* Switch HCLK clock source to PLL */
  33.     SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_PLL;

  34.     /* Enable IP clock */
  35.     //设置PWM0、PWM1的时钟源      
  36.     SYSCLK->APBCLK = SYSCLK_APBCLK_PWM01_EN_Msk;

  37.     /* Select IP clock source */
  38.     SYSCLK->CLKSEL1 = SYSCLK_CLKSEL1_PWM01_XTAL;

  39.     /* Reset PWMB channel0~channel3 */                    
  40.     SYS->IPRSTC2 = SYS_IPRSTC2_PWM47_RST_Msk;                    
  41.     SYS->IPRSTC2 = 0;      


  42.     /* Update System Core Clock */
  43.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
  44.     //SystemCoreClockUpdate();
  45.     PllClock        = PLL_CLOCK;            // PLL
  46.     SystemCoreClock = PLL_CLOCK / 1;        // HCLK
  47.     CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay()

  48. /*---------------------------------------------------------------------------------------------------------*/
  49. /* Init I/O Multi-function                                                                                 */
  50. /*---------------------------------------------------------------------------------------------------------*/
  51.     /* P2.0 for PWM0 */
  52.     SYS->P2_MFP = SYS_MFP_P20_PWM0 ;



  53.     /* Lock protected registers */
  54.     SYS_LockReg();
  55. }
  56. void PWMA_Init(void)
  57. {
  58.     //配置预分频器 (PPR)
  59.     PWMA->PPR = PWM_PPR_CP01(30) ;
  60.     //配置时钟选择器(CSR)
  61.     PWMA->CSR = PWM_CSR_CSR0(PWM_CSR_DIV16);

  62.     /* Enable PWM0  counter. We must set PWM mode before setting CNR, CMR. */
  63.     //如果设置PWM_PCR_CH0MOD_AUTO_RELOAD ,当PWM计数器达到0,自动重载CNR0的值到PWM计数器
  64.     PWMA->PCR = PWM_PCR_CH0EN_Msk | PWM_PCR_CH0MOD_AUTO_RELOAD;

  65.     //频率计算公式
  66.     /* PWM0 = 12000000 / 30 / 16 / 200 =    125Hz */
  67.         PWMA->CNR0= 200;   //配置PWM计数器寄存器 (CNR) 设定PWM周期
  68.     PWMA->CMR0= 100;   //配置比较器寄存器(CMR) 设定PWM占空比

  69.     /* Enable PWM channle 0  Output */
  70.     //配置相应的GPIO管脚为PWM功能(使能 POE 和禁用CAPENR).
  71.     PWMA->POE = PWM_POE_PWM0_Msk;
  72. }


  73. int main(void)
  74. {
  75.     uint16_t i,j;
  76.     SYS_Init();
  77.     PWMA_Init();
  78.     while(1)
  79.     {
  80.       //下面有小到大 然后由大到小 循环改变占空比大小,LED灯就会慢慢变亮,然后又慢慢变暗。
  81.       //注意CMR的值不能大于CNR
  82.         for (g_u16PWMValue = 1;g_u16PWMValue<200;g_u16PWMValue++)   
  83.         {      
  84.             PWMA->CMR0 = g_u16PWMValue;
  85.             for(i=0;i<500;i++)  //延时
  86.                 for(j=0;j<100;j++);
  87.         }
  88.         for (g_u16PWMValue = 199;g_u16PWMValue>0;g_u16PWMValue--)   
  89.         {      
  90.             PWMA->CMR0 = g_u16PWMValue;
  91.             for(i=0;i<500;i++)  //延时
  92.                 for(j=0;j<100;j++);
  93.         }
  94.     }
  95. }





643757107 发表于 2016-8-12 23:14 | 显示全部楼层
一个PWM功能强大,学习起来也复杂。
wahahaheihei 发表于 2016-8-13 16:31 | 显示全部楼层
在新唐的例程中通常都是使用PLL来驱动时钟的。
capturesthe 发表于 2016-8-13 21:04 | 显示全部楼层
PWM是工程控制当中非常重要的,有时候能够替代dac的功能
zhuomuniao110 发表于 2016-8-22 22:07 来自手机 | 显示全部楼层
pwm加滤波后就可以作为简单的数模转换器
mintspring 发表于 2016-8-23 08:46 | 显示全部楼层
由大到小 循环改变占空比大小,LED灯就会慢慢变亮,然后又慢慢变暗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

235

帖子

0

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