Use the common Timer 2 to generate an interrupt. Count mode: Increase the Count!
I. Programming Configuration
1. First configure the interrupt. The timer interrupt must be configured. The Code is as follows:
void TIM2_NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}
This part is not detailed.
2. Timer configuration is the focus
/* Tim_period -- 1000 tim_prescaler -- 71 --> the interrupt period is 1 ms */void tim2_configuration (void) {tim_timebaseinittypedef tim_timebasestructure; duration (duration, enable); tim_deinit (tim2 ); tim_timebasestructure.tim_period = 1000;/* automatically reload the value of the Register cycle (Count value) * // * generate an update or interrupt after the accumulated tim_period frequency */tim_timebasestructure.tim_prescaler = (72-1);/* Clock pre-minute frequency 72 m/72 */clock = tim_ckd_div1; /* sampling frequency */tim_timebasestructure.tim_countermode = tim_countermode_up;/* up counting mode */tim_timebaseinit (tim2, & tim_timebasestructure); tim_clearflag (tim2, tim_flag_update ); /* clear the overflow interrupt mark */tim_itconfig (tim2, tim_it_update, enable); tim_cmd (tim2, enable);/* enable the clock */rcc_apb1periphclockcmd (disable, disable ); /* disable waiting for use first */}
Find the struct.
TIM_TimeBaseInitTypeDef{uint16_t TIM_ClockDivision uint16_t TIM_CounterMode uint16_t TIM_Period uint16_t TIM_Prescaler uint8_t TIM_RepetitionCounter }
1. TIM_ClockDivision is used to set the clock frequency division. Its value can be
# Define |
Tim_ckd_div1 (uint16_t) 0x0000) |
# Define |
Tim_ckd_div2 (uint16_t) 0x0100) |
# Define |
Tim_ckd_div4 (uint16_t) 0x0200) |
2. TIM_CounterMode is used to set the count mode.
# Define |
Tim_countermode_centeraligned1 (uint16_t) 0x0020) |
# Define |
Tim_countermode_centeraligned2 (uint16_t) 0x0040) |
# Define |
Tim_countermode_centeraligned3 (uint16_t) 0x0060) |
# Define |
Tim_countermode_down (uint16_t) 0x0010) |
# Define |
Tim_countermode_up (uint16_t) 0x0000) |
3. TIM_Period
Specifies the period value to be loaded into the active Auto-Reload Register at the next update event. This parameter must be a number between 0x0000 and 0xFFFF.
It's just a reload value!
4. TIM_Prescaler is obviously a clock and frequency division coefficient.
Specifies the prescaler value used to divide the TIM clock. This parameter can be a number between 0x0000 and 0 xFFFF
The setting range is wide. Here is a formula.
5. TIM_RepetitionCounter
Specifies the repetition counter value. Each time the RCR downcounter reaches zero, an update event is generated and counting restarts from the RCR value (N)
This is used in PWM. You can skip this step.
6. Configure the interrupt and clear the interrupt flag
TIM_ClearFlag (TIM2, TIM_FLAG_Update);/* clear the overflow interrupt flag */TIM_ITConfig (TIM2, TIM_IT_Update, ENABLE );
Now the configuration of TIM2 is complete! The final result is:
/* TIM_Period -- 1000 TIM_Prescaler -- 71 --> the interruption period is 1 ms */
7. An initialization function is missing, which is to set TIMx to the default value!
void TIM_DeInit(TIM_TypeDef* TIMx){ /* Check the parameters */ assert_param(IS_TIM_ALL_PERIPH(TIMx)); switch (*(uint32_t*)&TIMx) { case TIM1_BASE: RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE); break; case TIM2_BASE: RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE); break; case TIM3_BASE: RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE); break; case TIM4_BASE: RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE); break; case TIM5_BASE: RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE); break; case TIM6_BASE: RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE); break; case TIM7_BASE: RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE); break; case TIM8_BASE: RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, DISABLE); break; default: break; }}
We can see that the default values of various timers are set here. We only need to input a parameter to automatically find the corresponding branch for initialization, which is very clear!
2. There is no doubt how can we implement the interrupt function since we have an interruption? Where can I implement it? Next, let's look at the interrupt function we implemented in the it. c file!
void TIM2_IRQHandler(void){if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) {TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update); time++;} }
Look at what was done in the interrupt. It's okay to find the manual. You can see this
TIM_IT_Update: TIM update Interrupt source TIM_IT_CC1: TIM Capture Compare 1 Interrupt source TIM_IT_CC2: TIM Capture Compare 2 Interrupt source TIM_IT_CC3: TIM Capture Compare 3 Interrupt source TIM_IT_CC4: TIM Capture Compare 4 Interrupt source TIM_IT_COM: TIM Commutation Interrupt source TIM_IT_Trigger: TIM Trigger Interrupt source TIM_IT_Break: TIM Break Interrupt source
This is the input parameter of the function. For various interrupt methods, Checks whether the TIM interrupt has occurred or not. it is used to check whether a corresponding interrupt is generated, because we set the TIM_IT_Update interrupt mode when we set the interrupt, that is, the update event. Reload the initial value. At least I understand this.
In the interrupt, the interrupt flag is paid off to facilitate the next interruption. Then, the global variable time is automatically added to 1 to facilitate the detection in the main function!
Okay. The code for pasting the main function should not be a problem.
/******* The program that does not perform the peripheral test is: press the "pa0" button to display only one LED lamp ****** // ******* because the program that does not perform the peripheral test is: the serial port uses pa9-> (T <-> T), pa9-> (r <-> r) *****/# include "stm32f10x. H "# include" LED. H "# include" ick. H "# include" delay. H "# include" usart. H "# include" stdio. H "# include" timer3.h "volatile u32 time; // MS timing variable int main (void) {// initialize gpioled_gpio_config (); // initialize the system timer systick_init (); usartdomainconfig ();/* tim2 scheduled configuration */tim2_nvic_configuration (); tim2_configuration (); printf ("\ r \ n (" _ date _ "-" _ time _ ") \ r \ n"); start_time; while (1) {If (time = 1000)/* 1 s time to */{time = 0;/* led1 reverse */gpio_writebit (gpioa, gpio_pin_0, (bitaction) (1-gpio_readoutputdatabit (gpioa, gpio_pin_0 ))));}}}