1)实验平台:正点原子stm32f103战舰开发板V4
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html#
第十七章 通用定时器中断实验
本章介绍APM32F407通用定时器的使用,通用定时器相较于基本定时器,拥有输入捕获和输出比较等功能,这些功能可以用来测量脉冲宽度、频率和占空比,并且可以产生并输出波形等。通过本章的学习,读者将学习到通用定时器的基本使用。
本章分为如下几个小节:
17.1 硬件设计
17.2 程序设计
17.3 下载验证
17.1 硬件设计
17.1.1 例程功能
- 程序运行后配置定时器14溢出时间为500毫秒,并开启中断,在中断服务函数中翻转LED1的状态
- 在主循环中每200毫秒执行一次LED0状态翻转操作
17.1.2 硬件资源
- LED
LED0 - PF9
LED1 - PF10
- 定时器14
17.1.3 原理图
本章实验使用的定时器14为APM32F407的片上资源,因此没有对应的连接原理图。
17.2 程序设计
17.2.1 Geehy标准库的TMR驱动
本章实验仅是使用通用定时器14代替上一章中基本定时器6,实现通用定时器的一些基本功能,具体的原理和使用的Geehy标准库函数都是一样的,因此请参考第16.2.1小节中对Geehy标准库中TMR驱动的相关介绍。
17.2.2 通用定时器驱动
本章实验的通用定时器驱动主要负责向应用层提供通用定时器的初始化函数,并实现通用定时器的中断回调函数。本章实验中,通用定时器的驱动代码包括gtmr.c和gtmr.h两个文件。
通用定时器驱动中,对TMR的相关宏定义,如下所示:
#define GTMR_TMRX_INT TMR14
#define GTMR_TMRX_INT_IRQn TMR8_TRG_COM_TMR14_IRQn
#define GTMR_TMRX_INT_IRQHandler TMR8_TRG_COM_TMR14_IRQHandler
#define GTMR_TMRX_INT_CLK_ENABLE() \
do { \
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR14); \
} while (0)
通用定时器驱动中TMR14的初始化函数,如下所示:
/**
* @brief 初始化通用定时器中断
* @note 当APB1PSC!=1时,定时器的时钟频率为APB1时钟的2倍
* 因此定时器的时钟频率为84MHz
* 定时器溢出时间计算方法:Tout = ((arr + 1) * (psc + 1)) / TMRxCLK
* TMRxCLK=定时器时钟频率,单位MHz
* @param arr: 自动重装载值
* @param psc: 预分频器数值
* @retval 无
*/
void gtmr_tmrx_int_init(uint16_t arr, uint16_t psc)
{
TMR_BaseConfig_T tmr_init_struct;
/* 使能时钟 */
GTMR_TMRX_INT_CLK_ENABLE(); /* 使能通用定时器时钟 */
/* 配置通用定时器 */
tmr_init_struct.countMode = TMR_COUNTER_MODE_UP; /* 向上计数 */
tmr_init_struct.clockDivision = TMR_CLOCK_DIV_1; /* 时钟分频系数 */
tmr_init_struct.period = arr; /* 自动重装载值 */
tmr_init_struct.division = psc; /* 预分频器数值 */
TMR_ConfigTimeBase(GTMR_TMRX_INT, &tmr_init_struct); /* 配置通用定时器 */
/* 使能通用定时器及其相关中断 */
NVIC_EnableIRQRequest(GTMR_TMRX_INT_IRQn, 1, 0); /* 开启中断 */
TMR_EnableInterrupt(GTMR_TMRX_INT, TMR_INT_UPDATE); /* 使能更新中断 */
TMR_Enable(GTMR_TMRX_INT); /* 使能通用定时器 */
}
从上面的代码中可以看出,本实验中对通用定时器TMR14的初始化与上一章实验中对基本定时器TMR6的初始化基本类似,不同之处在于通用定时器TMR14可以配置计数模式和时钟分频系数。
通用定时器驱动代码中,TMR14的中断回调函数也与上一章实验中TMR6的中断回调函数类似,如下所示:
/**
* @brief 通用定时器中断服务函数
* @param 无
* @retval 无
*/
void GTMR_TMRX_INT_IRQHandler(void)
{
/* 判断更新中断标志 */
if (TMR_ReadIntFlag(GTMR_TMRX_INT, TMR_INT_UPDATE) == SET)
{
LED1_TOGGLE(); /* 翻转LED1状态 */
TMR_ClearIntFlag(GTMR_TMRX_INT, TMR_INT_UPDATE); /* 清除更新中断标志 */
}
}
从上面的代码中可以看出,在TMR14每次计数溢出后都会翻转一次LED1的状态。
17.2.3 实验应用代码
本章实验的应用代码,如下所示:
int main(void)
{
NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_3); /* 设置中断优先级分组为组3 */
sys_apm32_clock_init(336, 8, 2, 7); /* 配置系统时钟 */
delay_init(168); /* 初始化延时功能 */
usart_init(115200); /* 初始化串口 */
led_init(); /* 初始化LED */
gtmr_tmrx_int_init(5000 - 1, 8400 - 1); /* 初始化通用定时器中断 */
while (1)
{
LED0_TOGGLE();
delay_ms(200);
}
}
与上一章实验一样,TMR14的计数频率为10KHz,溢出频率为2Hz,因此LED1的闪烁频率也为1Hz。
17.3 下载验证
在完成编译和烧录操作后,可以看到板子上的LED0和LED1都在闪烁,但闪烁的频率不同,LED0每间隔200毫秒改变一次状态,LED1在TMR14的中断回调函数中被改变状态,其闪烁的频率约为1Hz。