• 【STM32】定时器


    systick定时器

    【STM32】Systick定时器-CSDN博客

    0.通用定时器框图

    1)设置RCC----》开启时钟

    2)选择时钟模式---》配置时钟源

    3)设置时基单元---》定时器初始化

    4)使能中断---》中断输出配置

    5)设置NVIC---》NVIC中断分组+NVIC配置

    6)TIM使能

    1. /**
    2. * 函 数:定时中断初始化
    3. * 参 数:无
    4. * 返 回 值:无
    5. */
    6. void Timer_Init(void)
    7. {
    8. /*开启时钟*/
    9. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟
    10. /*配置时钟源*/
    11. TIM_InternalClockConfig(TIM2); //选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
    12. /*时基单元初始化*/
    13. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
    14. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
    15. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
    16. /**
    17. 这里设置表示我们要计时1s,1s进入一次中断
    18. 72 000 000/(7200-1)/(1 0000-1)=1s
    19. */
    20. TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //计数周期,即ARR的值
    21. TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //预分频器,即PSC的值
    22. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
    23. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
    24. /*中断输出配置*/
    25. TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除定时器更新标志位
    26. //TIM_TimeBaseInit函数末尾,手动产生了更新事件
    27. //若不清除此标志位,则开启中断后,会立刻进入一次中断
    28. //如果不介意此问题,则不清除此标志位也可
    29. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //开启TIM2的更新中断
    30. /*NVIC中断分组*/
    31. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC为分组2
    32. //即抢占优先级范围:0~3,响应优先级范围:0~3
    33. //此分组配置在整个工程中仅需调用一次
    34. //若有多个中断,可以把此代码放在main函数内,while循环之前
    35. //若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
    36. /*NVIC配置*/
    37. NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量
    38. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //选择配置NVIC的TIM2线
    39. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
    40. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //指定NVIC线路的抢占优先级为2
    41. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1
    42. NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设
    43. /*TIM使能*/
    44. TIM_Cmd(TIM2, ENABLE); //使能TIM2,定时器开始运行
    45. }

    1.时钟源

    1)内部时钟APB

    2)外部时钟模式二ETR

    3)内部触发输入时钟ITR0,ITR1...

    4)外部时钟模式一TI1FP1来自于通道1,TI2FP2来自于通道2

    2.控制器

    触发控制器会将触发信号传输给其他定 时器的触发输入时钟

    3.输入捕获:测量脉冲时间

    计数器实际上是与比较寄存器的影子寄存器进行比较的。

    1)由图可知从通道1进入可能会被变为输入捕获通道1或者输入捕获通道2

    2)上升沿/下降沿进行捕获,产生一个时间,然后进入捕获通道(获得计数值),

    4.输出比较

    1)写入一个比较值

    2)配置预分频器

    3)计数值  VS  比较值(影子寄存器)比较--》触发比较事件

    4)在转移到影子寄存器有一个缓冲作用

    5)有8种输入模式

    1.STM32的定时器学习要点

    参考手册

    STM32F1xx中文参考手册.pdf · 林何/STM32F103C8 - 码云 - 开源中国 (gitee.com)

    1.通用定时器和其他的区别

    1)其实最多可以有17个定时器

    2)功能差别

    2.STM32定时器的学习要点

    1)先学会定时器基本概念的使用

    2)高级功能用到到时再去细看

    3)设计本身的复杂性导致学习难度大,要有耐心

    4)很多书面概念要搞清楚,需要不断前后对照

    5)学习三宝:数据手册+外设库源码+例程

    2.通用定时器的数据手册

    进行比较计数器和寄存器的值进行电平的反转。

    1.TIMx主要功能

    定时器是基于计数器进行的,分频,然后走一格就计数一次。

    PWM生成:就是输出比较产生的电流

    单脉冲:表示就输出一次

    1.向上/向下

    向上:加法计数器【从x不断++到65535】

    向下:减法计数器【从x不断--到0】

    2.TIM的所属APB

    3.发生的中断/DMA

    2.通用定时器框图

    3.预分频器

    1.时基单元

    1)可以在运行的时候对预分频器的值进行修改

    我们这里可以在运行时对其进行修改的是count计数器(可以在当前事件执行时进行更新,也可以等到下一次更新事件发生后在进行改变)

    预分频器(预分频器的值只能在下一次更新事件到来时被采用。)

    2)影子寄存器【预装载寄存器】:在硬件上实际上是存在的,但是没有给他分配地址(不需要程序进行干预)---实际上装的是ARR的值,在2种情况下才会被加载到影子寄存器中:

            1.立即加载到影子寄存器【如果此时计数是300,则会立刻变成600】----》无缓存区

            2.等这个时间计数结束后才会重新加载【只能等到执行到0或者600时才会被重新赋值】--》有缓存区

    1.1 TIMx_CR1_ARPE:修改位(有无缓存区)

    1.2 TIMx_CR1_UDIS:中断允许位

    1.3 TIMx_CR1_CEN:时钟和计数器的使能

    1)计数器的结果是分频后的结果

    2)只有在定时器开启时才可以使能计数器

    注意点:

    真正的计时器使能信号CNR_EN(定时器打开)是在CEN的一个时钟周期后被设置(表示计数器是在定时器打开后的一个周期才开始计时)

    2.预分频器描述

    预分频器可以在工作时被改 变。但是新的预分频器参数只能在下一次更新事件到来时被采用。【因为预分频器中带有缓冲器】

    2.1 计数器的时序图:1分频--2分频

    2.2 计数器的时序图:1分频--4分频

    4.计数器

    1.向上计数器模式

    1.与51单片机不同

    2.基本概念

    3.是否产生更新事件

    4.计数器时序图

    5.ARPE=0时的更新事件【立即模式-不缓存】

    6.ARPE=1时的更新事件【下一周期改变--缓存】

    2.向下计数模式

    注意点:

    向下计数模式没有【立即模式】,因为如果原来ff,然后现在走到05,然后修改为36,不可能重新回36在继续减,这是不合理的。

    3.中央对齐模式(向上/向下计数)

    在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器 溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。

    1.注意点

    1)在这个模式,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。

    2)注意加减的边界值问题:

            加法计数器是寄存器值-1

            减法计数器是减到1

    2.计数器时序图

    3.ARPE=1时的更新事件【下一周期更新--缓存】

    5.时钟选择

    1.内部时钟(CK_INT)--常规模式【从APB过来的】

    1.使能

    通过设置TIMx_SMCR寄存器的SMS=000,表示使用内部时钟【常规模式】。

    2.外部时钟模式1:外部输入脚(TIx)

    3.外部时钟模式2:外部触发输入(ETR)

    4.内部触发输入(ITRx):一个定时器的输出作为另外一个定时器的输入

    6.库函数

    1.TIM_TimeBaseInit

    1. void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
    2. {
    3. uint16_t tmpcr1 = 0;
    4. /* Check the parameters */
    5. assert_param(IS_TIM_ALL_PERIPH(TIMx));
    6. assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));
    7. assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));
    8. tmpcr1 = TIMx->CR1;
    9. if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||
    10. (TIMx == TIM4) || (TIMx == TIM5))
    11. {
    12. /* Select the Counter Mode */
    13. tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
    14. tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
    15. }
    16. if((TIMx != TIM6) && (TIMx != TIM7))
    17. {
    18. /* Set the clock division */
    19. tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
    20. tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
    21. }
    22. TIMx->CR1 = tmpcr1;
    23. /* Set the Autoreload value */
    24. //要计数的值
    25. TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;
    26. /* Set the Prescaler value */
    27. //预分频参数
    28. TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
    29. if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))
    30. {
    31. /* Set the Repetition Counter value */
    32. TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;
    33. }
    34. /* Generate an update event to reload the Prescaler and the Repetition counter
    35. values immediately */
    36. //预分频器参数的改变
    37. TIMx->EGR = TIM_PSCReloadMode_Immediate;
    38. }

    2.TIM_ITConfig

    1. void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
    2. {
    3. /* Check the parameters */
    4. assert_param(IS_TIM_ALL_PERIPH(TIMx));
    5. assert_param(IS_TIM_IT(TIM_IT));
    6. assert_param(IS_FUNCTIONAL_STATE(NewState));
    7. if (NewState != DISABLE)
    8. {
    9. /* Enable the Interrupt sources */
    10. TIMx->DIER |= TIM_IT;
    11. }
    12. else
    13. {
    14. /* Disable the Interrupt sources */
    15. TIMx->DIER &= (uint16_t)~TIM_IT;
    16. }
    17. }

    7.定时器例程分析和编程实践

    1.RCC_Configuration

    TIM2接APB1,GPIOB接APB2

    2.GPIO_Configuration

    配置的是GPIOB

    3.NVIC_Configuartion

    1. void NVIC_Configuration(void)
    2. {
    3. NVIC_InitTypeDef NVIC_InitStructure;
    4. #ifdef VECT_TAB_RAM
    5. /* Set the Vector Table base location at 0x20000000 */
    6. NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
    7. #else /* VECT_TAB_FLASH */
    8. /* Set the Vector Table base location at 0x08000000 */
    9. NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
    10. #endif
    11. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    12. /* Enable the TIM1 Interrupt */
    13. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    14. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    15. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    16. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    17. NVIC_Init(&NVIC_InitStructure);
    18. }

     4.TIM2_IRQHandler

    5.时钟编写

    8.代码移植

    1.先写定时器

    如果不知道定时器的名字是什么可以去“startup_stm32f10x_hd.s”查看

    再去“stm32f10x_it.c”中填写

    2.RCC_Configuration

    注意点:

    TIM2和GPIOB所对应的APB对应不一样,所以一定要分开声明,要不然会出现错误。

    TIM2---》APB2

    GPIOB--》APB1

    1. void RCC_Configuration(void)
    2. {
    3. //打开时钟
    4. //注意点:
    5. //TIM2和GPIOB的APB不一样,所以只能分开声明,要不然不起效果
    6. // RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB2Periph_GPIOB, ENABLE);
    7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    8. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    9. }

    3.GPIO_Configuration

    1. void GPIO_Configuration(void)
    2. {
    3. GPIO_InitTypeDef GPIO_InitStructure;
    4. /* GPIOA Configuration: */
    5. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
    6. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    7. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    8. GPIO_Init(GPIOB, &GPIO_InitStructure);
    9. GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET);
    10. }

    4.NVIC_Configuration

    1. void NVIC_Configuration(void)
    2. {
    3. NVIC_InitTypeDef NVIC_InitStructure;
    4. #ifdef VECT_TAB_RAM
    5. /* Set the Vector Table base location at 0x20000000 */
    6. NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
    7. #else /* VECT_TAB_FLASH */
    8. /* Set the Vector Table base location at 0x08000000 */
    9. NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
    10. #endif
    11. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    12. /* Enable the TIM1 Interrupt */
    13. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    14. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    15. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    16. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    17. NVIC_Init(&NVIC_InitStructure);
    18. }

    5.APB的分频问题

    TIM2接APB1,GPIOB接APB2

    我们APB1不能超过36MHZ,所以要对72MHZ进行分频

    1. //72MHZ定时器的定义
    2. // 主频是72MHz,HCLK是72M,PCLK2是72M,PCLK1是36M
    3. // TIM2接在PCLK1下(APB1)所以源是36M,CK_CNT是36M/7200=5KHz
    4. TIM_TimeBaseStructure.TIM_Prescaler = 7199;
    5. //例如:时钟频率=72/(时钟预分频+1)
    6. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    7. // 计数个数是10000,所以计数时间是10000*1/5000=2s
    8. TIM_TimeBaseStructure.TIM_Period = 9999;//自动重装载寄存器周期的值(定时时间)累计
    9. //0xffff 个频后产生个更新或者中断(也就是说定时时间到)

    6.完整代码

    main

    1. #include "stm32f10x.h" // Device header
    2. /**
    3. 根据定时器2来实现数码管每隔1秒闪烁一次
    4. */
    5. void RCC_Configuration(void);
    6. void GPIO_Configuration(void);
    7. void NVIC_Configuration(void);
    8. int main(){
    9. //设置TIM2定时器
    10. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    11. RCC_Configuration(); //系统时钟配置
    12. NVIC_Configuration(); //NVIC配置
    13. GPIO_Configuration(); //通用IO端口配置
    14. //72MHZ定时器的定义
    15. // 主频是72MHz,HCLK是72M,PCLK2是72M,PCLK1是36M
    16. // TIM2接在PCLK1下(APB1)所以源是36M,CK_CNT是36M/7200=5KHz
    17. TIM_TimeBaseStructure.TIM_Prescaler = 7199;
    18. //例如:时钟频率=72/(时钟预分频+1)
    19. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    20. // 计数个数是10000,所以计数时间是10000*1/5000=2s
    21. //注意点:我们计算出来的值是5,但是我们实际上是从0开始,所以我们这里要-1
    22. TIM_TimeBaseStructure.TIM_Period = 4;//自动重装载寄存器周期的值(定时时间)累计
    23. //0xffff 个频后产生个更新或者中断(也就是说定时时间到)
    24. TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    25. //初始化定时器2
    26. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    27. //打开中断,溢出中断
    28. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    29. //定时器打开
    30. TIM_Cmd(TIM2, ENABLE);
    31. while (1);
    32. //进入中断
    33. return 0;
    34. }
    35. void RCC_Configuration(void)
    36. {
    37. //打开时钟
    38. //注意点:
    39. //TIM2和GPIOB的APB不一样,所以只能分开声明,要不然不起效果
    40. // RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB2Periph_GPIOB, ENABLE);
    41. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    42. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    43. }
    44. void GPIO_Configuration(void)
    45. {
    46. GPIO_InitTypeDef GPIO_InitStructure;
    47. /* GPIOA Configuration: */
    48. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
    49. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    50. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    51. GPIO_Init(GPIOB, &GPIO_InitStructure);
    52. //使亮数码管
    53. GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET);
    54. }
    55. void NVIC_Configuration(void)
    56. {
    57. NVIC_InitTypeDef NVIC_InitStructure;
    58. #ifdef VECT_TAB_RAM
    59. /* Set the Vector Table base location at 0x20000000 */
    60. NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
    61. #else /* VECT_TAB_FLASH */
    62. /* Set the Vector Table base location at 0x08000000 */
    63. NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
    64. #endif
    65. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    66. /* Enable the TIM1 Interrupt */
    67. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    68. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    69. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    70. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    71. NVIC_Init(&NVIC_InitStructure);
    72. }

    stm32f10x_it.c

    1. void TIM2_IRQHandler(void){
    2. if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //检测制定的中断是否发生
    3. {
    4. TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断处理位。
    5. //LED的取反
    6. GPIO_WriteBit(GPIOB, GPIO_Pin_8, !GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8));
    7. }
    8. }

    9.问题解决:APB频率计算问题

    cnt的计数公式 

    cnt=1s*频率值(HZ)

    例如:

    此时TIM2一定是分完频,结果为36MHZ

    初始化:TIM_TimeBaseStructure.TIM_Prescaler = 7199;--》【最后要+1】

    分频后的频率=36M/72 00=5KHZ

    实际测试得到的是1KHZ的结果,说明前面分析有误

    初始化:计数个数为1 0000个

    计数时间=个数*f(1/周期)

    所以:计数时间为:1 0000*1/5000=2s

    结论:APB1时钟确实是36MHZ,但是APB1到定时器时钟那边中间被乘以2,所以又变成72MHZ了。

    10.定时器定时中断

    1.初始化

    1. /**
    2. * 函 数:定时中断初始化
    3. * 参 数:无
    4. * 返 回 值:无
    5. */
    6. void Timer_Init(void)
    7. {
    8. /*开启时钟*/
    9. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟
    10. /*配置时钟源*/
    11. TIM_InternalClockConfig(TIM2); //选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
    12. /*时基单元初始化*/
    13. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
    14. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
    15. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
    16. /**
    17. 这里设置表示我们要计时1s,1s进入一次中断
    18. 72 000 000/(7200-1)/(1 0000-1)=1s
    19. */
    20. TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //计数周期,即ARR的值
    21. TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //预分频器,即PSC的值
    22. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
    23. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
    24. /*中断输出配置*/
    25. TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除定时器更新标志位
    26. //TIM_TimeBaseInit函数末尾,手动产生了更新事件
    27. //若不清除此标志位,则开启中断后,会立刻进入一次中断
    28. //如果不介意此问题,则不清除此标志位也可
    29. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //开启TIM2的更新中断
    30. /*NVIC中断分组*/
    31. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC为分组2
    32. //即抢占优先级范围:0~3,响应优先级范围:0~3
    33. //此分组配置在整个工程中仅需调用一次
    34. //若有多个中断,可以把此代码放在main函数内,while循环之前
    35. //若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
    36. /*NVIC配置*/
    37. NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量
    38. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //选择配置NVIC的TIM2线
    39. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
    40. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //指定NVIC线路的抢占优先级为2
    41. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1
    42. NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设
    43. /*TIM使能*/
    44. TIM_Cmd(TIM2, ENABLE); //使能TIM2,定时器开始运行
    45. }

    2.中断函数

    1. uint16_t Num; //定义在定时器中断里自增的变量
    2. /**
    3. * 函 数:TIM2中断函数
    4. * 参 数:无
    5. * 返 回 值:无
    6. * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
    7. * 函数名为预留的指定名称,可以从启动文件复制
    8. * 请确保函数名正确,不能有任何差异,否则中断函数将不能进入
    9. */
    10. void TIM2_IRQHandler(void)
    11. {
    12. if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //判断是否是TIM2的更新事件触发的中断
    13. {
    14. Num ++; //Num变量自增,用于测试定时中断
    15. TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除TIM2更新事件的中断标志位
    16. //中断标志位必须清除
    17. //否则中断将连续不断地触发,导致主程序卡死
    18. }
    19. }
  • 相关阅读:
    计算通过率逾期率并绘制通过率逾期率曲线
    Matlab 基础与应用
    什么是邮件签名证书?
    React组件的生命周期
    关于项目、项目集、项目组合以及运营管理之间的关系
    muduo库的高性能日志库(四)——LogFile文件
    PostgreSQL安装异常,服务无法启动导致创建服务器超时
    鸿蒙Harmony应用开发—ArkTS声明式开发(触摸事件)
    使用正则表达式分割字符串
    第一百一十六节 Java 面向对象设计 - Java 终止块
  • 原文地址:https://blog.csdn.net/m0_63077733/article/details/134244217