前列腺不能吃什么食物| 蝶窦囊肿是什么病| 什么叫肠化| 出家人是什么意思| 11月2日是什么星座| 颈动脉彩超挂什么科| 惊厥是什么病| 庞统为什么要献连环计| 西米是什么做成的| 什么的贾宝玉| 大脑供血不足是什么原因引起的| 小腿抽筋是什么原因引起的| 肋软骨炎挂什么科| 田野里有什么| 吃什么降血压的食物| 草木皆兵是什么意思| 早晨嘴苦是什么原因引起的| 额头高代表什么| 治胃病吃什么药| 西洋菜是什么菜| 表白送什么礼物好| 为什么不建议吃三代头孢| 肾积水是什么原因造成的怎么治疗| 总胆固醇是什么意思| 八月一日是什么日子| 离婚需要什么手续和证件| 什么是乳胶床垫| 为什么肝区隐隐作痛| 脊椎挂什么科| 无缘无故吐血是什么原因| eus是什么检查| 颈肩综合症有什么症状| 胃寒喝什么茶暖胃养胃| 大陆对什么| 乳糖不耐受是什么症状| 腱鞘炎看什么科| 为什么会有台风| 照身份证穿什么颜色的衣服| 提前吃什么喝酒不醉| 孕妇羊水多是什么原因造成的| 寒食节是什么时候| 熟视无睹什么意思| 向心性肥胖是什么意思| 1.8号是什么星座| 小孩吃了就吐是什么原因| 什么的假山| 眼睛干痒用什么眼药水比较好| 一学年是什么意思| 花生碎能做什么食物吃| 健脾养胃喝什么好| sat是什么考试| 晚上吃什么水果对身体好| 花生什么时候收| 迷茫是什么意思| 腺瘤是什么意思| 什么是肾虚| 挑什么| 茯苓有什么功效| 卧底大结局是什么| 耳朵发炎吃什么药| 腹泻吃什么药| 我宣你 是什么意思| 阴虚血热什么症状| 尿酸高吃什么肉| 寻麻疹吃什么药| 吃生洋葱有什么好处| 吴亦凡为什么退出exo| 吃什么治肝病| tag什么意思| 中二病的意思是什么| dic医学上是什么意思| 铁锈用什么能洗掉| 肉苁蓉是什么| 八十岁是什么之年| 男人阴囊潮湿吃什么药| 吃榴莲有什么坏处| 面瘫是什么引起的| 男性吃什么生精快| 烈女怕缠郎是什么意思| 吃什么食物对肝好| 提拉米苏是什么| 9月10号是什么星座| 波奇饭是什么意思| 什么叫等离子| 茱萸是什么意思| 肝不好吃什么药效果好| 信佛有什么好处| 味素是什么| 牙疼吃什么药最好最有效| 什么季节喝白茶| 一年级又什么又什么| 老鼠是什么意思| c2驾照可以开什么车| 抑郁看病看什么科| 孛儿只斤现在姓什么| 腿部肿胀是什么原因引起的| 一什么鹿角| 抽动症是什么原因引起的| 长口腔溃疡是什么原因| 床咚是什么意思啊| 诸什么意思| 蜜糖有什么功效和作用| 上海松江有什么好玩的地方| 佩戴沉香有什么好处| 梦见蘑菇是什么预兆| 唾液酸苷酶阳性什么意思| jps是什么意思| 胃不舒服想吐吃什么药| 一心向阳下一句是什么| 浅笑安然是什么意思| 1972年五行属什么| 89年的蛇是什么命| 为什么吃了饭就想睡觉| betty是什么意思| 颠三倒四是什么意思| 风象星座是什么意思| 鹿沼土是什么土| 什么是反物质| hrd阳性是什么意思| 小儿惊风是什么症状| 喝什么水解酒| 形声字是什么意思| 闯空门什么意思| 梦见牛肉有什么征兆| 尿检白细胞阳性是什么意思| 香薰是什么| 海肠是什么| 左束支传导阻滞是什么意思| 气血虚什么症状| 类似蜈蚣的虫子叫什么| 7月31日是什么星座| 胃大肚子大是什么原因| 梦见鞭炮是什么意思| 什么地摇动| 海水为什么是蓝色的| 神经紊乱有什么症状| 摸金是什么意思| 捻子泡酒有什么功效| 爽肤水是什么| 部分空蝶鞍是什么意思| 铁皮石斛有什么功效| 翻白眼是什么意思| 美甲做多了有什么危害| siri是什么意思| hcg低是什么原因| 什么姿势| alp是什么意思| sheep是什么意思| 淡泊名利是什么意思| 什么的图案| 甲亢什么东西不能吃| 肾轻度积水是什么意思| hc是胎儿的什么| 梦见父亲去世预示什么| 舌头发黄是什么原因| 乱的偏旁是什么| 月经是什么| 什么的遗产| 五行什么生火| 吃花生米是什么意思| 大姨妈来了能吃什么水果| 止汗药什么最好| 胸腔积液吃什么药最有效| 脚底痛挂什么科| 咳嗽什么东西不能吃| 大眼角痒用什么眼药水| 干预是什么意思| 什么的琴声| 梦见枕头是什么意思| 请佛像回家有什么讲究| 刮宫是什么| 月经期喝红糖水有什么好处| 巨蟹跟什么星座最配| 腐败什么意思| 小孩咳嗽喝什么药| 溶血症是什么意思| 丧尸是什么意思| 什么孕妇容易怀脑瘫儿| 九地是什么中药| 转氨酶高是什么原因造成的| 牙齿痒是什么原因| 独宠是什么意思| 多此一举是什么生肖| 花匠是什么意思| 慧眼识珠是什么意思| 汗毛旺盛是什么原因| 脚心热吃什么药| 看痘痘挂什么科| 白芷有什么作用| 聿字五行属什么| 界限性脑电图是什么意思| 十一月二十二是什么星座| 微不足道的意思是什么| 咽喉炎吃什么药好| 康桑密达是什么意思| 柠檬是什么季节的水果| 新生儿什么时候上户口| 梦见抢银行是什么意思| 穿山甲说了什么| 佰草集属于什么档次| 犹太人为什么那么聪明| 眼袋是什么| 更年期失眠吃什么药调理效果好| cns医学上是什么意思| 光阴是什么意思| 更年期什么时候开始| 肝病吃什么好得快| 12月份是什么星座| 什么是邪淫| 三七主要治什么病| 什么东西能去脸上的斑| 翻白草治什么病| 普拉提是什么| 日间病房是什么意思| 常字五行属什么| 口是什么感觉| 被舔下面什么感觉| 晟怎么读音是什么| 鸡是什么动物| 情难自禁是什么意思| c6是什么| pr过高是什么意思| 女生下面是什么味道| 为什么同房会有刺痛感| 合菜是什么| 38属什么| 眼镜发黄是什么原因| 陈皮是什么| 1973年属牛是什么命| 头发油的快是什么原因| 一什么城市| 血压高会有什么症状| 乌龙茶是什么茶| 过年给老人买什么| 岗位等级是什么意思| 肺肿了是什么病严重吗| 龛影是什么意思| 什么是取保候审| abs材质是什么| 子宫内膜6mm意味着什么| 下面外面瘙痒用什么药| 鹿米念什么| a型血为什么叫贵族血| 国企属于什么编制| 血钾低会有什么症状| 孩子积食发烧吃什么药| 牙龈出血挂什么科| 槟榔长什么样| 眼睛长眼屎是什么原因| 吃什么补肺养肺比较好| spi是什么| 苍苍什么| 榴莲为什么是苦的| 为什么学习不好| 阶段性是什么意思| 什么是新陈代谢| 梅菜是什么菜晒干的| 棕色眼睛的人什么血统| 干什么呢| 冠心病吃什么水果| 总胆红素是什么| 为什么呀| 心电图异常q波是什么意思| nb是什么意思| 百度

