STM32 study notes_6 timer interrupt (on)

TIM

The timer is the most powerful and complex 32 structure.

  1. The functions used by 51 before, generate interrupts at regular intervals.
  2. Output comparison, often used to generate PWM waveforms, drive motors, etc.
  3. Input capture, measure square wave frequency.
  4. Encoder, reads the waveform of the quadrature encoder.

Maximum timing time: 72M/65536/65536=interrupt frequency, the reciprocal of the interrupt frequency is the maximum timing time.

The timer can be cascaded, for example, the maximum timing of 72MHz is 59.65s, cascading once * 65536 * 65536.

type serial number bus Function
Advanced Timer TEAM1、TEAM8 APB2 It has all the functions of a general-purpose timer, and additional functions such as repetition counter, dead zone generation, complementary output, brake input, etc.
General purpose timer TIM2、TIM3、TIM4、TIM5 APB1 It has all the functions of the basic timer, and has additional functions such as internal and external clock source selection, input capture, output comparison, encoder interface, master-slave trigger mode, etc.
basic timer TIM6、TIM7 APB1 It has the functions of timing interrupt and master mode triggering DAC

Increasingly complex and powerful from bottom to top. f103c8t6 has TM1-4 (different chips are different, please refer to the manual!), we mainly study general-purpose timers.

image-20230425201024320

PSC divides the frequency of RCC. For example, if writing 1 means 2 frequency division, it will output 72MHz/2=36MHz. Actual frequency division factor = prescaler value + 1.

The counter is continuously incremented according to the clock frequency, = cleared and an interrupt is generated when the register value is automatically reloaded. UI is interrupt, U is event.

Actively trigger DAC: DAC interrupts will be very frequent and occupy a lot of CPU resources. If the timer can manipulate the slave device to handle the DAC by itself, it will save a lot of CPU resources. TRGO in the picture above is.

image-20230425203158414

On the basis of basic counters, general-purpose registers also support down counting and center-aligned counting (0-reload value-0-reload value...)

Clock optional internal 72MHz clock or external clock.

Timer cascading can be realized, refer to the manual to check which timers and which cascades. The self-output pin CH can also be used as its own clock input, and the function will be expanded later.

The four outputs are output compare circuits, and the left is the input capture circuit.

image-20230425204348250

The shadows in the figure have buffer registers, and the buffer registers will be discussed immediately below.

The repetition counter allows several cycles before an interrupt is triggered.

Output CH1-3 can output complementary waves, useful. In order to prevent the straight-through phenomenon when switching (two inverting circuits switch at the same time, similar to x-shaped), through the DTG dead zone generating circuit, a dead zone is generated before switching, and the upper and lower tubes are all reset to zero before switching.

Brake input in the lower left corner, the timer can be terminated in an abnormal state.

The basic structure is as follows:

image-20230425205237061

Running control is like setting up and down counting.

The interrupt output control is equivalent to a flag bit, which determines whether the interrupt is needed or not.

image-20230425205647303

CK_PSC: Input clock for prescaler.

CNT_EN: Counter enable, high level open. The subsequent prescaler becomes 1, and the frequency is divided by /2, so two rising edges are triggered only once. The counter register is continuously incremented accordingly.

The event is updated when the autoreloader value is reached and the counter is zeroed.

After the prescaler register is modified, it is not changed immediately, but the prescaler buffer is modified after the next counting cycle after the interrupt is triggered, so that the prescaler buffer can be truly controlled.

The principle of frequency division can be seen in the prescaler counter. For example, if the prescaler buffer is set to 1, that is, the actual frequency division factor is 2, then the actual frequency division factor -1 is reached after counting 0 and 1, and the counter is cleared to ++.

C K _ C N T = C K _ P S C / ( P S C + 1 ) CK\_CNT=CK\_PSC / (PSC+1) CK_CNT=CK_PSC/(PSC+1)

For counters it's like this:

image-20230425211659817

The actual frequency division factor is 2, 2 clock cycles before +1, and the update event and interrupt flag register prompt is now interrupted when overflow occurs. The interrupt flag register must be manually cleared in the interrupt routine.

Counter overflow frequency:

C K _ C N T _ O V = C K _ C N T / ( A R R + 1 ) = C K _ P S C / ( P S C + 1 ) / ( A R R + 1 ) CK\_CNT\_OV = CK\_CNT / (ARR + 1) = CK\_PSC / (PSC + 1) / (ARR + 1) CK_CNT_OV=CK_CNT/(ARR+1)=CK_PSC/(PSC+1)/(ARR+1)

arr is the auto-reload register value. Take the reciprocal of the overflow time.

arr also has a buffer register, you can choose whether to use it or not.

image-20230425212615653

As shown in the figure, although arr has been changed to 36, the shadow register has to be updated after this round of interrupts is over.

It is better to turn on this, because if the value of arr is almost added, and then arr shrinks, the counter may have to be added until it overflows and returns to zero, and then it will trigger a small problem such as an interrupt.

Next look at the clock, the clock is what all peripherals need. The configuration is in the systemInit() function.

image-20230425212944952

HSI HSE is an internal and external clock source, and the external one is more stable. Both provide the system clock and some peripherals (AHB APB12) rely on them.

