银杏科技有限公司旗下技术文档发布平台 |
技术支持电话 | 0379-69926675-801 |
技术支持邮件 | Gingko@vip.163.com |
版本 | 日期 | 作者 | 修改内容 |
V1.0 | 2020-07-04 | gingko | 初次建立 |
实验十二:通用定时器实验——定时点亮LED
一、 实验目的与意义
了解STM32 TIMER结构。
了解STM32 TIMER特征。
掌握通用定时器的使用方法。
掌握STM32 HAL库中TIMER属性的配置方法。
掌握KEIL MDK 集成开发环境使用方法。
二、 实验设备及平台
-
-
Micro USB线缆。
Keil MDK 开发平台。
STM32CubeMX开发平台。
装有WIN XP(及更高版本)系统的计算机。
三、 实验原理
1、用定时器简介
STM32F767的通用定时器包含一个16位或32位自动重载计数器(CNT),该计数器由可编程预分频器(PSC)驱动。STM32F767的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等。使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32F767的每个通用定时器都是完全独立的,没有互相共享的任何资源。
STM32的通用TIMx(TIM2~TIM5和TIM9~TIM14)定时器功能包括:
(1)16位/32位(仅TIM2和TIM5)向上、向下、向上/向下自动装载计数(TIMx_CNT),注意:TIM9~TIM14只支持向上(递增)计数方式。
(2)16位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为1~65535之间的任意数值。
(3)4个独立通道(TIMx_CH1~4,TIM9~TIM14最多2个通道),这些通道可以用来作为:
(4)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用1个定时器控制另外一个定时器)的同步电路。
(5)如下事件发生时产生中断/DMA(TIM9~TIM14不支持DMA):
A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
C.输入捕获
D.输出比较
E.支持针对定位的增量(正交)编码器和霍尔传感器电路(TIM9~TIM14不支持)
F.触发输入作为外部时钟或者按周期的电流管理(TIM9~TIM14不支持)
2、时基单元
可编程定时器的主要模块由一个16位/32位计数器及其相关的自动重装寄存器组成。计数器可递增计数、递减计数或同时递增和递减计数。计数器的时钟可通过预分频器进行分频。计数器、自动重载寄存器和预分频器寄存器可通过软件进行读写。即使在计数器运行时也可执行读写操作。
时基单元包括:
计数器寄存器(TIMx_CNT)
预分频器寄存器(TIMx_PSC)
自动重载寄存器(TIMx_ARR)
自动重载寄存器是预装载的。对自动重载寄存器执行写入或读取操作时会访问预装载寄存器。预装载寄存器的内容既可以直接传送到影子寄存器,也可以在每次发生更新事件(UEV)时传送到影子寄存器,这取决于TIMx_CR1寄存器中的自动重载预装载使能位(ARPE)。当计数器达到上溢值(或者在递减计数时达到下溢值)并且TIMx_CR1寄存器中的UDIS位为0时,将发送更新事件。该更新事件也可由软件产生。计数器由预分频器输出CK_CNT提供时钟,仅当TIMx_CR1寄存器中的计数器启动位(CEN)置1时,才会启动计数器。注意,实际的计数器使能信号CNT_EN在CEN置1的一个时钟周期后被置1。
3、相关寄存器
这里,定时器的时钟来源有4个:
这些时钟,具体选择哪个可以通过TIMx_SMCR寄存器的相关位来设置。这里的CK_INT时钟是从APB1倍频的来的,除非APB1的时钟分频数设置为1(一般都不会是1),否则通用定时器TIMx的时钟是APB1时钟的2倍,当APB1的时钟不分频的时候,通用定时器TIMx的时钟就等于APB1的时钟。这里还要注意的就是高级定时器以及TIM9~TIM11的时钟不是来自APB1,而是来自APB2的。
(4)自动重装载寄存器(TIMx_ARR),该寄存器在物理上实际对应着2个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《STM32F7中文参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据TIMx_CR1寄存器中APRE位的设置:APRE=0时,预装载寄存器的内容可以随时传送到影子寄存器,此时2者是连通的;而APRE=1时,在每一次更新事件(UEV)时,才把预装载寄存器(ARR)的内容传送到影子寄存器。自动重装载寄存器的各位描述如图所示:
四、 实验程序
1、主函数
int main(void)
{
system_clock.initialize();//初始化系统时钟
led.initialize(); //LED初始化
timer3.initialize(); //timer3初始化
while(1);
}
2、定时器初始化
static int initialize(void)
{
//定时1s
htim3.Instance = TIM3;
htim3.Init.Prescaler = 21599; //预分频系数
htim3.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数模式
htim3.Init.Period = 4999; //自动装载值
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //时钟分频因子
htim3.Init.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE;//自动装载使能
if (HAL_TIM_Base_Init(&htim3) != HAL_OK) //初始化定时器参数
{
while(1);
}
//使能定时器更新中断和使能定时器
HAL_TIM_Base_Start_IT(&htim3);
return 0;
}
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
{
/* 检查参数 */
assert_param(IS_TIM_INSTANCE(htim->Instance));
/* 使能定时器更新中断 */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
/* 使能外围设备 */
__HAL_TIM_ENABLE(htim);
/* 返回函数状态*/
return HAL_OK;
}
3、TIM3中断优先级设置
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM3)
{
/* TIM3时钟使能 */
__HAL_RCC_TIM3_CLK_ENABLE();
/* 初始化中断 */
HAL_NVIC_SetPriority(TIM3_IRQn, 1, 3);//设置中断优先级
HAL_NVIC_EnableIRQ(TIM3_IRQn);//开启中断
}
}
4、中断服务函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static int counter = 0;
if(counter % 3 == 0){
LED_RED_ON;
LED_BLUE_OFF;
LED_GREEN_OFF;
}else if(counter % 3 == 1){
LED_RED_OFF;
LED_BLUE_ON;
LED_GREEN_OFF;
}else if(counter % 3 == 2){
LED_RED_OFF;
LED_BLUE_OFF;
LED_GREEN_ON;
}
counter ++;
}
五、 实验步骤
把仿真器与iCore4的SWD调试口相连(直接相连或者通过转接器相连);
把iCore4通过Micro USB线与计算机相连,为iCore4供电;
打开Keil MDK 开发环境,并打开本实验工程;
烧写程序到iCore4上;
也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。
六、 实验现象