新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > Cortex-M3 (NXP LPC1788)之PWM

Cortex-M3 (NXP LPC1788)之PWM

作者:时间:2016-11-19来源:网络收藏
PWM即脉宽调制,可用于输出一定占空比的方波。LPC1788有两个PWM,每个PWM可以由6路的输出,PWM1~PWM6。下面介绍使用PWM0.1输出PWM波。

1,PWM使用公共的PCLK,因此要配置系统时钟和外设时钟。之前的文章中有具体的时钟配置过程。

本文引用地址:http://www.eepw.com.cn/article/201611/318448.htm

2,使能PWM模块。配置外设功率配置寄存器PCONP,使能PWM0的时钟控制位。

3,PWM0.1的输出管脚和P1_2管脚复用,因此要配置IOCON_P1_02寄存器,将其设置成PWM0.1的输出。

4,设置PWM的脉冲宽度,基本的原理就是比较PWM定时器计数器TC和匹配寄存器MR中的值,如果匹配我们可以通过匹配控制寄存器MCR选择操作,如产生一个中断,复位TC,停止TC和预分频计数器PC且停止计数。匹配寄存器MR0通过在匹配是将计数器TC复位来控制PWM的周期频率。另一个匹配寄存器控制PWM沿的位置。如PWM0.1的输出,将使用MR0控制PWM的周期频率,MR1控制边沿的位置。

5,最后是对于PWM的具体控制,配置PWM预分频寄存器PWMPR,该32位寄存器规定了PWM预分频计数的最大值,PWM预分频计数器寄存器PWMPC在每个PCLK上递增一次,当PWMPC和PWMPR值相等时,PWMTC的值会递增,而PWMPR在系一个PCLK周期被复位。这样,当PWMPR=0时,PWMTC会在每个PCLK上递增,而当PWMPR=1时,在每2个PCLK上递增。匹配寄存器PWMMR中的值和PWMTC的值比较,如果相等则触发在PWMMCR中配置的操作。当MR0和TC相等时,我们进行复位TC从新计数从而固定了PWM的周期频率。当定时器处于PWM模式时,软件对PWM匹配寄存器MR的写操作,写入值实际上被保存在一个映像寄存器中,不会被立即使用。所以在我们需要操作PWM锁存使能寄存器PWMLER,典型序列为:将新值写入MR,写PWMLER中相应的位,更改的MR值将在下一次定时器复位时生效。

