SAM4S芯片PWM的生成

首先查询芯片的PWM线性表,4S芯片一共有0-3高和0-3低,共8路独立的PWM。我用了其中的四路,PWMH0==>PA11,PWMH1==>PA12,PWML0==>PA19,PWML1==>PA20,初始化的时候要注意对应关系。

首先初始化GPIO,线性表中这四路Peripheral都是B,所以引脚统一配置为 (PIO_PERIPH_B | PIO_DEFAULT),注意这里和普通的GPIO配置不同。

以PA20为例,初始化pwm函数:

 
  1. static pwm_channel_t g_pwm_channel_m1;  
  2. void m1_pwm_init(void)  
  3. {  
  4.     /* Enable PWM peripheral clock */  
  5.     pmc_enable_periph_clk(ID_PWM);  
  6.   
  7.   
  8.     /* Disable PWM channels for LEDs */  
  9.     pwm_channel_disable(PWM, PWM_CHANNEL_1);  
  10.       
  11.     /* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */  
  12.     pwm_clock_t clock_setting = {  
  13.         .ul_clka = PWM_FREQUENCY * PERIOD_VALUE,  
  14.         .ul_clkb = 0,  
  15.         .ul_mck = sysclk_get_cpu_hz()  
  16.     };  
  17.   
  18.     pwm_init(PWM, &clock_setting);  
  19.   
  20.     /* Initialize PWM channel for PWM_CHANNEL_1 */  
  21.     /* Period is center-left */  
  22.     g_pwm_channel_m1.alignment = PWM_ALIGN_LEFT;  
  23.     /* Output waveform starts at a low level, PWML1==>PA20 */  
  24.     g_pwm_channel_m1.polarity =PWM_LOW;  
  25.     /* Use PWM clock A as source clock */  
  26.     g_pwm_channel_m1.ul_prescaler = PWM_CMR_CPRE_CLKA;  
  27.     /* Period value of output waveform */  
  28.     g_pwm_channel_m1.ul_period = PERIOD_VALUE;  
  29.     /* Duty cycle value of output waveform */  
  30.     g_pwm_channel_m1.ul_duty = INIT_DUTY_VALUE;  
  31.     g_pwm_channel_m1.channel = PWM_CHANNEL_1;  
  32.     /* Disable channel counter event interrupt */  
  33.     pwm_channel_init(PWM, &g_pwm_channel_m1);  
  34.   
  35.     /* Disable channel counter event interrupt */  
  36.     pwm_channel_disable_interrupt(PWM, PWM_CHANNEL_1, 0);  
  37.   
  38.     /* Configure interrupt and enable PWM interrupt */  
  39.     NVIC_DisableIRQ(PWM_IRQn);  
  40.     NVIC_ClearPendingIRQ(PWM_IRQn);  
  41.     NVIC_SetPriority(PWM_IRQn, 0);  
  42.     NVIC_EnableIRQ(PWM_IRQn);  
  43.       
  44.     /* Enable PWM channels for PWM_CHANNEL_1 */  
  45.     pwm_channel_enable(PWM, PWM_CHANNEL_1);  
  46. }  

这里面有几个地方注意下:

PA20所对应的PWML 1,其中1代表的是PWM的通道1,L代表以低位开始。

所以函数pwm_channel_disable(PWM, PWM_CHANNEL_1); 先关闭通道1;

L1对应的是 g_pwm_channel_m1.polarity =PWM_LOW; 以低位开始;

g_pwm_channel_m1.channel = PWM_CHANNEL_1; 通道同样选择PWM_CHANNEL_1;

pwm_channel_disable_interrupt(PWM, PWM_CHANNEL_1, 0);

pwm_channel_enable(PWM, PWM_CHANNEL_1); 关中断和使能同样选择通道1.

动态更新PWM使用如下函数:

pwm_channel_update_duty(PWM, &g_pwm_channel_m1, dat);

pwm_channel_enable(PWM, PWM_CHANNEL_1);

dat是一个小于 PERIOD_VALUE 的正数,占空比为 dat/PERIOD_VALUE。

关闭流程为:

pwm_channel_update_duty(PWM, &g_pwm_channel_m1, 0);
pwm_channel_disable(PWM, PIN_PWM_M1_CHANNEL);

首先将占空比调为0,然后停止PWM对应引脚。

2019.04.26更新

实际上这八路独立的PWM只是相对的,确实有八路PWM输出,但是两两成对称关系,即H0和L0不能分开控制,一个改变,另一个必定跟着变化,一个关闭,另一个也是关闭状态。如果想使用完全独立的四路PWM,就必须初始化通道0,1,2,3

打赏
原文链接:,转发请注明来源!

发表评论

  • 2 Responses to “SAM4S芯片PWM的生成”
    • PWMH0 和PWML0可以相互独立吗 ?

      PWMH0 和PWML0配置和更新占空比都是不能独立的。只能互补输出。
      不知道我的理解是否对?

      回复
      • 是的,H0和L0是一个通道,H0变了,L0跟着变,如果H0关了,L0也跟着关了,如果想要独立,必须H0和L1.

        美多多 回复私信