STM32 timer output comparison time mode

Publisher:春林初盛Latest update time:2016-10-11 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
As mentioned in the SM32 Timer Essentials, the timer can be configured into six modes, as follows:
  TIM_OCMode  Library Description  explain 
 TIM_OCMode_Timing  TIM Output Compare Time Mode  Freeze, output compare not working
 TIM_OOCMode_Active  TIM output compare active mode  When a comparison occurs, the output is forced high
 TIM_OCMode_Inactive  TIM output comparison inactive mode  When a comparison occurs, the output is forced low
 TIM_OCMode_Toggle  TIM output compare trigger mode  When a comparison occurs, the output flips
 TIM_OCMode_PWM1  TIM PWM Mode 1  PWM1
 TIM_OCMode_PWM2  TIM PWM Mode 2  PWM2
Let's talk about the timer output comparison time mode first. As for the output comparison time mode, it is explained above that it actually freezes the output function, that is, when the timer compares the count value, it does nothing. In this case, what is the use of it? In fact, although it has no effect on the output, it can also generate a comparison event, that is, when the count value of the timer is equal to the set comparison value, a timer interrupt can be triggered, and then we can do something with the timer interrupt. It enters the interrupt once every time from 0 to the count value, which is equivalent to timing, so it is called the output comparison time mode!
Here, I use the output compare time mode of the timer to generate PWM waves on any pin as an example. It is still based on my own standard project.
1. Modification of the project
1) A timer is used here, so you need to add the library file stm32f10x_tim.c to the STM32F10x_StdPeriod_Driver project group.
2) Open the stm32f10_conf.h file and remove the original shield of #include "stm32f10x_tim.h".
· 3) Create two new files, OCTiming.c and OCTiming.h, and save them in the src and inc folders of the BSP folder respectively. Then add OCTiming.c to the BSP project group.
 
2. Programming of OCTimingc and OCTiming.h files
First, initialize some pins as PWM output pins. It should be noted that it is best not to initialize the pins corresponding to the timer channels (if the timer pins are configured to GPIO_Mode_AP_PP mode, there will be no phenomenon). Select other pins as output pins. Here I choose the four pins PC6, PC7, PC8, and PC9, and configure them to GPIO_Mode_Out_PP mode. The code is as follows:

/****************************************************************
Function: OC_GPIO_Init
Description: Timer output comparison pin initialization
Input: none
return: none
**********************************************************/
static void OCTiming_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //Turn on GPIOA clock

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}

Next, configure the timer. The code is as follows:

/****************************************************************
Function: OC_TIM2_Init
Description: Set the 4 output comparisons of timer 2
Input: none
return: none
**************************************************************/
static void OCTiming_TIM2_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_TimeBaseStructure.TIM_Period = 65535;//Timing period value
TIM_TimeBaseStructure.TIM_Prescaler = 0;//No pre-division
TIM_TimeBaseStructure.TIM_ClockDivision = 0;//Clock is not divided
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //Increase count
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //Initialize timer


/* -------------------------------------------------------
Timer configuration output comparison time mode:
the clock frequency of the timer is 72M.
The frequency of PC6 output is 72M/CCR1_Val/2=732Hz, and the duty cycle is 50%.
The frequency of PC7 output is 72M/CCR2_Val/2=1099Hz, and the duty cycle is 50%.
The frequency of PC8 output is 72M/CCR3_Val/2=2197Hz, and the duty cycle is 50%.
The frequency of PC9 output is 72M/CCR4_Val/2=4395Hz, and the duty cycle is 50%.
---------------------------------------------------------*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; //Output comparison time mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //Output enable
TIM_OCInitStructure.TIM_Pulse = CCR1_Val; //Set comparison value
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //When the timer count value is less than CCR1_Val, it is high level
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //Initialize TIM2 output comparison channel 11
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable); //Do not automatically re-transfer count value

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //Output enable
TIM_OCInitStructure.TIM_Pulse = CCR2_Val; //Set comparison valueTIM_OC2Init
(TIM2, &TIM_OCInitStructure); //Initialize output comparison channel 2 of TIM2
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable); //Do not automatically re-transfer count

valueTIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //Output enableTIM_OCInitStructure.TIM_Pulse
= CCR3_Val; //Set comparison valueTIM_OC3Init
(TIM2, &TIM_OCInitStructure); //Initialize output comparison channel 3 of TIM2
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable); //Do not automatically re-transfer count valueTIM_OCInitStructure.TIM_OutputState

= TIM_OutputState_Enable; // output enable
TIM_OCInitStructure.TIM_Pulse = CCR4_Val; // set comparison value
TIM_OC4Init(TIM2, &TIM_OCInitStructure); // initialize TIM2 output comparison channel 3
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable); // do not automatically re-transfer count value

TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE); // clear interrupt flag
TIM_Cmd(TIM2, ENABLE); // turn on timer
}

First, configure the timer's time base, here set the timing cycle number to 65535, then set the timing value of each channel of the timer, and turn on the output comparison interrupt of each channel. In this way, every time the timing comparison value wants to match, it will enter an interrupt, and then flip the pin level in the interrupt, and then reset the comparison value, so that the PWM wave can be generated.
Now that the interrupt is turned on, you need to configure the interrupt. The code is as follows:

/****************************************************************
Function: OC_Int_Config
Description: Timer output compare interrupt configuration
Input: none
return: none
**********************************************************/
static void OCTiming_Int_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2 interrupt
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //Priority is 1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

