"First of all, we must affirm the strength of ST company and admit that STM32 is indeed a very good Cortex-M3 core single chip microcomputer. However, his manual is really incomprehensible, especially the Tim module, which is disorganized. After reading it for two days, we almost don't know what to say, which makes people very depressed. At the same time, the description of the supporting firmware library is difficult to correspond to the registers in the manual, which is very hard to study! Powerful is true, but at least it should be accompanied by a clear description~~
In two days, the most basic part of STM32 timer is studied, and the two most basic functions of the timer are realized. The remaining functions need to be further studied.
First of all, it should be noted that the latest version of fwlib firmware library should be v2.0. X. in v1.0. X firmware library, TIM1 module is independent, and the function called is different from other timers; In v2.0 series version, TIM1. H is cancelled, and all tim modules can call Tim. H uniformly. Many of the various codes circulating on the network are based on the V1 version of the firmware library. Some modifications need to be made when porting to the V2 version of the firmware library. All programs in this paper are based on v2.0 firmware library.
The following is an example code of timer up overflow:
C language: TIM1 module generates an upward overflow event
//Step 1. Clock setting: start TIM1
RCC_ APB2PeriphClockCmd(RCC_ APB2Periph_ TIM1, ENABLE);
//Step 2. Interrupt NVIC setting: allow interrupt and set priority
NVIC_ InitStructure.NVIC_ IRQChannel = TIM1_ UP_ IRQChannel; // Update event
NVIC_ InitStructure.NVIC_ IRQChannelPreemptionPriority = 0; // Preemption priority 0
NVIC_ InitStructure.NVIC_ IRQChannelSubPriority = 1; // Response priority 1
NVIC_ InitStructure.NVIC_ IRQChannelCmd = ENABLE; // Allow interrupt
NVIC_ Init(&NVIC_ InitStructure); // Write settings
//Step3.tim1 module setting
void TIM_ Configuration(void)
{
TIM_ TimeBaseInitTypeDef TIM_ BaseInitStructure;
TIM_ OCInitTypeDef TIM_ OCInitStructure;
//TIM1 uses an internal clock
//TIM_ InternalClockConfig(TIM1);
//TIM1 basic settings
//Set the prescaler frequency division coefficient 71, i.e. apb2 = 72m, TIM1_ CLK=72/72=1MHz
//TIM_ Period(TIM1_ ARR) = 1000, when the counter counts up to 1000, an update event is generated, and the count value returns to zero
//Count up mode
//TIM_ RepetitionCounter(TIM1_ RCR) = 0, each upward overflow will generate an update event
TIM_ BaseInitStructure.TIM_ Period = 1000;
TIM_ BaseInitStructure.TIM_ Prescaler = 71;
TIM_ BaseInitStructure.TIM_ ClockDivision = 0;
TIM_ BaseInitStructure.TIM_ CounterMode = TIM_ CounterMode_ Up;
TIM_ BaseInitStructure.TIM_ RepetitionCounter = 0;
TIM_ TimeBaseInit(TIM1, &TIM_ BaseInitStructure);
//Clear the interrupt to avoid an interrupt immediately after the interrupt is enabled
TIM_ ClearFlag(TIM1, TIM_ FLAG_ Update);
//Enable TIM1 interrupt source
TIM_ ITConfig(TIM1, TIM_ IT_ Update, ENABLE);
//TIM1 main switch: on
TIM_ Cmd(TIM1, ENABLE);
}
//Step4. Interrupt service subroutine:
void TIM1_ UP_ IRQHandler(void)
{
GPIOC-》ODR ^= (1《《4); // flash light
TIM_ ClearITPendingBit(TIM1, TIM_ FLAG_ Update); // Clear interrupt
}
The following is the output comparison function to realize TIM1_ Ch1 pin outputs pulses of specified frequency:
C language: TIM1 module realizes output comparison, automatically flips and triggers interrupt
//Step 1. Start TIM1 and pay attention to starting the clock for the corresponding function pin
RCC_ APB2PeriphClockCmd(RCC_ APB2Periph_ TIM1, ENABLE);
RCC_ APB2PeriphClockCmd(RCC_ APB2Periph_ GPIOA, ENABLE);
//Step 2. Pa.8 port is set as OC1 output port of TIM1
GPIO_ InitStructure.GPIO_ Pin = GPIO_ Pin_ 8;
GPIO_ InitStructure.GPIO_ Mode = GPIO_ Mode_ AF_ PP;
GPIO_ InitStructure.GPIO_ Speed = GPIO_ Speed_ 50MHz;
GPIO_ Init(GPIOA, &GPIO_ InitStructure);
//Step 3. Enable the output comparison matching interrupt of TIM1
NVIC_ InitStructure.NVIC_ IRQChannel = TIM1_ CC_ IRQChannel;
NVIC_ InitStructure.NVIC_ IRQChannelPreemptionPriority = 1;
NVIC_ InitStructure.NVIC_ IRQChannelSubPriority = 1;
NVIC_ InitStructure.NVIC_ IRQChannelCmd = ENABLE;
NVIC_ Init(&NVIC_ InitStructure);
//Step4. Tim module setting
void TIM_ Configuration(void)
{
TIM_ TimeBaseInitTypeDef TIM_ BaseInitStructure;
TIM_ OCInitTypeDef TIM_ OCInitStructure;
//TIM1 basic counter settings
TIM_ BaseInitStructure.TIM_ Period = 0xffff; // This must be 65535
TIM_ BaseInitStructure.TIM_ Prescaler = 71; // Pre frequency division 71, i.e. 72 frequency division, gets 1m
TIM_ BaseInitStructure.TIM_ ClockDivision = 0;
TIM_ BaseInitStructure.TIM_ CounterMode = TIM_ CounterMode_ Up;
TIM_ BaseInitStructure.TIM_ RepetitionCounter = 0;
TIM_ TimeBaseInit(TIM1, &TIM_ BaseInitStructure);
//TIM1_ OC1 module settings
TIM_ OCStructInit(& TIM_ OCInitStructure);
TIM_ OCInitStructure.TIM_ OCMode = TIM_ OCMode_ Toggle; // Pin output mode: flip
TIM_ OCInitStructure.TIM_ Pulse = 2000; // Turnover cycle: 2000 pulses
TIM_ OCInitStructure.TIM_ OutputState = TIM_ OutputState_ Enable; // Enable TIM1_ Ch1 channel
TIM_ OCInitStructure.TIM_ OCPolarity = TIM_ OCPolarity_ High; // The output is positive logic
TIM_ OC1Init(TIM1, &TIM_ OCInitStructure); // Write configuration
//Clear interrupt
TIM_ ClearFlag(TIM1, TIM_ FLAG_ CC1);
//Set the TIM1 interrupt source to enable the capture comparison interrupt of the corresponding channel
TIM_ ITConfig(TIM1, TIM_ IT_ CC1, ENABLE);
//TIM1 on
TIM_ Cmd(TIM1, ENABLE);
//Channel output enable
TIM_ CtrlPWMOutputs(TIM1, ENABLE);
}
Step5. Interrupt service subroutine
void TIM1_ CC_ IRQHandler(void)
{
u16 capture;
if(TIM_ GetITStatus(TIM1, TIM_ IT_ CC1) == SET)
{
TIM_ ClearITPendingBit(TIM1, TIM_ IT_ CC1 );
capture = TIM_ GetCapture1(TIM1);
TIM_ SetCompare1(TIM1, capture + 2000);
//Here is an explanation:
//Set TIM1_ The value of CCR1 increases by 2000, so that 2000 pulses are also required for the next tim event,
//Another way is to clear the pulse counter
//TIM_ SetCounter(TIM2,0x0000);
}
}
For Tim operation, it should be noted that STM32 processor needs to turn on the clock independently because of low power consumption. Therefore, don't forget to enable the clock for the modules and pins used. For this reason, I wasted a lot of time ~ ~!
STM32 note (II) Tim module generates PWM
This is the PWM output mode of STM32. The TIM1 module of STM32 is an enhanced timer module. It is born for motor control and can generate three groups of 6-channel PWM. At the same time, each group of 2-channel PWM is complementary and can have a dead band, which can be used to drive the H-bridge.
The following code is a code example of generating a total of 4 PWM channels by using channels 1 and 2 of TIM1 module. For similar codes, please refer to the corresponding example in the firmware library of St
C language: TIM1 module generates PWM with dead band
//Step 1. Turn on Tim and corresponding port clock
//Start GPIO
RCC_ APB2PeriphClockCmd(RCC_ APB2Periph_ GPIOA | RCC_ APB2Periph_ GPIOB | \
RCC_ APB2Periph_ GPIOC | RCC_ APB2Periph_ GPIOD,\
ENABLE);
//Start Afio
RCC_ APB2PeriphClockCmd(RCC_ APB2Periph_ AFIO, ENABLE);
//Start TIM1
RCC_ APB2PeriphClockCmd(RCC_ APB2Periph_ TIM1, ENABLE);
//Step 2. Make corresponding settings for GPIO to output AF
//Pa.8/9 port is set as OC1 output port of TIM1
GPIO_ InitStructure.GPIO_ Pin = GPIO_ Pin_ 8 | GPIO_ Pin_ 9;
GPIO_ InitStructure.GPIO_ Mode = GPIO_ Mode_ AF_ PP;
GPIO_ InitStructure.GPIO_ Speed = GPIO_ Speed_ 50MHz;
GPIO_ Init(GPIOA, &GPIO_ InitStructure);
//The pb.13/14 port is set to TIM1_ Ch1n and TIM1_ CH2n output
GPIO_ InitStructure.GPIO_ Pin = GPIO_ Pin_ 13 | GPIO_ Pin_ 14;
GPIO_ InitStructure.GPIO_ Mode = GPIO_ Mode_ AF_ PP;
GPIO_ InitStructure.GPIO_ Speed
Our other product: