本帖最后由 zexin 于 2024-8-9 16:56 编辑
#申请原创# AT32F403A基本定时器 目录
一、简介
二、功能
1.计数时钟
2.基本结构
3.计数模式
三、案例
1.描述
2.步骤
3.代码
4.现象
一、简介
基本定时器(TMR6和TMR7)包含一个16位向上计数器,由内部时钟作为计数时钟,支持溢出事件中断和DMA请求。
定时器框图 二、功能
1.计数时钟
TMR6和TMR7由内部时钟源(CK_INT)经预分频器提供计数器计数。
使用内部时钟 2.基本结构
基本结构图 - TMRx_PR(周期寄存器):用于设置计数器计数周期;
- TMRx_DIV(预分频寄存器):用于设置计数器计数频率;
- TMRx_CNT(计数值寄存器):用于读/写计数器的计数值;
- PR_shadow(周期影子寄存器):默认TMRx_PR的值会立即传入它的影子寄存器;
- DIV_shadow(预分频影子寄存器):默认TMRx_DIV的值会立即传入它的影子寄存器;
- PRBEN(周期缓冲使能):选择是否打开周期缓冲功能;
注:
①若PRBEN=0,即关闭周期缓冲功能,则TMRx_PR的值会立即传入它的影子寄存器(PR_shadow);
关闭周期缓冲功能时的溢出事件 如上图,关闭周期缓冲功能时,改写PR(计数周期由0x22改为0x32)后,COUNTER立即使用新的计数值(0x32)。
②若PRBEN=1,即打开周期缓冲功能,则TMRx_PR的值会在溢出事件发生时传入它的影子寄存器(PR_shadow);
打开周期缓冲功能时的溢出事件 如上图,打开周期缓冲功能时,改写PR(计数周期由0x22改为0x32)后,COUNTER仍是使用旧的计数值(0x22),等OVFIF(溢出中断标志)产生信号之后,才使用新的计数值(0x32)。
3.计数模式
计数器时序图 基本定时器仅提供向上计数模式,即当计数值达到TMR_PR时,计数器向上溢出并产生溢出事件,同时OVFIF(溢出中断标志)置1,之后重新从0开始计数。
三、案例
1.描述
TMR6向上计数,每过1秒溢出一次同时让LED电平翻转1次。
2.步骤
①打开WorkBench,选择对应的型号,以AT32F403A为例新建工程;
②通过分频系数和周期值设定溢出频率为1Hz,即1秒溢出1次; ③打开溢出中断;
④选择任意端口作为端口输出,以PD13为例;
⑤配置PD13;
⑥生成代码。 3.代码 main.c
#include "at32f403a_407_wk_config.h"
#include "at32f403a_407_board.h"
int main(void)
{
wk_system_clock_config();
wk_periph_clock_config();
wk_nvic_config();
wk_tmr6_init();
wk_gpio_config();
while(1)
{
}
}
at32f403a_407_wk_config.c
#include "at32f403a_407_wk_config.h"
void wk_system_clock_config(void)
{
crm_reset();
crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
while(crm_flag_get(CRM_LICK_STABLE_FLAG) != SET)
{
}
crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);
while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET)
{
}
crm_pll_config(CRM_PLL_SOURCE_HICK, CRM_PLL_MULT_60, CRM_PLL_OUTPUT_RANGE_GT72MHZ);
crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
{
}
crm_ahb_div_set(CRM_AHB_DIV_1);
crm_apb2_div_set(CRM_APB2_DIV_2);
crm_apb1_div_set(CRM_APB1_DIV_2);
crm_auto_step_mode_enable(TRUE);
crm_sysclk_switch(CRM_SCLK_PLL);
while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
{
}
crm_auto_step_mode_enable(FALSE);
system_core_clock_update();
}
void wk_periph_clock_config(void)
{
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_TMR6_PERIPH_CLOCK, TRUE);
}
void wk_nvic_config(void)
{
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
nvic_irq_enable(TMR6_GLOBAL_IRQn, 0, 0);
}
at32f403a_407_int.c
#include "at32f403a_407_int.h"
void TMR6_GLOBAL_IRQHandler(void)
{
if(tmr_interrupt_flag_get(TMR6, TMR_OVF_FLAG) != RESET)
{
tmr_flag_clear(TMR6, TMR_OVF_FLAG);
GPIOD->odt ^= GPIO_PINS_13; //PD13电平翻转
}
}
4.现象
LED每隔1秒闪烁1次。
参考资料:《RM_AT32F403A_407_CH_V2.06》的14.1基本定时器(TMR6和TMR7)参考手册
由于作者水平有限,本文难免有错误之处,恳请读者批评指正!
|
一篇很基础的基本定时器的使用,所演示的例程为定时器溢出中断使IO电平反转,但是作者的文章结构合理紧凑,配图清晰,重点信息标注得当,版面整洁易读。
感谢大佬的文章分享~后续申请原创请@21小跑堂,以便跑堂及时安排审核~~~