一位萌新为参加robomaster所做的前期准备–stm32基础(三)(定时器中断)

一位萌新为参加robomaster所做的前期准备–stm32基础(三)(定时器中断)


前段时间,由于在调试步兵车的底盘以及云台代码,调pid参数,研读新规则,小组开会,有些忙,没有及时更新,现在抽空更新文档 (嘿嘿)

一、实验完成目的:利用stm32中的定时器来进行中断程序,从而对led灯的闪灭进行控制(有点类似用延时函数对led灯进行重复亮暗),利用定时器中断控制led灯目的在于控制系统是内部的,到达一定时间可以自行产生中断,在此期间可以做其他的任务。
二、方案:
①该实验要用到led,故要运用到gpio等函数(打开led端口时钟,配置gpio等)
②需要运用led相关函数,熄灭led,点亮led,翻转led亮暗
③需要运用到通用定时器tim3,需对其进行打开相关时钟,设置分频系数,计数溢出值,计数模式以及对中断优先级的设置
④需要编写中断服务函数
三、流程图
在这里插入图片描述
四、主要代码

int main(void)
{  
leds_init();    //初始化gpio,将led灯熄灭
TIM3_Init();   //初始化TIM并进行相关配置
while(1) {   
        sw_delay_ms(200);;    //(自行加入的,控制led1,定时器中断控制的led2作比较,可以不要)
        led_toggle(LED_1) ;
	}
}

本实验需要掌握的关键代码:
void TIM3_Init(void)
{   	
 TIM_TimeBaseInitTypeDef	TIM_TimeBaseInitStruct;
	//初始定时器(与配置io口类似,定时器的初始化也是给一个结构体变量赋值,把参数传送给初始化函数.)
 NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3 , ENABLE); //打开时钟
TIM_DeInit(TIM3);  
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1 ; //时钟分割
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up ;
//配置计数模式(向上计数)
TIM_TimeBaseInitStruct.TIM_Period = 9999 ;
//设置在下一个更新事件装入活动的自动重装载寄存器周期的值arr
TIM_TimeBaseInitStruct.TIM_Prescaler = 7199 ;
//设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct ) ;  
TIM_ClearFlag(TIM3, TIM_FLAG_Update);  
TIM_ITConfig(TIM3, TIM_IT_Update,ENABLE);   
//使能TIM3的更新中断
	 TIM_Cmd(TIM3, ENABLE);   
//中断优先级NVIC设置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;   
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
NVIC_Init(&NVIC_InitStructure);
}

//中断服务函数
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET){
//检查TIM3更新中断发生与否
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
//清除TIM3更新中断标志
	led_toggle(LED_2);  
	}
}
//实验现象可以看到led1是由延时函数控制的,led2是由定时器内部中断控制的,由于给的参数不一样于是它们的亮暗时间不一样。如果不要led1,则主函数中的while函数可以为空

四、中断相关知识:
①定时器的溢出公式为:溢出时间(秒)= ((ARR+1)*(PSC+1))/ TIMx时钟CK_INT(MHz)
(程序中的溢出时间就为1s,TIMx时钟CK_INT(MHz)为72)
②定时器中断的一般步骤
1-配置时基初始化结构体
2-开启定时器更新中断(即定时时间到了)
3-配置中断优先级(开启定时器中断,配置NVIC)
4-使能定时器
5-编写中断服务函数
6-编写main函数
③计数器模式
通用定时器可以向上计数、向下计数、向上向下双向计数模式。
向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
在这里插入图片描述
④STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。
五、总结
本次实验已经大体掌握中断的原理及对led闪烁的编程思路,理解各个代码意思。一开始对void TIM3_IRQHandler(void)函数不理解,认为主函数及其他中并没有调用该函数,为什么会执行?(现理解为中断后就会自动执行该函数),到现在对中断优先级的制配不太理解(即红色标注的代码),不明白该如何制配及运用。

对于通用定时器的配置:
① 定义定时器结构体
② 打开TIM3定时器时钟RCC_APB1PeriphClockCmd()
③ 对结构体中的相关变量进行配置(TIM_ClockDivision-时钟分割;TIM_CounterMode-设置计数模式;TIM_Period-设置重装值;TIM_Prescaler-设置预分频值)
④ 根据 TIM_TimeBaseInitStruct 中指定的参数初始化 TIMx 的时间基数单位 TIM_TimeBaseInit()
⑤ 清除待处理标志位TIM_ClearFlag()
⑥ 使能TIMx中断TIM_ITConfig()
⑦ 使能TIMx外设TIM_Cmd()

设置中断后就要配置NVIC
⑧ 定义NVIC结构体
⑨ 配置NVIC优先级VIC_PriorityGroupConfig()
⑩ 对结构体中的相关变量进行配置(NVIC_IRQChannel-配置为TIMx的中断;NVIC_IRQChannelPreemptionPriority-配置抢占优先级;VIC_IRQChannelSubPriority-配置从优先级;NVIC_IRQChannelCmd-使能中断通道)
⑪ 根据 NVIC_InitStruct 中指定的参数初始化外设 NVIC 寄存NVIC_Init()

⑫编写服务中断函数TIM3_IRQHandler()

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值