Here, the interrupt priority of TIM2 is set to 1.
You also need to write a total function: OCTiming_Init() to call all the initialization codes above. The code is as follows:

/****************************************************************
Function: OC_Init
Description: Timer output comparison initialization
Input: none
return: none
**********************************************************/
void OCTiming_Init(void)
{
OCTiming_GPIO_Init(); //Output comparison pin configuration
OCTiming_TIM2_Init(); //Timer 2 output comparison initialization
OCTiming_Int_Config(); //Output comparison interrupt configuration
}

Next, change the contents of OCTiming.h to the following:

#ifndef __TIMEBASE_H__
#define __TIMEBASE_H__
#include "stm32f10x.h"

#define CCR1_Val 49152
#define CCR2_Val 32768
#define CCR3_Val 16384
#define CCR4_Val 8192

void OCTiming_Init(void);

#endif

3. Modification of stm32f10x_it.c file
In this file, you need to write an interrupt service function. In this function, the PWM wave is realized by flipping the pin. The code is as follows:

/****************************************************************
Function: TIM2_IRQHandler
Description: Timer 2 interrupt service routine
Input: none
return: none
*************************************************************/
void TIM2_IRQHandler(void)
{
static u16 capture = 0;
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//Output comparison channel 1
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);

GPIO_WriteBit(GPIOC, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6)));//Flip level value, generate PWM wave with frequency of 72M/CCR1_Val/2 and duty cycle of 50%
capture = TIM_GetCapture1(TIM2);//Get comparison value
TIM_SetCompare1(TIM2, capture + CCR1_Val);//Reset comparison value
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)//Output comparison channel 1
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

GPIO_WriteBit(GPIOC, GPIO_Pin_7, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_7)));//Flip level value, generate PWM wave with frequency of 72M/CCR2_Val/2 and duty cycle of 50%
capture = TIM_GetCapture2(TIM2);//Get comparison value
TIM_SetCompare2(TIM2, capture + CCR2_Val);//Reset comparison value
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)//Output comparison channel 1
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);

GPIO_WriteBit(GPIOC, GPIO_Pin_8, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_8)));//Flip the level value to generate a PWM wave with a frequency of 72M/CCR3_Val/2 and a duty cycle of 50%
capture = TIM_GetCapture3(TIM2);//Get comparison value
TIM_SetCompare3(TIM2, capture + CCR3_Val);//Reset comparison value
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)//Output comparison channel 1
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);

GPIO_WriteBit(GPIOC, GPIO_Pin_9, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_9))); //Flip the level value to generate a PWM wave with a frequency of 72M/CCR4_Val/2 and a duty cycle of 50%
capture = TIM_GetCapture4(TIM2); //Get the comparison value
TIM_SetCompare4(TIM2, capture + CCR4_Val); //Reset the comparison value
}
}

In the interrupt function, if the comparison interrupt flag is detected, GPIO_WriteBit(GPIOC, GPIO_Pin_7, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_7))); will be called to flip the pin level. After flipping the level, the current capture value is obtained, and then our capture value is reset on this basis. Here, I reset the comparison value to the same as the original comparison time (of course, it can also be set differently). In this way, the pin output is high level for half of the time and low level for half of the time, so that the output duty cycle is 50%. For example, if the CCR1_Val value is 49152, each time the count value reaches this, the pin level is flipped, and then the comparison value is reset to 49152 + 49152. Considering that the timer is a 16-bit timer and will overflow, the reset count value is 32768. In this case, there are 49152 count value times to output high level, and 49152 count value times to output low level, so the frequency of the final output PWM wave is 72M/49152/2=732Hz, and the duty cycle is 50%.
 
