请选择 进入手机版 | 继续访问电脑版
搜索
查看: 279|回复: 0

【我要分享】Cortex-M3 (NXP LPC1788)之PWM

[复制链接]

该用户从未签到

13

主题

28

帖子

73

积分

注册会员

Rank: 2

积分
73
发表于 2017-2-17 10:59:09 | 显示全部楼层 |阅读模式
PWM即脉宽调制,可用于输出一定占空比的方波。LPC1788有两个PWM,每个PWM可以由6路的输出,PWM1~PWM6。下面介绍使用PWM0.1输出PWM波。

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

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灯进行示意。

程序在MR0匹配时复位TC,在MR1匹配时触发边沿。可以看到随着MR1匹配值的改变,LED灯的亮灭时间对应改变。(程序中的预分频寄存器PR设置为了让LED效果明显)

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

  1.     #define CCLK        120000000
  2.     #define PCLK         60000000
  3.      
  4.     #define rFIO1DIR    (*(volatile unsigned*)(0x20098020))
  5.     #define rFIO1MASK   (*(volatile unsigned*)(0x20098030))
  6.     #define rFIO1PIN    (*(volatile unsigned*)(0x20098034))
  7.     #define rFIO1SET    (*(volatile unsigned*)(0x20098038))
  8.     #define rFIO1CLR    (*(volatile unsigned*)(0x2009803c))
  9.      
  10.     #define rCLKSRCSEL  (*(volatile unsigned *)(0x400FC10C))     //时钟源选择寄存器   
  11.     #define rPLL0CON    (*(volatile unsigned *)(0x400FC080))     //PLL0控制寄存器   
  12.     #define rPLL0CFG    (*(volatile unsigned *)(0x400FC084))     //PLL0配置寄存器   
  13.     #define rPLL0STAT   (*(volatile unsigned *)(0x400FC088))     //PLL0状态寄存器   
  14.     #define rPLL0FEED   (*(volatile unsigned *)(0x400FC08C))     //PLL0馈送寄存器   
  15.     #define rPLL1CON    (*(volatile unsigned *)(0x400FC0A0))        
  16.     #define rPLL1CFG    (*(volatile unsigned *)(0x400FC0A4))   
  17.     #define rPLL1STAT   (*(volatile unsigned *)(0x400FC0A8))   
  18.     #define rPLL1FEED   (*(volatile unsigned *)(0x400FC0AC))   
  19.     #define rCCLKSEL    (*(volatile unsigned *)(0x400FC104))     //CPU时钟选择寄存器   
  20.     #define rUSBCLKSEL  (*(volatile unsigned *)(0x400FC108))     //USB时钟选择寄存器   
  21.     #define rPCLKSEL    (*(volatile unsigned *)(0x400FC1A8))     //外设时钟寄存器   
  22.     #define rPCON       (*(volatile unsigned *)(0x400FC0C0))   
  23.     #define rPXCONP     (*(volatile unsigned *)(0x400FC0C4))   
  24.     #define rSCS        (*(volatile unsigned *)(0x400FC1A0))     //系统控制和状态寄存器   
  25.     #define rCLKOUTCFG  (*(volatile unsigned *)(0x400FC1C8))
  26.      
  27.     #define rIOCON_P1_02    (*(volatile unsigned *)(0x4002C088))
  28.     #define rPCONP      (*(volatile unsigned *)(0x400FC0C4))
  29.      
  30.     #define rPWM0IR     (*(volatile unsigned *)(0x40014000))
  31.     #define rPWM0TCR    (*(volatile unsigned *)(0x40014004))
  32.     #define rPWM0TC     (*(volatile unsigned *)(0x40014008))
  33.     #define rPWM0PR     (*(volatile unsigned *)(0x4001400C))
  34.     #define rPWM0CTCR   (*(volatile unsigned *)(0x40014070))
  35.     #define rPWM0MCR    (*(volatile unsigned *)(0x40014014))
  36.     #define rPWM0MR0    (*(volatile unsigned *)(0x40014018))
  37.     #define rPWM0MR1    (*(volatile unsigned *)(0x4001401C))
  38.     #define rPWM0CCR    (*(volatile unsigned *)(0x40014028))
  39.     #define rPWM0PCR    (*(volatile unsigned *)(0x4001404C))
  40.     #define rPWM0LER    (*(volatile unsigned *)(0x40014050))
  41.      
  42.     #define rISER1      (*(volatile unsigned *)(0xE000E104))
  43.     #define rCER1       (*(volatile unsigned *)(0xE000E184))
  44.      
  45.     unsigned int duty = 10;
  46.     unsigned char match_cnt = 0;
  47.      
  48.     void PWM0_IRQHandler(void)
  49.     {
  50.         if(rPWM0IR&0x1)
  51.         {
  52.             rFIO1PIN |= (1<<18);
  53.             match_cnt++;
  54.             rPWM0IR |= 0x1;     //MR0中断复位
  55.         }
  56.          
  57.         if(rPWM0IR&(0x1<<1))
  58.         {
  59.             rFIO1PIN &= ~(1<<18);
  60.             rPWM0IR |= 0x1<<1;  //MR1中断复位
  61.         }
  62.     }
  63.      
  64.     void SystemInit()   
  65.     {   
  66.         rSCS &= ~(0x1<<4);                //频率12M   
  67.         rSCS |= (0x1<<5);             //使能主振荡器   
  68.         while(0 == (rSCS & (0x1<<6)));//等待主振荡器稳定   
  69.            
  70.         rCLKSRCSEL = 0x1;   
  71.            
  72.         rPLL0CFG = 0x9;                 //配置CCLK = 120M   
  73.         rPLL0CON = 0x01;   
  74.         rPLL0FEED = 0xAA;   
  75.         rPLL0FEED =0x55;   
  76.         while( 0 == (rPLL0STAT & (0x1<<10)));   
  77.            
  78.         rCCLKSEL = (0x1 | (0x1<<8));   
  79.         rPCLKSEL = 0x2;                 //配置PCLK = 60M   
  80.            
  81.         rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);   
  82.     }  
  83.      
  84.      
  85.     void PWMInit()
  86.     {
  87.         rIOCON_P1_02 &= ~0x7;
  88.         rIOCON_P1_02 |= 0x3;    //P1.02配置成PWM0[1]
  89.          
  90.         rPCONP |= 0x1<<5;     //使能PWM0外设
  91.          
  92.         rPWM0IR = 0x73F;    //初始化PWM相关控制寄存器
  93.         rPWM0TCR = 0;
  94.         rPWM0CTCR = 0;
  95.         rPWM0MCR = 0;
  96.         rPWM0CCR = 0;
  97.         rPWM0PCR = 0;
  98.         rPWM0LER = 0;
  99.          
  100.         rPWM0PR = 0x1<<20;    //每0x1<<20+1个PLCK上升沿,TC递增
  101.         rPWM0TCR |= 0x1<<1;   //复位TC和PC
  102.         rPWM0TCR &= ~(0x1<<1);
  103.          
  104.         rPWM0MR0 = 100;
  105.         rPWM0LER |= 0x1;
  106.         rPWM0MCR |= 0x1<<1 | 0x1;     //MR0和TC匹配时复位TC和PC.并且产生中断
  107.          
  108.         rPWM0MR1 = duty;
  109.         rPWM0LER |= 0x1<<1;
  110.         rPWM0MCR |= 0x1<<3;   //MR1和TC匹配时产生中断
  111.     }
  112.      
  113.     int main ()
  114.     {
  115.         PWMInit();
  116.          
  117.         rFIO1DIR |= (0x1<<18);
  118.         rISER1 |= 0x1<<7; //PWM0中断使能
  119.          
  120.         rPWM0TCR |= 0x1<<1;   //复位TC和PC
  121.         rPWM0TCR &= ~(0x1<<1);
  122.          
  123.         rPWM0TCR |= 0x1;    //PC和TC计数使能
  124.         rPWM0TCR |= 0x1<<3; //PWM模式使能
  125.          
  126.         while(1)
  127.         {
  128.             if(match_cnt >= 1)
  129.             {
  130.                 match_cnt = 0;
  131.                 duty = duty+10;
  132.                 if(duty >= 100)
  133.                 {
  134.                     duty  = 0;
  135.                 }
  136.                 rPWM0MR1 = duty;
  137.                 rPWM0LER |= 0x1<<1;
  138.                 rPWM0MCR |= 0x1<<3;
  139.             }
  140.         }
  141.         return 1;
  142.     }
