eew_Violet 发表于 2021-4-28 00:29

【雅特力开发板 AT32F421 测评】定时器PWM输出

本帖最后由 eew_Violet 于 2021-4-28 00:34 编辑

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有些地方需要输出有一定相位差的PWM,对于没有异步PWM的片子,这个时候可以利用定时器的PWM1和PWM2模式实现,像这种.</span></p>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最大占空比一般不超48%,否则会炸管,我已经搞废两个D209L了<img height="27" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/frowning-face-with-open-mouth_1f626.png" width="27" />.接下来我们看下具体如何实现.TIM初始化代码依旧放在了at32_board.c中.</span></p>

<pre>
<code>/*TIM1初始化*/
void TIM_Init()
{
        TMR_TimerBaseInitType         TIM_TimerBaseStructure;
    TMR_OCInitType                                TMR_OCInitStructure;
    GPIO_InitType                                         GPIO_InitStructure;
       
        /* 启用 TIM clock 和 GPIO 时钟*/
RCC_APB2PeriphClockCmd(AT32_TIM_FUNC , ENABLE);
RCC_AHBPeriphClockCmd(AT32_TIM_GPIO_RCC , ENABLE);
       

/* Configure tim_pins: CH1   CH4
       *        CH1--&gt;PA8
       *        CH4--&gt;PA11
       */
//GPIO初始化
GPIO_StructInit(&amp;GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pins = AT32_TIM_CH1_PIN|AT32_TIM_CH4_PIN ;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
GPIO_InitStructure.GPIO_OutType = GPIO_OutType_PP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pull = GPIO_Pull_NOPULL;
GPIO_Init(AT32_TIM_GPIO, &amp;GPIO_InitStructure);
        //GPIO复用到定时器
GPIO_PinAFConfig(AT32_TIM_GPIO, GPIO_PinsSource8, GPIO_AF_2);
GPIO_PinAFConfig(AT32_TIM_GPIO, GPIO_PinsSource11, GPIO_AF_2);
       
/* 定时器时基配置 为了便于观察先频率调的低些--------------------------------------*/
TMR_TimeBaseStructInit(&amp;TIM_TimerBaseStructure);
TIM_TimerBaseStructure.TMR_Period = 65535-1;
TIM_TimerBaseStructure.TMR_DIV = 6553-1;
TIM_TimerBaseStructure.TMR_ClockDivision = TMR_CKD_DIV2;
TIM_TimerBaseStructure.TMR_CounterMode = TMR_CounterDIR_CenterAligned1;

TMR_TimeBaseInit(AT32_TIM, &amp;TIM_TimerBaseStructure);
       
/* PWM模式配置: Channe8 */
TMR_OCStructInit(&amp;TMR_OCInitStructure);
TMR_OCInitStructure.TMR_OCMode = TMR_OCMode_PWM1;
TMR_OCInitStructure.TMR_OutputState = TMR_OutputState_Enable;
TMR_OCInitStructure.TMR_Pulse = 0;
TMR_OCInitStructure.TMR_OCPolarity = TMR_OCPolarity_High;
TMR_OCInitStructure.TMR_OCIdleState = TMR_OCIdleState_Reset ;

TMR_OC1Init(AT32_TIM, &amp;TMR_OCInitStructure);

TMR_OC1PreloadConfig(AT32_TIM, TMR_OCPreload_Enable);

/* PWM2模式配置: Channe11 */
TMR_OCInitStructure.TMR_OCMode = TMR_OCMode_PWM2;
TMR_OCInitStructure.TMR_OutputState = TMR_OutputState_Enable;
TMR_OCInitStructure.TMR_Pulse = 0;

TMR_OC4Init(AT32_TIM, &amp;TMR_OCInitStructure);

TMR_OC4PreloadConfig(AT32_TIM, TMR_OCPreload_Enable);
        //使能定时器
        TMR_Cmd(AT32_TIM,ENABLE);
    //使能输出
        TMR_CtrlPWMOutputs(TMR1, ENABLE);
}
</code></pre>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了便于移植在at32_board.h中宏定义</span></p>

<pre>
<code>/**************** TIM ****************/
#define AT32_TIM                          TMR1

#define AT32_TIM_GPIO_RCC               RCC_AHBPERIPH_GPIOA
#define AT32_TIM_FUNC                           RCC_APB2PERIPH_TMR1

/*TIM1_CH1*/
#define AT32_TIM_CH1_PIN         GPIO_Pins_8
#define AT32_TIM_GPIO            GPIOA

/*TIM1_CH4*/
#define AT32_TIM_CH4_PIN         GPIO_Pins_11
#define AT32_TIM_GPIO            GPIOA

/**************** End TIM****************/</code></pre>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通道2和通道3让串口给占了,所以这里就用通道1和通道4了</span></p>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 在board.c中调用初始化函数完成初始化.</span></p>

<pre>
<code>void rt_hw_board_init()
{
    /* System Clock Update */
    SystemCoreClockUpdate();
   
    /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
       
          /* 串口1初始化*/
          UART_Print_Init(115200);
          /* SPI2初始化 */
          SPI2_Init();

          OLED_Init();
          TIM_Init();
       
    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) &amp;&amp; defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}
</code></pre>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(1)中写好测试代码</span></p>

<p>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:24px;">&nbsp;&nbsp;&nbsp;每100毫秒对比较寄存器自增一次,改变占空比,然后OLED获取并显示比较寄存器的值.</span></p>

<pre>
<code>uint16_t Pulse;
uint8_tdir = 1;

while (1)
{

                if(dir == 1)
                        Pulse++;
                if(Pulse&gt;31456)
                        dir = 0;
                       
                if(dir == 0)
                        Pulse--;
                if(Pulse==0)
                        dir = 1;
      //设置比较寄存器
                TMR_SetCompare1(AT32_TIM, Pulse);
                TMR_SetCompare4(AT32_TIM, 65535-Pulse);
                OLED打印寄存器值
                OLED_ShowString(5,0,(uint8_t*)"CC1",16);
                OLED_ShowNum(5,16,TMR_GetCapture1(AT32_TIM),5,16);
                OLED_ShowString(5,30,(uint8_t*)"CC4",16);
                OLED_ShowNum(5,46,TMR_GetCapture4(AT32_TIM),5,16);
                OLED_Refresh();
                rt_thread_mdelay(100);
}</code></pre>

<p></p>

<p><span style="font-size:24px;">这是占空比比较小的时候</span></p>

<p></p>

<p><span style="font-size:24px;">这是占空比比较大的时候,刚才蓝色绿色可能不太容易看出来,这次换个色.</span></p>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可以看到代码已成功运行</span></p>

火辣西米秀 发表于 2021-4-29 21:59

<p>看到绿灯亮的还可以</p>
页: [1]
查看完整版本: 【雅特力开发板 AT32F421 测评】定时器PWM输出