い瓣Q簈莱淋畊瞴穝竒蕾畃穦阶韭穝籇祇ガ穦

百度 基础研究像一个强大的引擎,带动与之相关的科学研究和技术的巨大发展2005年,田刚从美国回国组建了北京国际数学研究中心,13年来,中心见证了国内数学科研水平的飞速发展。

STM32 CubeMX学习:3. 定时器闪烁LED

系列文章目录
  1. 前期的准备
  2. 点亮 LED
  3. 闪烁 LED
  4. 定时器闪烁LED
  5. PWM控制LED亮度
  6. 常见的PWM设备
  7. 按键的外部中断
  8. ADC模数转换
  9. 串口收发
  10. 串口打印遥控器数据
  11. 未完待续…


0.前言

这次的博文,我们要了解定时器的基本功能及其配置方法,还接触STM32中最重要的概念之一——中断,介绍在cubeMX中如何对中断进行设置,如何开启中断以及配置中断的优先级等,最后将实现由定时器触发的定时器中断,控制LED灯的闪烁。

1.基础学习

1.1 定时器功能讲解

对于定时器,这里我换种说法吧。我们可以把定时器比作闹铃,定时器的基本功能就是定时,在设定好对应的时间后,会在设定的时刻响起铃声。例如上次博文的滴答定时器,设定为1ms的定时时间,便每隔1ms引起中断函数。
在使用定时器时,我们会涉及到三个非常重要的概念——分频,计数,重载。这三个概念可以结合生活中使用的时钟来理解。

  • 分频
    时钟上不同的指针需要有不同的速度,也就是不同的频率,从而精确的表示时间,比如秒针,分针,时针,这三者相邻的频率之比都是60:1,即秒针每转过60格分针转动1格,分针转动60格时针转动1格,所以分针对于秒针的分频为60。
  • 计数
    时钟所对应的值都是与工作时间成正比的,比如秒针转动10格,意味着过了10秒,同样定时器中的计数也是和计数时间成正比的值,频率越高增长速度越快。
  • 重载
    时、分、秒的刻度都是有上限的,一个表盘最多记12小时,60分钟,60秒,如果继续增加的话就会回到0。同样的在定时器中也需要重载,当定时器中的计数值达到重载值时,计数值就会被清零。

现在,我们介绍三个与定时器有关的三个重要的寄存器

  • 预分频寄存器TIMx_PSC
  • 计数器寄存器TIMx_CNT
  • 自动重装载寄存器TIMx_ARR

时钟源处的时钟信号经过预分频寄存器,按照预分频寄存器内部的值进行分频。比如时钟源的频率为12MHz,而预分频寄存器中设置的值为12:1,那么通过预分频后进入定时器的时钟频率就下降到了1MHz。

在已经分频后的定时器时钟驱使下,TIMx_CNT根据该时钟的频率向上计数,直到TIMx_CNT的值增长到与设定的自动重装载寄存器TIMx_ARR相等时,TIMx_CNT被清空,并重新从0开始向上计数,TIMx_CNT增长到TIMx_ARR中的值后被清空时产生一个定时中断触发信号。

综上定时器触发中断的时间是由设定的TIMx_PSC中的分频比和TIMx_ARR中的自动重装载值共同决定的。

定时器是STM32中非常重要的外设。在大多数应用场景中,部分任务需要周期性的执行,比如上一讲中提到的LED闪烁,这个功能就可以依靠定时器来实现,此外STM32的定时器还能够提供PWM输出,输入捕获,输出比较等多种功能。

1.2 中断的讲解

由单片机控制的机器人往往需要处理多种信号的输入,比如各种传感器信号等等,此外还需要进行多种信号的输出,比如控制电机的CAN信号,控制舵机的PWM等等,那么STM32是如何有序安排这些任务的呢?就是依赖于中断构成的前后台机制。

在STM32中,对信号的处理可以分为轮询方式和中断方式,轮询方式就是不断去访问一个信号的端口,看看有没有信号进入,有则进行处理,中断方式则是当输入产生的时候,产生一个触发信号告诉STM32有输入信号进入,需要进行处理。

例如,厨房里烧着开水,主人在客厅里看电视。为了防止开水烧干,他有两种方式,第一种是每隔10分钟就去厨房看一眼,另一种是等水壶烧开了之后开始发出响声再去处理。前者是轮询的方式,后者是中断的方式。

每一种中断都有对应的中断函数,当中断发生时,程序会自动跳转到处理函数处运行,而不需要人为进行调用。

当定时器的计数值增长到重载值时,在清空计数值的同时,会触发一次定时器中断,即定时器更新中断。只要设定好定时器的重载值,就可以保证定时器中断以固定的频率被触发。

2 程序的学习

2.1 定时器在CubeMX里的配置

首先我们按照之前的配置配置一个LED工程,忘记的小伙伴可以去看我之前的博客,相信大家一定没问题。

下面,我们进行如下的设置

  1. 在左侧的标签页中选择Timer,点击标签页下的TIM1。
    TIM1

  2. 在弹出的TIM1 Mode and Configuration中,在ClockSouce的右侧下拉菜单中选中Internal Clock。
    时钟源

  3. 此时TIM1得到使能,接下来需要配置TIM1的运转周期。需要在Clock Configuration标签页进行时钟树的配置,具体操作见我的第0篇博客。(前期的准备 ),这里我默认大家已经完成了相关的配置。
    下面通过设置分频比和重载值来控制定时器的周期。
    如果想要得到周期为500毫秒的定时器,我们需要回到Pinout&Configuration标签页下,对应TIMx_PSC寄存器的Prescaler项和对应TIMx_ARR寄存器的Counter Period项。500ms对应的频率为2Hz,为了得到2Hz的频率,可以将分频值设为16799,重载值设为4999。具体的原理我会在这篇博客后面的进阶学习中进行讲解。
    按如图方式配置
    定时器配置

2.2 中断优先级讲解

回顾刚才所说的中断概念,在STM32专门用于处理中断的控制器叫做NVIC,即嵌套向量中断控制器 (Nested Vectored Interrupt Controller)。
NVIC的功能非常强大,支持中断优先级和中断嵌套的功能,中断优先级即给不同的中断划分不同的响应等级,如果多个中断同时产生,则STM32优先处理高优先级的中断。
中断嵌套即允许在处理中断时,如果有更高优先级的中断产生,则挂起当前中断,先去处理产生的高优先级中断,处理完后再恢复到原来的中断继续处理。
这个过程理解起来就像是在上文的情境中,主人听到水烧开了,正打算去厨房时突然听到门口响起了急促的敲门声,那么主人就会先去执行开门的操作,然后再去厨房处理开水。
为了在有限的寄存器位数中实现更加丰富的中断优先级,NVIC使用了中断分组机制。STM32将先将中断进行分组,然后又将优先级划分为抢占优先级 (Prem priority) 和响应优先级 (Subpriority),抢占优先级和响应优先级的数量均可以通过NVIC中AIRCR寄存器的PRIGROUP[8:10]位进行配置,从而规定了两种优先级对NVIC_IPRx[7:4]的划分,根据划分决定两种优先级的数量。总共可以分成下表中的5种情况

抢占优先级级数响应优先级级数
0000
0010-1
0100-3
0110-7
1000-15

拥有相同抢占优先级的中断处于同一个中断分组下。
当多个中断发生时,先根据抢占优先级判断哪个中断分组能够优先响应,再到这个中断分组中根据各个中断的响应优先级判断哪个中断优先响应。

2.3 CubeMX中的中断配置以及中断函数管理

2.3.1 CubeMX的中断配置

我们可以在CubeMX的NVIC标签页下可以看到当前系统中的中断配置,如下图所示:
NVIC
列表中显示了当前系统中所有中断的使能情况与优先级设置。要使能中断则在Enable一栏打勾,这里选中TIM1 update interrupt,打勾,开启该中断。此外还可以在该页面下进行抢占优先级和响应优先级的分配和中断的两种优先级的配置。这里为定时器1的中断保持默认的0,0优先级。

点击Generate code,生成代码。

下面来看一下HAL库是如何对中断进行处理的。
在stm32f4xx_it.c中,找到cubeMX自动生成的中断处理函数

/**
  * @brief This function handles TIM1 update interrupt and TIM10 global interrupt.
  */
void TIM1_UP_TIM10_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 0 */

  /* USER CODE END TIM1_UP_TIM10_IRQn 0 */
  HAL_TIM_IRQHandler(&htim1);
  /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 1 */

  /* USER CODE END TIM1_UP_TIM10_IRQn 1 */
}

该函数调用了HAL库提供的HAL_TIM_IRQHandler这一函数

void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)

该函数返回值为void,其作用在于HAL对涉及中断的寄存器进行处理,有一个参数,*htim 定时器的句柄指针,如定时器1就输入&htim1,定时器2就输入&htim2 。

在HAL_TIM_IRQHandler对各个涉及中断的寄存器进行了处理之后,会自动调用中断回调函数HAL_TIM_PeriodElapsedCallback,该函数使用__weak修饰符修饰,即用户可以在别处重新声明该函数,调用时将优先进入用户声明的函数。

__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

一般我们需要在中断回调函数中判断中断来源并执行相应的用户操作。

2.3.2 定时器回调函数介绍

如前文所介绍的,HAL库在完成定时器的中断服务函数后会自动调用定时器回调函数。
通过配置TIM1的分频值和重载值,使得TIM1的中断以500ms的周期被触发。因此中断回调函数也是以500ms为周期被调用。在main.c中重新声明定时器回调函数,并编写内容如下:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 
{ 
	if(htim == &htim1) 
	{ 
		//500ms trigger 
		bsp_led_toggle(); 
	} 
}

注意,这个函数需要我们自己在main.c文件中定义声明。

可以看到首先在回调函数中进行了中断来源的判断,判断其来源是否是定时器1。如果有其他的定时器产生中断,同样会调用该定时器回调函数,因此需要进行来源的判断。

在确认了中断源为定时器1后,调用bsp_led_toggle函数,翻转LED引脚的输出电平。

2.3.3 HAL_TIM_Base_Start函数

如果不开启中断,仅让定时器以定时功能工作,为了使定时器开始工作,需要调用HAL库提供的函数。

HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)

该函数的返回值为HAL_StatusTypeDef,HAL库定义的几种状态,如果成功使定时器开始工作,则返回HAL_OK。其作用在于使对应的定时器开始工作。该函数有一个参数,*htim 定时器的句柄指针,如定时器1就输入&htim1,定时器2就输入&htim2。
如果需要使用定时中断,则需要调用函数

HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)

该函数的返回值为HAL_StatusTypeDef,HAL库定义的几种状态,如果成功使定时器开始工作,则返回HAL_OK。其作用在于使对应的定时器开始工作,并使能其定时中断。该函数有一个参数,*htim 定时器的句柄指针,如定时器1就输入&htim1,定时器2就输入&htim2

以上两个函数如果要使用则都需要在主循环while(1)之前调用。

3. 效果展示

定时器会以500ms定时触发中断,使得开发板C型上的LED灯会以500ms跳变一次,呈现闪烁的效果。使用定时器触发中断,时间精度决定于晶振的精度,比软件模拟延时精度大大提升。

4. 进阶学习

4.1 APB总线计算定时器定时时间

前面我们提到可以通过设置分频比和自动重装载值来控制定时器的定时周期,在这里结合芯片手册(Datasheet)来详细介绍一下定时周期的计算过程。芯片手册可以在Keil的book标签页下获取。

在手册中我们可以看到APB1和APB2总线上挂载在了大量的外设。定时器1,8,9,10,11挂载在APB2总线上。根据datasheet中给出的定时器所挂载的总线就可以确定定时器在分频前的时钟源频率。
总线挂载
在cubeMX的clock configuration标签页下,可以看到时钟树的结构。在整个时钟树的最右端,可以看到APB1和APB2两个总线的时钟频率设置,其中APBx peripheral clocks为挂载在总线上的定时器以外的外设提供时钟源,APBx timer clocks为挂载在总线上的定时器提供时钟源。

