This is the 20th day of my participation in the Genwen Challenge

The STM32 timer has the following functions

The PWM mode is usually used, which can generate square wave signals with adjustable frequency and duty cycle through the PWM function. Sometimes, it is necessary to generate square wave with adjustable initial phase, and the PWM function cannot meet the requirements. This can be done by outputting the comparison pattern.

The output comparison mode is to compare the value of the counter CNT with the capture comparison register CCR. When the CNT value is equal to the value of CCR, the output level is flipped.

By capturing the description of CCMR mode setting bit of the comparison register, it can be seen that the output level will be flipped only when CCR = CNT in the output comparison mode. In PWM mode, one level is output when CNT < CCR, and the opposite level is output when CNT > CCR.

Look at the PWM output mode through a schematic diagram

In the figure above is a schematic diagram of PWM output. It can be seen that the value of CNT varies from 0 to ARR. When the value of CNT is on the left of CCR, a level is output; when the value of CNT is on the right of CCR, the opposite level is output. This changes the CCR value to change the duty cycle of the output PWM.

Let’s look at the output comparison mode

In the output comparison mode, it does not care whether CNT is larger or smaller than CCR, but only when CNT and CCR values are equal. When the two values are equal, the output level is flipped. In PWM mode, the output level changes twice in a cycle when CNT value increases from 0 to ARR, while in output comparison mode, the output level changes only once in a cycle when CNT value increases from 0 to ARR. Therefore, in the output comparison mode, the output frequency of the timer is half that of the output frequency of the timer in PWM mode.

Now let’s see how the code works. Okay

Void TIM3_CMP_Init(u16 ARr, u16 PSC) {GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); / / can make 36 m RCC_APB2PeriphClockCmd 3 clock timer (RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); / / can make GPIOC clock GPIO_InitStructure. GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); / / initialize the TIM3 TIM_TimeBaseInitStructure. TIM_Period = arr; TIM_TimeBaseInitStructure.TIM_Prescaler = psc; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStructure ); Tim_ocinitstructure. TIM_OCMode = TIM_OCMode_Toggle; TIM_OCMode_Toggle; TIM_OCMode_Toggle; TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init( TIM3, &TIM_OCInitStructure ); TIM_OC2Init( TIM3, &TIM_OCInitStructure ); TIM_OC3Init( TIM3, &TIM_OCInitStructure ); TIM_OC4Init( TIM3, &TIM_OCInitStructure ); TIM_OC1PreloadConfig( TIM3, TIM_OCPreload_Enable ); TIM_OC2PreloadConfig( TIM3, TIM_OCPreload_Enable ); TIM_OC3PreloadConfig( TIM3, TIM_OCPreload_Enable ); TIM_OC4PreloadConfig( TIM3, TIM_OCPreload_Enable ); // ENABLE TIM3 TIM_Cmd(TIM3, ENABLE); }Copy the code

Timer 3 is used here, and all four channels of timer 3 are set to output comparison mode.

Timer initialization code, output comparison mode setting method and PWM mode setting method only mode setting this line of code is different.

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
Copy the code

Just change the output mode from TIM_OCMode_PWM1 to TIM_OCMode_Toggle.

Let’s look at the main function code

#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "pwm.h" // LED0 PA8 LED1 PD2 int main( void ) { u16 led_pwm_val = 0; u8 dir = 1; delay_init(); // Delay function initializes NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); LED_Init(); LED0 = 1; LED1 = 1; delay_ms( 500 ); LED0 = 0; LED1 = 0; // In PWM mode, ARR determines the output frequency and CCRx determines the initial phase of each channel. TIM3_CMP_Init(1000-1, 36-1); TIM3_CMP_Init(1000-1, 36-1); //1K TIM_SetCompare1( TIM3, 0 ); TIM_SetCompare2( TIM3, 200 ); TIM_SetCompare3( TIM3, 400 ); TIM_SetCompare4( TIM3, 600 ); while( 1 ) { delay_ms( 200 ); LED0 = ! LED0; }}Copy the code

Timer 3 clock is 72MHz, after 36 frequency division is 2MHz, automatic loading value is 1000-1, output frequency is 2M / 1000 = 2KHz. The frequency of the output comparison mode should be reduced by half, so the output square wave signal frequency is 2K / 2 = 1KHz.

Next, the initial phase of the output of the four channels is set respectively. The phase of channel 1 is set to 0, and the delay of channel 2 is 1/5 cycle, channel 3 is 2/5 cycle, and channel 4 is 3/5 cycle.

The output frequency of the four channels is 1KHz with a period of 1000us.

It can be seen from the output waveform that the initial phase lags behind successively. If channel 1 is the starting point of 0, channel 2 lags behind 100us, channel 3 lags behind 200us, and channel 4 lags behind 300us.

The channel 2 calculated above lags 1/5 cycle with a period of 1000us, and the 1/5 cycle should be 200us, which is actually measured to be 100us, indicating that the theoretical value of phase calculation should also be halved.

In this way, the timer output comparison mode can be used to control the initial phase of the output square wave by changing the value of the TIMER CCR register.