在下面的程序中,将给MR1中写入不同的匹配值,来控制PWM的占空比。为了方便使用LED灯进行示意。

  1. #defineCCLK120000000
  2. #definePCLK60000000
  3. #definerFIO1DIR(*(volatileunsigned*)(0x20098020))
  4. #definerFIO1MASK(*(volatileunsigned*)(0x20098030))
  5. #definerFIO1PIN(*(volatileunsigned*)(0x20098034))
  6. #definerFIO1SET(*(volatileunsigned*)(0x20098038))
  7. #definerFIO1CLR(*(volatileunsigned*)(0x2009803c))
  8. #definerCLKSRCSEL(*(volatileunsigned*)(0x400FC10C))//时钟源选择寄存器
  9. #definerPLL0CON(*(volatileunsigned*)(0x400FC080))//PLL0控制寄存器
  10. #definerPLL0CFG(*(volatileunsigned*)(0x400FC084))//PLL0配置寄存器
  11. #definerPLL0STAT(*(volatileunsigned*)(0x400FC088))//PLL0状态寄存器
  12. #definerPLL0FEED(*(volatileunsigned*)(0x400FC08C))//PLL0馈送寄存器
  13. #definerPLL1CON(*(volatileunsigned*)(0x400FC0A0))
  14. #definerPLL1CFG(*(volatileunsigned*)(0x400FC0A4))
  15. #definerPLL1STAT(*(volatileunsigned*)(0x400FC0A8))
  16. #definerPLL1FEED(*(volatileunsigned*)(0x400FC0AC))
  17. #definerCCLKSEL(*(volatileunsigned*)(0x400FC104))//CPU时钟选择寄存器
  18. #definerUSBCLKSEL(*(volatileunsigned*)(0x400FC108))//USB时钟选择寄存器
  19. #definerPCLKSEL(*(volatileunsigned*)(0x400FC1A8))//外设时钟寄存器
  20. #definerPCON(*(volatileunsigned*)(0x400FC0C0))
  21. #definerPXCONP(*(volatileunsigned*)(0x400FC0C4))
  22. #definerSCS(*(volatileunsigned*)(0x400FC1A0))//系统控制和状态寄存器
  23. #definerCLKOUTCFG(*(volatileunsigned*)(0x400FC1C8))
  24. #definerIOCON_P1_02(*(volatileunsigned*)(0x4002C088))
  25. #definerPCONP(*(volatileunsigned*)(0x400FC0C4))
  26. #definerPWM0IR(*(volatileunsigned*)(0x40014000))
  27. #definerPWM0TCR(*(volatileunsigned*)(0x40014004))
  28. #definerPWM0TC(*(volatileunsigned*)(0x40014008))
  29. #definerPWM0PR(*(volatileunsigned*)(0x4001400C))
  30. #definerPWM0CTCR(*(volatileunsigned*)(0x40014070))
  31. #definerPWM0MCR(*(volatileunsigned*)(0x40014014))
  32. #definerPWM0MR0(*(volatileunsigned*)(0x40014018))
  33. #definerPWM0MR1(*(volatileunsigned*)(0x4001401C))
  34. #definerPWM0CCR(*(volatileunsigned*)(0x40014028))
  35. #definerPWM0PCR(*(volatileunsigned*)(0x4001404C))
  36. #definerPWM0LER(*(volatileunsigned*)(0x40014050))
  37. #definerISER1(*(volatileunsigned*)(0xE000E104))
  38. #definerCER1(*(volatileunsigned*)(0xE000E184))
  39. unsignedintduty=10;
  40. unsignedcharmatch_cnt=0;
  41. voidPWM0_IRQHandler(void)
  42. {
  43. if(rPWM0IR&0x1)
  44. {
  45. rFIO1PIN|=(1<<18);
  46. match_cnt++;
  47. rPWM0IR|=0x1;//MR0中断复位
  48. }
  49. if(rPWM0IR&(0x1<<1))
  50. {
  51. rFIO1PIN&=~(1<<18);
  52. rPWM0IR|=0x1<<1;//MR1中断复位
  53. }
  54. }
  55. voidSystemInit()
  56. {
  57. rSCS&=~(0x1<<4);//频率12M
  58. rSCS|=(0x1<<5);//使能主振荡器
  59. while(0==(rSCS&(0x1<<6)));//等待主振荡器稳定
  60. rCLKSRCSEL=0x1;
  61. rPLL0CFG=0x9;//配置CCLK=120M
  62. rPLL0CON=0x01;
  63. rPLL0FEED=0xAA;
  64. rPLL0FEED=0x55;
  65. while(0==(rPLL0STAT&(0x1<<10)));
  66. rCCLKSEL=(0x1|(0x1<<8));
  67. rPCLKSEL=0x2;//配置PCLK=60M
  68. rCLKOUTCFG=0x0|(0xb<<4)|(0x1<<8);
  69. }
  70. voidPWMInit()
  71. {
  72. rIOCON_P1_02&=~0x7;
  73. rIOCON_P1_02|=0x3;//P1.02配置成PWM0[1]
  74. rPCONP|=0x1<<5;//使能PWM0外设
  75. rPWM0IR=0x73F;//初始化PWM相关控制寄存器
  76. rPWM0TCR=0;
  77. rPWM0CTCR=0;
  78. rPWM0MCR=0;
  79. rPWM0CCR=0;
  80. rPWM0PCR=0;
  81. rPWM0LER=0;
  82. rPWM0PR=0x1<<20;//每0x1<<20+1个PLCK上升沿,TC递增
  83. rPWM0TCR|=0x1<<1;//复位TC和PC
  84. rPWM0TCR&=~(0x1<<1);
  85. rPWM0MR0=100;
  86. rPWM0LER|=0x1;
  87. rPWM0MCR|=0x1<<1|0x1;//MR0和TC匹配时复位TC和PC.并且产生中断
  88. rPWM0MR1=duty;
  89. rPWM0LER|=0x1<<1;
  90. rPWM0MCR|=0x1<<3;//MR1和TC匹配时产生中断
  91. }
  92. intmain()
  93. {
  94. PWMInit();
  95. rFIO1DIR|=(0x1<<18);
  96. rISER1|=0x1<<7;//PWM0中断使能
  97. rPWM0TCR|=0x1<<1;//复位TC和PC
  98. rPWM0TCR&=~(0x1<<1);
  99. rPWM0TCR|=0x1;//PC和TC计数使能
  100. rPWM0TCR|=0x1<<3;//PWM模式使能
  101. while(1)
  102. {
  103. if(match_cnt>=1)
  104. {
  105. match_cnt=0;
  106. duty=duty+10;
  107. if(duty>=100)
  108. {
  109. duty=0;
  110. }
  111. rPWM0MR1=duty;
  112. rPWM0LER|=0x1<<1;
  113. rPWM0MCR|=0x1<<3;
  114. }
  115. }
  116. return1;
  117. }
程序在MR0匹配时复位TC,在MR1匹配时触发边沿。可以看到随着MR1匹配值的改变,LED灯的亮灭时间对应改变。(程序中的预分频寄存器PR设置为了让LED效果明显)

LPC1788的PWM可以进行双边沿的控制。如PWM0.2可以用MR0控制PWM的周期频率,用MR1和MR2控制PWM0.2的边沿。



关键词: Cortex-M3NXPLPC1788PW

评论


相关推荐

技术专区

关闭