写在前面:
本文章为《ARM Cortex-M4裸机开发篇》系列中的一篇,,全系列总计14篇。笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板),Cortex-M4裸机开发篇除了讲M4裸机开发外,还会讲解通过M4控制资源扩展板上的各种传感器执行器模块(包括空气温湿度传感器、LED灯、数码管、蜂鸣器、震动马达、按键中断、风扇等),本篇是M4控制资源扩展板中的一篇。
资源扩展板是FS-MP1A开发板的扩展模块,主要包含了10余种助主流传感器、执行器件、总线控制器件,非常方便项目扩展用。可拓展开发智慧家庭、智能医疗、智能安防、工业控制、图像识别、环境检测等方向的10个左右综合项目,华清远见开发板也将配套提供所有项目的说明文档、实验源码、应用程序等资料。
针对FS-MP1A开发板,除了Cortex-M4裸机开发篇外,还包括其他多系列教程,包括Cortex-A7开发篇、FreeRTOS篇、Linux基础及应用开发篇、Linux系统移植篇、Linux驱动开发篇、硬件设计篇、人工智能机器视觉篇、Qt应用编程篇、Qt综合项目实战篇等。d=622457259672
1.资源扩展板介绍
1.1硬件介绍&资源扩展板可开发项目
2.Cortex-M4 TIM定时器中断
2.1实验目的
熟悉STM32CubeIDE工具软件的使用。
掌握STM32CubeIDE软件的基本设计流程和设计步骤,能够使用工具进行设计、编程、仿真调试。
学习通用定时器的使用方法,掌握如何利用STM32MP157A芯片的通用定时器定时产生中断。
2.2实验环境
FS-MP1A开发平台
ST-Link仿真器
STM32CubeIDE开发软件
PC机 XP、Window7/10 (32/64bit)
2.3实验原理
STM32系列微控制器具有多种定时器,其中包括基本定时器,通用定时器,高级定时器。
几种定时器功能比较:
基本定时器:主要运用于定时器计数及驱动DAC
通用定时器:定时器定时计数、输入捕获、输出比较、PWM输出、使用外部信号控制定时器和定时器互连的同步电路
高级定时器:通用定时器的所有功能、带死区控制和紧急刹车,可用于PWM控制电机
本章节实验以通用定时器TIM3为例实现定时计数,计数到设置值后触发中断改变LED灯亮灭状态。
从下图可以看出定时器时钟TIM3挂载在APB1时钟总线上,在STM32CubeIDE软件中可配置总线时钟频率来确定定时器时钟。
基本定时器功能框图
从上图我们可以看到,基本定时器主要由下面几部分组成
时钟源
定时器要实现计数必须有个时钟源,基本定时器时钟只能来自内部时钟,高级控制定时器和通用定时器还可以选择外部时钟源或者直接来自其他定时器等模式。
控制器
定时器控制器控制实现定时器功能,控制定时器复位、使能、计数是其基础功能,基本定时器还专门用于 DAC转换触发。
计数器
基本定时器计数过程主要涉及到三个寄存器内容,分别是计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器(TIMx_ARR),这三个寄存器都是 16 位有效数字,即可设置值为 0至 65535。上图中预分频器 PSC,它有一个输入时钟 CK_PSC和一个输出时钟CK_CNT。输入时钟 CK_PSC 来源于控制器部分,基本定时器只有内部时钟源所以CK_PSC实际等于 CK_INT。在不同应用场所,经常需要不同的定时频率,通过设置预分频器 PSC的值可以非常方便得到不同的 CK_CNT,实际计算为:fCK_CNT等于 fCK_PSC/(PSC[15:0]+1)。下图中可看到将预分频器 PSC的值从 1改为 4时计数器时钟变化过程。原来是 1分频,CK_PSC和 CK_CNT频率相同。向 TIMx_PSC 寄存器写入新值时,并不会马上更新CK_CNT输出频率,而是等到更新事件发生时,把 TIMx_PSC 寄存器值更新到影子寄存器中,使其真正产生效果。更新为 4分频后,在 CK_PSC 连续出现 4个脉冲后 CK_CNT 才产生一个脉冲。
基本定时器时钟源分频
在定时器使能(CEN 置 1)时,计数器 COUNTER根据 CK_CNT频率向上计数,即每来一个 CK_CNT脉冲,TIMx_CNT 值就加 1。当 TIMx_CNT值与 TIMx_ARR的设定值相等时就自动生成事件并 TIMx_CNT 自动清零,然后自动重新开始计数,如此重复以上过程。为此可见,我们只要设置 CK_PSC和 TIMx_ARR 这两个寄存器的值就可以控制事件生成的时间,而我们一般的应用程序就是在事件生成的回调函数中运行的。在 TIMx_CNT 递增至与 TIMx_ARR值相等,我们叫做为定时器上溢。自动重载寄存器 TIMx_ARR用来存放于计数器值比较的数值,如果两个数值相等就生成事件,将相关事件标志位置位,生成 DMA和中断输出。TIMx_ARR 有影子寄存器,可以通过 TIMx_CR1 寄存器的 ARPE位控制影子寄存器功能,如果 ARPE 位置 1,影子寄存器有效,只有在事件更新时才把 TIMx_ARR值赋给影子寄存器。如果 ARPE位为 0,修改TIMx_ARR 值马上有效。
定时器周期计算
经过上面分析,我们知道定时事件生成时间主要由 TIMx_PSC 和 TIMx_ARR两个寄存器值决定,这个也就是定时器的周期。比如我们需要一个 1s周期的定时器,具体这两个寄存器值该如何设置内。假设,我们先设置 TIMx_ARR寄存器值为 9999,即当 TIMx_CNT从 0开始计算,刚好等于 9999时生成事件,总共计数 10000次,那么如果此时时钟源周期为 100us即可得到刚好 1s的定时周期。接下来问题就是设置 TIMx_PSC寄存器值使得 CK_CNT 输出为 100us 周期(10000Hz)的时钟。预分频器的输入时钟 CK_PSC为 64MHz,所以设置预分频器值为(6400-1)即可满足
中断时间:1/(TIMxCLK/(PSC+1))* (ARR+1)
2.4实验步骤
打开STM32CubeIDE->File->New->STM32 Project
可以在左侧搜索框内输入芯片型号STM32MP157A进行搜索,选择对应芯片,点击Next
填写工程名,点击Finsh
点击Yes打开配置页面
配置TIM3,勾选Cortex-M4,Clock Source选择Internal Clock
Configuration下依据时钟频率配置预分频和计数值,NVIC使能
搜索框内搜索LED对应GPIO引脚PZ5、PZ6、PZ7,左键点击设置为GPIO_Output
这里我们需要注意一下,和其他单片机不同,还需要继续设置“ Pin Reservation”给“ Cortex-M4”,否则STM32CubeMX不会生生成GPIO初始化相关代码。具体操作:在刚才选择的引脚上,鼠标右键选择“ Pin Reservation”->“ Cortex-M4”。
在Code Generator处选择为每个外设生成单独的C和H文件,这样设置方便阅读代码
完成以上设置后,Ctrl+S保存,会提示是否需要生成代码,选择Yes即可自动生成代码。系统会自动生成System Clock代码
可以在左侧工程文件夹找到TIM_CM4子工程,打开main.c
添加定时器中断回调函数
1234567 | void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim->Instance == TIM3) //TIM3周期1s { HAL_GPIO_TogglePin(GPIOZ, GPIO_PIN_5); }} |
main函数调用定时器中断使能函数
上述为新建工程配置过程,可参考12.3.2章节进行导入已有工程,工程存放路径【华清远见-FS-MP1A开发资料 2-程序源码ARM体系结构与接口技术Cortex-M45_TIM】
配置完成或导入工程后进行程序下载,具体步骤参考12.3.3节进行开发板连接,程序编译、下载
2.5实验现象
可看到LED灯间隔1S改变一次亮灭状态