4. Writing the main function
The main function actually does nothing, it just uses the initialization function of each module. The code is as follows:

/****************************************************************
Function: main
Description: main entry
Input: none
return: none
*************************************************************/
int main(void)
{
BSP_Init();
OCTiming_Init(); //Output comparison initialization
PRINTF("\nmain() is running!\r\n");
while(1)
{
LED1_Toggle();
Delay_ms(1000);
}
}

5. Testing
Connect the oscilloscope probe to pins PC6, PC7, PC8, and PC9 respectively, and you can see the waveform and frequency output by each pin.
The output frequency of PC6 is 732Hz, and the duty cycle is 50% PWM wave, as shown in the following figure:
STM32 timer output compare flip mode - ziye334 - ziye334's blog
The output frequency of PC7 is 0.99Hz, and the duty cycle is 50% PWM wave, as shown in the following figure:
STM32 timer output compare flip mode - ziye334 - ziye334's blog
The output frequency of PC8 is 2197Hz, and the duty cycle is 50% PWM wave, as shown in the following figure:
STM32 timer output compare flip mode - ziye334 - ziye334's blog
The output frequency of PC9 is 4395Hz, and the duty cycle is 50% PWM wave, as shown in the following figure:
STM32 timer output compare flip mode - ziye334 - ziye334's blog

Keywords:STM32 Reference address:STM32 timer output comparison time mode

Previous article:STM32 timer output compare active mode
Next article:STM32 generates 7 PWM waves

Recommended ReadingLatest update time:2024-11-15 14:07

Detailed explanation of STM32 learning Flash (main storage block, system memory and option bytes)
    When it comes to STM32's FLSAH, our first reaction is that it is used to install programs. In fact, the STM32's on-chip FLASH is not only used to install programs, but also to install chip configuration, chip ID, bootloader, etc. Of course, FLASH can also be used to store data.      I have collected some informati
[Microcontroller]
Solution to the problem of stm32 entering HardFault_Handler
1. First, set a breakpoint at while (1) of HardFault_Handler. 2. Wait for the code to run to this point, then check the register LR. On the left is the project and the other is the register. The LR above is what I copied normally. Generally, when entering hardfault, it will become the value in the figure below. At
[Microcontroller]
Solution to the problem of stm32 entering HardFault_Handler
Using STM32's SysTick to achieve precise delay
Use SysTick's normal counting mode to manage delays. static u8  fac_us=0; //us delay multiplier static u16 fac_ms=0; //ms delay multiplier   //Initialize delay function void delay_init(u8 SYSCLK) {   SysTick- CTRL&=0xfffffffb;  //Clear bit2, select external clock*/      fac_us = SYSCLK/8;                   
[Microcontroller]
stm32 controls lcd to write characters, draw lines, Chinese characters, etc.
1. Algorithm for drawing straight lines          When drawing a straight line, due to the granularity of the display on the LCD, the problem of the pace of the x and y axes is distinguished. The problem of pace involves the problem of slope. Therefore, even if the line drawing algorithm is completed, it is necessary t
[Microcontroller]
Advanced use of STM32 timers
[Microcontroller]
stm32 memory space allocation learning
The figure is a memory map of stm32, where the code area starts at 0x0800 0000, and its end address is 0x0800 0000 plus the actual chip flash size. Its ram start address is 0x2000 0000, and the end address is still the actual chip ram size.
[Microcontroller]
stm32 memory space allocation learning
STM32 printf redirection
Configuration method of using printf to send data in STM32 serial communication (development environment Keil RVMDK)   It is very convenient to use printf to send data in the STM32 serial communication program. However, there are always problems when using it for the first time. The most common problem is that the mai
[Microcontroller]
Use of STM32 ADC and internal temperature sensor
  STM32 comes with 1-3 ADC modules, and the sampling accuracy reaches 12 bits, which is a small upgrade compared to the 10 bits of the AVR microcontroller used in those days. This test program uses the ADC DMA interrupt method, so that the CPU can hand over the ADC task to the hardworking DMA. When the DMA completes a
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号