确定时钟源频率之后,根据数据手册的内容,分频值为TIMx_PSC中的分频值+1。即TIMx_SPC为0时,分频比刚好为1:1,如果TIMx_SPC为15,则分频比为16:1,进入的16MHz的频率信号会被分频为1MHz。
分频
分频后的频率就是TIMx_CNT自增的频率,根据之前介绍的内容,当TIMx_CNT的值增长到TIMx_ARR中的值后,就会发生重载,并触发中断信号,相当于使用TIMx_ARR中的值又进行了一次分频。因此产生这个中断信号的频率应该为(需要加1是因为CNT是从0开始计数的)。
公式1
结合上面两个式子,可以得到最终的用于计算定时器触发频率的公式
公式2
其中f_CKPSK的值通过之前所说的方法,找到对应的APB总线进行确认。

完整的main.c代码如下所示

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

void bsp_led_toggle(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
  * @brief          Toggle the red led, green led and blue led 
  * @param[in]      none
  * @retval         none
  */
/**
  * @brief          反转红灯,绿灯和蓝灯电平
  * @param[in]      none
  * @retval         none
  */
void bsp_led_toggle(void)
{
    HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);
    HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);
    
}

/**
  * @brief          Period elapsed callback in non-blocking mode
  * @param[in]      htim TIM handle
  * @retval         none
  */
/**
  * @brief          定时器周期定时回调
  * @param[in]      htim:定时器指针
  * @retval         none
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim == &htim1)
    {
      //500ms trigger
      bsp_led_toggle();
    }
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
	
	// HAL_TIM_Base_Start(&htim1);
    HAL_TIM_Base_Start_IT(&htim1);
		
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 6;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

代码我已经放到了我的GitHub仓库,如有需要可以下载使用:
CubeMX学习


总结

这篇博客主要讲解了STM32的定时器外设,学习了如何通过配置几个重要的参数使定时器按照期望的周期运行,利用定时器可以实现嵌入式系统中重要的后台机制,即按照稳定的周期执行定时任务。 此外我们还学习了中断这一重要的概念,通过开启多样的中断,并合理制定其优先级,才能够在机器人上实时地运行丰富的任务。 阿巴阿巴,这次的博客的确有点长,大家可能已经晕菜 不过大家不要担心,现在继续开始敲黑板啦

其实我们主要掌握的内容是

  1. 定时器基本功能
  2. 定时器的配置
  3. 定时器中断以及中断优先级讲解
  4. CubeMX中的中断管理

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
梦到鞋子是什么意思 七夕送什么礼物好 堤防是什么意思 维生素d滴剂什么时候吃最好 没胃口吃什么
印度阿三是什么意思 esim卡是什么 是代表什么意思 撇清关系是什么意思 焦虑症是什么症状
kamagra是什么药 累的什么 精神分裂是什么 hpv16阳性是什么意思 兜兜转转是什么意思
蟑螂长什么样子 涤棉是什么材质 小孩说话晚是什么原因 心肌缺血做什么检查能查出来 属猴的守护神是什么菩萨
树脂材料是什么hcv9jop6ns9r.cn 常吃火龙果有什么好处hcv7jop7ns1r.cn 尿蛋白高吃什么药hcv8jop9ns9r.cn fion属于什么档次的包xinmaowt.com 幺蛾子是什么意思yanzhenzixun.com
心无什么用hcv9jop8ns2r.cn 坪效是什么意思hcv8jop1ns9r.cn 捭阖是什么意思hcv8jop3ns7r.cn 什么奶粉跟母乳一个味hcv8jop2ns5r.cn 氟苯尼考兽药治什么病520myf.com
普贤菩萨的坐骑是什么bjhyzcsm.com 人是什么结构hcv8jop9ns9r.cn 不什么其什么的成语hcv8jop2ns6r.cn 报复是什么意思hcv8jop2ns2r.cn 烫伤了抹什么hcv7jop6ns0r.cn
六月二十六是什么日子hcv8jop4ns4r.cn 穿丝袜有什么好处hcv8jop2ns7r.cn 纳米是什么单位hcv9jop0ns7r.cn 什么水果不能放冰箱hcv9jop7ns1r.cn 检查乙肝五项挂什么科hcv9jop0ns2r.cn
百度