复制代码
  1. #define CCLK        120000000
  2. #define PCLK         60000000

  3. #define rFIO1DIR    (*(volatile unsigned*)(0x20098020))
  4. #define rFIO1MASK     (*(volatile unsigned*)(0x20098030))
  5. #define rFIO1PIN    (*(volatile unsigned*)(0x20098034))
  6. #define rFIO1SET    (*(volatile unsigned*)(0x20098038))
  7. #define rFIO1CLR    (*(volatile unsigned*)(0x2009803c))

  8. #define rCLKSRCSEL  (*(volatile unsigned *)(0x400FC10C))     //时钟源选择寄存器  
  9. #define rPLL0CON    (*(volatile unsigned *)(0x400FC080))     //PLL0控制寄存器  
  10. #define rPLL0CFG    (*(volatile unsigned *)(0x400FC084))     //PLL0配置寄存器  
  11. #define rPLL0STAT   (*(volatile unsigned *)(0x400FC088))     //PLL0状态寄存器  
  12. #define rPLL0FEED   (*(volatile unsigned *)(0x400FC08C))     //PLL0馈送寄存器  
  13. #define rPLL1CON    (*(volatile unsigned *)(0x400FC0A0))      
  14. #define rPLL1CFG    (*(volatile unsigned *)(0x400FC0A4))  
  15. #define rPLL1STAT   (*(volatile unsigned *)(0x400FC0A8))  
  16. #define rPLL1FEED   (*(volatile unsigned *)(0x400FC0AC))  
  17. #define rCCLKSEL    (*(volatile unsigned *)(0x400FC104))     //CPU时钟选择寄存器  
  18. #define rUSBCLKSEL  (*(volatile unsigned *)(0x400FC108))     //USB时钟选择寄存器  
  19. #define rPCLKSEL    (*(volatile unsigned *)(0x400FC1A8))     //外设时钟寄存器  
  20. #define rPCON       (*(volatile unsigned *)(0x400FC0C0))  
  21. #define rPXCONP     (*(volatile unsigned *)(0x400FC0C4))  
  22. #define rSCS        (*(volatile unsigned *)(0x400FC1A0))     //系统控制和状态寄存器  
  23. #define rCLKOUTCFG  (*(volatile unsigned *)(0x400FC1C8))

  24. #define rIOCON_P1_02    (*(volatile unsigned *)(0x4002C088))
  25. #define rPCONP        (*(volatile unsigned *)(0x400FC0C4))

  26. #define rPWM0IR     (*(volatile unsigned *)(0x40014000))
  27. #define rPWM0TCR    (*(volatile unsigned *)(0x40014004))
  28. #define rPWM0TC        (*(volatile unsigned *)(0x40014008))
  29. #define rPWM0PR     (*(volatile unsigned *)(0x4001400C))
  30. #define rPWM0CTCR    (*(volatile unsigned *)(0x40014070))
  31. #define rPWM0MCR    (*(volatile unsigned *)(0x40014014))
  32. #define rPWM0MR0    (*(volatile unsigned *)(0x40014018))
  33. #define rPWM0MR1    (*(volatile unsigned *)(0x4001401C))
  34. #define rPWM0CCR    (*(volatile unsigned *)(0x40014028))
  35. #define rPWM0PCR    (*(volatile unsigned *)(0x4001404C))
  36. #define rPWM0LER    (*(volatile unsigned *)(0x40014050))

  37. #define rISER1      (*(volatile unsigned *)(0xE000E104))
  38. #define rCER1        (*(volatile unsigned *)(0xE000E184))

  39. unsigned int duty = 10;
  40. unsigned char match_cnt = 0;

  41. void PWM0_IRQHandler(void)
  42. {
  43.     if(rPWM0IR&0x1)
  44.     {
  45.         rFIO1PIN |= (1<<18);
  46.         match_cnt++;
  47.         rPWM0IR |= 0x1;     //MR0中断复位
  48.     }
  49.    
  50.     if(rPWM0IR&(0x1<<1))
  51.     {
  52.         rFIO1PIN &= ~(1<<18);
  53.         rPWM0IR |= 0x1<<1;  //MR1中断复位
  54.     }
  55. }

  56. void SystemInit()  
  57. {  
  58.     rSCS &= ~(0x1<<4);                //频率12M  
  59.     rSCS |= (0x1<<5);             //使能主振荡器  
  60.     while(0 == (rSCS & (0x1<<6)));//等待主振荡器稳定  
  61.       
  62.     rCLKSRCSEL = 0x1;  
  63.       
  64.     rPLL0CFG = 0x9;                 //配置CCLK = 120M  
  65.     rPLL0CON = 0x01;  
  66.     rPLL0FEED = 0xAA;  
  67.     rPLL0FEED =0x55;  
  68.     while( 0 == (rPLL0STAT & (0x1<<10)));   
  69.       
  70.     rCCLKSEL = (0x1 | (0x1<<8));  
  71.     rPCLKSEL = 0x2;                 //配置PCLK = 60M  
  72.       
  73.     rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);  
  74. }


  75. void PWMInit()
  76. {
  77.     rIOCON_P1_02 &= ~0x7;
  78.     rIOCON_P1_02 |= 0x3;    //P1.02配置成PWM0[1]
  79.    
  80.     rPCONP |= 0x1<<5;     //使能PWM0外设
  81.    
  82.     rPWM0IR = 0x73F;    //初始化PWM相关控制寄存器
  83.     rPWM0TCR = 0;
  84.     rPWM0CTCR = 0;
  85.     rPWM0MCR = 0;
  86.     rPWM0CCR = 0;
  87.     rPWM0PCR = 0;
  88.     rPWM0LER = 0;
  89.    
  90.     rPWM0PR = 0x1<<20;    //每0x1<<20+1个PLCK上升沿,TC递增
  91.     rPWM0TCR |= 0x1<<1;     //复位TC和PC
  92.     rPWM0TCR &= ~(0x1<<1);
  93.    
  94.     rPWM0MR0 = 100;
  95.     rPWM0LER |= 0x1;
  96.     rPWM0MCR |= 0x1<<1 | 0x1;     //MR0和TC匹配时复位TC和PC.并且产生中断
  97.    
  98.     rPWM0MR1 = duty;
  99.     rPWM0LER |= 0x1<<1;
  100.     rPWM0MCR |= 0x1<<3;     //MR1和TC匹配时产生中断
  101. }

  102. int main ()
  103. {
  104.     PWMInit();
  105.    
  106.     rFIO1DIR |= (0x1<<18);
  107.     rISER1 |= 0x1<<7;    //PWM0中断使能
  108.    
  109.     rPWM0TCR |= 0x1<<1;     //复位TC和PC
  110.     rPWM0TCR &= ~(0x1<<1);
  111.    
  112.     rPWM0TCR |= 0x1;    //PC和TC计数使能
  113.     rPWM0TCR |= 0x1<<3; //PWM模式使能
  114.    
  115.     while(1)
  116.     {
  117.         if(match_cnt >= 1)
  118.         {
  119.             match_cnt = 0;
  120.             duty = duty+10;
  121.             if(duty >= 100)
  122.             {
  123.                 duty  = 0;
  124.             }
  125.             rPWM0MR1 = duty;
  126.             rPWM0LER |= 0x1<<1;
  127.             rPWM0MCR |= 0x1<<3;
  128.         }
  129.     }
  130.     return 1;
  131. }

复制代码




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区    

GMT+8, 2017-7-22 04:34 , Processed in 0.118604 second(s), 13 queries , Memcache On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表