LSE OSC is RTC.

LSI RC is a clock for independent watchdog.

SystemInit() starts the internal clock first, the system temporarily runs at 8MHz, then starts the external clock and enters the PLL phase-locked loop for frequency multiplication, and outputs it after reaching a stable 72MHz.

Therefore, there is a problem with the external clock circuit. When it cannot be switched normally, it may feel that the program runs slowly. It is running with the 8MHz system clock. Or the CSS clock security system may forcefully stop the external circuit. The CSS also participates in the brake input circuit in the Advanced Control Timer.

APB1 prescaler factor of this board is 2, APB2 is 1.

The division factor of the AHB prescaler directly divides PCLK1. Timer 2-7 is: "If the prescaler factor = 1, then the frequency = 36MHz unchanged; otherwise, the frequency * 2", so its internal reference clock is always 72MHz. So are timers 1,8 on APB2.

All clocks are connected with an AND gate, plus an enable circuit.

Code: Timer

process:

  1. RCC。
  2. Set the clock source.
  3. Set the time base unit of the clock source (initialize prescaler, auto-reloader, counter mode).
  4. Set interrupt control (on).
  5. Configure nvic, this uses the NIVC_Init learned earlier.
  6. Set up run controls.
  7. Start the counter.

List of functions needed:

image-20230426005302884

TimeBaseInit: Initialize the prescaler, auto-reloader, counter mode.

TimeBaseStructInit: Assign an initial value to the time base unit.

Cmd: Start the clock.

ITConfig: Enable the corresponding clock interrupt.

The following six are clock source selection, internal clock, ITRx other timer clock, TIx capture channel clock, ETR mode 1, 2 clock, functions for configuring ETR time base unit, polarity, filter and other settings individually.

These five functions are functions to modify the configuration of the time base unit after Init (change the prescaler, change the counting mode, set whether to preload, change the counter value, change the automatic reload value, etc.

image-20230426010613144

image-20230426010918513

Finally there are four functions that get clear registers.

image-20230426010930216

The code is slightly different from exti.

#include "stm32f10x.h"                  // Device header

extern uint16_t cnt;

void Timer_Init(void){
    
    
    //rcc, set timer source, set psc + set arr + set cnt mode(time base unit), set it controller, set nvic it handler, set running control, enable counter
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    TIM_InternalClockConfig(TIM2);//默认也是这个时钟,不写也行
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//滤波器采样,频率越低,采样点数越多,滤波效果越好。不过延迟也越大。采样频率就是内部时钟和这个分频参数共同作用的结果
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    //比如我们想定1s中断一次,CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1),也就是72M / (PSC + 1) / (ARR + 1) = 1
    //所以两者赋值可以是10000-1和7200-1,只要两者都在65535以内就行,赋值不唯一
    TIM_TimeBaseInitStructure.TIM_Period=10000-1;//arr自动重装器值,72M 计数10000次,耗时 10000/72M s
    TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//预分频器值,分7200频,即 10000/(72M/7200) s=1s中断一次。
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器值,高级计数器才用
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
    
    TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);//设为更新中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_Cmd(TIM2,ENABLE);
    
    
}

void TIM2_IRQHandler(void){
    
    
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){
    
    //这里设置为update
        cnt++;
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    }
}

Here the cnt variable is written in main.c, and the extern variable is used to declare "this variable is in another file, you can find the compiler". In fact, the function declaration in .h should also add extern, but it can be omitted.

After starting the development board, you can see that an interrupt is triggered immediately, why is this? The last sentence of TIM_BaseInit is this:

TIMx->EGR = TIM_PSCReloadMode_Immediate;   

We know that the value written to the auto-reload register is not written immediately, but is written into the buffer until the event is updated. At the beginning, after we initialized the auto-reload register, we couldn't write it in, and couldn't trigger an interrupt.

Therefore, we need to manually trigger an update event in TIM_BaseInit, which is the above statement. The price is that an interrupt is triggered immediately after power-on. Update events and update interruptions occur simultaneously.

If you want to remove this interrupt, you can immediately follow TIM_BaseInit with a "TIM_ClearFlag".

Next, we write a use case, because TIM2 and PA0 are one pin, so we set TIM2 to be configured by external clock mode, so that after we connect the infrared shutter to PA0, manually blocking the light once is equivalent to simulating a cycle of the clock .

Modifications needed:

  1. Clock initialization plus GPIOInit, change the internal clock configuration to external clock (mode 2).
void Timer_Init(void){
    
    
    //rcc, set timer source, set psc + set arr + set cnt mode(time base unit), set it controller, set nvic it handler, set running control, enable counter
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);//这里是滤波,太小的话一次红外检测加好多
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period=10-1;
    TIM_TimeBaseInitStructure.TIM_Prescaler=1-1;//十次红外检测,定时器++
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
    
    TIM_ClearFlag(TIM2, TIM_IT_Update);
    
    TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_Cmd(TIM2,ENABLE);
}

In this way, the effect is to create a clock waveform through the infrared sensor for the timer to read.

Guess you like

Origin blog.csdn.net/jtwqwq/article/details/130441253