首先查询芯片的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函数:
- static pwm_channel_t g_pwm_channel_m1;
- void m1_pwm_init(void)
- {
- /* Enable PWM peripheral clock */
- pmc_enable_periph_clk(ID_PWM);
- /* Disable PWM channels for LEDs */
- pwm_channel_disable(PWM, PWM_CHANNEL_1);
- /* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
- pwm_clock_t clock_setting = {
- .ul_clka = PWM_FREQUENCY * PERIOD_VALUE,
- .ul_clkb = 0,
- .ul_mck = sysclk_get_cpu_hz()
- };
- pwm_init(PWM, &clock_setting);
- /* Initialize PWM channel for PWM_CHANNEL_1 */
- /* Period is center-left */
- g_pwm_channel_m1.alignment = PWM_ALIGN_LEFT;
- /* Output waveform starts at a low level, PWML1==>PA20 */
- g_pwm_channel_m1.polarity =PWM_LOW;
- /* Use PWM clock A as source clock */
- g_pwm_channel_m1.ul_prescaler = PWM_CMR_CPRE_CLKA;
- /* Period value of output waveform */
- g_pwm_channel_m1.ul_period = PERIOD_VALUE;
- /* Duty cycle value of output waveform */
- g_pwm_channel_m1.ul_duty = INIT_DUTY_VALUE;
- g_pwm_channel_m1.channel = PWM_CHANNEL_1;
- /* Disable channel counter event interrupt */
- pwm_channel_init(PWM, &g_pwm_channel_m1);
- /* Disable channel counter event interrupt */
- pwm_channel_disable_interrupt(PWM, PWM_CHANNEL_1, 0);
- /* Configure interrupt and enable PWM interrupt */
- NVIC_DisableIRQ(PWM_IRQn);
- NVIC_ClearPendingIRQ(PWM_IRQn);
- NVIC_SetPriority(PWM_IRQn, 0);
- NVIC_EnableIRQ(PWM_IRQn);
- /* Enable PWM channels for PWM_CHANNEL_1 */
- pwm_channel_enable(PWM, PWM_CHANNEL_1);
- }
这里面有几个地方注意下:
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
PWMH0 和PWML0配置和更新占空比都是不能独立的。只能互补输出。
不知道我的理解是否对?
是的,H0和L0是一个通道,H0变了,L0跟着变,如果H0关了,L0也跟着关了,如果想要独立,必须H0和L1.