[Atria Development Board AT32F421 Review] Timer PWM Output
[Copy link]
This post was last edited by eew_Violet on 2021-4-28 00:34
Some places need to output PWM with a certain phase difference. For chips without asynchronous PWM, the PWM1 and PWM2 modes of the timer can be used to achieve this, like this.
The maximum duty cycle is generally not more than 48%, otherwise the tube will explode. I have already ruined two D209L . Next, let's see how to implement it. The TIM initialization code is still placed in at32_board.c.
/*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-->PA8
* CH4-->PA11
*/
//GPIO初始化
GPIO_StructInit(&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, &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(&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, &TIM_TimerBaseStructure);
/* PWM模式配置: Channe8 */
TMR_OCStructInit(&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, &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, &TMR_OCInitStructure);
TMR_OC4PreloadConfig(AT32_TIM, TMR_OCPreload_Enable);
//使能定时器
TMR_Cmd(AT32_TIM,ENABLE);
//使能输出
TMR_CtrlPWMOutputs(TMR1, ENABLE);
}
In order to facilitate transplantation, the macro definition in at32_board.h
/**************** 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****************/
Channel 2 and channel 3 are occupied by the serial port, so channel 1 and channel 4 are used here.
Call the initialization function in board.c to complete the initialization.
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) && defined(RT_USING_HEAP)
rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}
Write the test code in while(1)
The comparison register is incremented every 100 milliseconds to change the duty cycle, and then the OLED obtains and displays the value of the comparison register.
uint16_t Pulse;
uint8_t dir = 1;
while (1)
{
if(dir == 1)
Pulse++;
if(Pulse>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);
}
WeChat_20210428000856.mp4
(1.77 MB, downloads: 4)
This is when the duty cycle is relatively small
WeChat_20210428002619.mp4
(2.32 MB, downloads: 2)
This is when the duty cycle is relatively large. The blue and green colors may not be easy to see just now, so let's change the color this time.
You can see that the code has run successfully
|