王者做网站,chown wordpress,怎样做淘客网站,精准推广这里写目录标题 一、定时器的作用二、定时器简介1、定时器类型2、时钟树3、定时器功能配置框图 三、定时器寄存器分析1、控制寄存器#xff08;TIMERx_CTL0)#xff09;2、DMA 和中断使能寄存器 (TIMERx_DMAINTEN)3、预分频寄存器 (TIMERx_PSC)4、计数器自动重载寄存器 (TIME… 这里写目录标题 一、定时器的作用二、定时器简介1、定时器类型2、时钟树3、定时器功能配置框图 三、定时器寄存器分析1、控制寄存器TIMERx_CTL0)2、DMA 和中断使能寄存器 (TIMERx_DMAINTEN)3、预分频寄存器 (TIMERx_PSC)4、计数器自动重载寄存器 (TIMERx_CAR)5、中断标志寄存器 (TIMERx_INTF) 四、定时器的配置1时钟使能2初始化定时器参数3设置允许更新中断。即TIMERx-DMAINTEN4中断优先级设置。5使能定时器6编写中断服务函数 五、定时器核心配置示例定时1ms六、定时器定时溢出时间计算1、定时器的时钟源。2、定时器频率3、自动重装载值 一、定时器的作用
定时功能设置不同时间长度的定时。系统滴答定时器一般用来提供“心跳”作用如延时操作、周期性任务调度、测试某段代码的执行时间等。中断触发定时器可以在达到设定的计数值时产生中断从而触发中断服务程序。这种机制使得CPU可以在处理其他任务的同时响应定时器的中断请求执行相应的中断服务程序。这对于需要实时响应的应用场景非常有用如实时数据采集、实时控制等。与GPIO一起实现外设功能。如PWM输入捕获、输出比较、DMA、占空比等。其中PWM脉冲宽度调制输出应用于控制电机、调节亮度、产生音频等场景的信号。通过配置定时器的PWM模式和相关参数可以精确地控制PWM信号的频率和占空比从而实现对外部设备的精确控制。外部事件计数GD32F350的定时器还可以用于测量外部事件的频率或计数外部事件的发生次数。通过将定时器的输入连接到外部信号源可以实现对外部信号的精确测量和计数。
二、定时器简介
1、定时器类型
以GD32为例此款芯片共有8个定时器。分三大类高级定时器、通用定时器和基本定时器。2、时钟树
各定时器挂载总线不同。
3、定时器功能配置框图
1高级定时器 高级定时器TIMER0是四通道定时器支持输入捕获和输出比较。可以产生PWM信号控制电机和电源管理。 高级定时器含有一个16位无符号计数器。
高级定时器是可编程的可被用来计数其外部事件可以驱动其他定时器 高级定时器包含了一个死区时间插入模块非常适合电机控制。
定时器和定时器之间是相互独立但是它们可以被同步在一起形成一个更大的定时器这些定时器的计数器一致地增加。
2通用定时器 3基本定时器 基本定时器可以由内部时钟源CK_TIMER驱动。 基本定时器时钟内部连接到TIMER_CK。 基本定时器仅有一个时钟源TIMER_CK用来驱动计数器预分频器。当CEN置位TIMER_CK 经过预分频器预分频值由TIMERx_PSC寄存器确定产生PSC_CLK。
三、定时器寄存器分析
以常用的通用定时器为例。
1、控制寄存器TIMERx_CTL0) 最低位 CEN 为计数器使能 0计数器禁能 1计数器使能 在软件将CEN位置1后外部时钟、暂停模式和编码器模式才能工作。触发模式可 以自动地通过硬件设置CEN位。
第7位 ARSE 自动重载影子使能 0禁能TIMERx_CAR寄存器的影子寄存器 1使能TIMERx_CAR寄存器的影子寄存器
第8、9位 CKDIV[1:0] 时钟分频。
其中使用定时器的前提是要使能时钟 enable a TIMER 即TIMER_CTL0_CEN置1 此设置一般在timer_enable()函数里。
TIMER_CTL0(timer_periph) |(uint32_t)TIMER_CTL0_CEN;2、DMA 和中断使能寄存器 (TIMERx_DMAINTEN) 最低位UPIE 更新中断使能 0禁止更新中断 1使能更新中断
第1位CH0IE 通道0比较/捕获中断使能 0禁止通道0中断 1使能通道0中断
第8位UPDEN 更新DMA请求使能 0禁止更新DMA请求 1使能更新DMA请求
第9位CH0DEN 通道0比较/捕获 DMA请求使能 0禁止通道0比较/捕获DMA请求 1使能通道0比较/捕获DMA请求
第14位 TRGDEN 触发DMA请求使能 0禁止触发DMA请求 1使能触发DMA请求
常用在enable the TIMER DMA 和 enable the TIMER interrupt 里。
TIMER_DMAINTEN(timer_periph) | (uint32_t)interrupt;//timer_interrupt_enable()
TIMER_DMAINTEN(timer_periph) | (uint32_t)dma;//timer_dma_enable()3、预分频寄存器 (TIMERx_PSC) TIMER_PSC(timer_periph) (uint16_t)initpara-prescaler;//设置预分频值常用在定时器的初始化中如timer_init()
4、计数器自动重载寄存器 (TIMERx_CAR) 计数器自动重载寄存器 (TIMERx_CAR)在物理上对应着两个寄存器。一个是可以直接操作的一个是看不到的。看不到的那个寄存器叫影子寄存器其实真正起作用的是影子寄存器。由控制寄存器TIMERx_CTL0)中的ARSE位的设置
当ARSE 0禁能TIMERx_CAR寄存器的影子寄存器。在这种情况下对TIMERx_CAR寄存器的直接写操作将直接修改该寄存器的值而没有备份或影子值。预装载寄存器的内容可随时传送到改寄存器此时两者是相通的。
当ARSE1使能TIMERx_CAR寄存器的影子寄存器当启用影子寄存器时对TIMERx_CAR寄存器的写操作实际上首先会更新影子寄存器的值。在某些特定的条件或事件如硬件复位或特定的同步事件发生时影子寄存器的值会被复制到主寄存器中从而确保主寄存器中的值始终是一个可靠和一致的备份。在每一次更新事件时才把预装载寄存器的内容传送到影子寄存器自动重装载寄存器的位描述如上所示。
5、中断标志寄存器 (TIMERx_INTF)
该寄存器用来标记当前与定时器相关的各种事件/中断是否发生。其位描述如下 第7位 BRKIF 中止中断标志位 一旦中止输入有效由硬件对该位置‘1’。如果中止输入无效则该位可由软件清‘0’。 0无中止事件产生 1中止输入上检测到有效电平
最低位UPIF 更新中断标志 此位在任何更新事件发生时由硬件置1软件清0。 0无更新中断发生 1发生更新中断
四、定时器的配置
通过库函数进行配置相关的库函数有gd32f20x_timer.h 和 stm32120x_timer.c 文件。
1时钟使能
TIMERx是挂在APB1之下的通过APB1总线下的使能函数来使能TIMERx。例如 rcu_periph_clock_enable(RCU_TIMER5)2初始化定时器参数
如设置自动重装值、分频系数 、计数方式等。 定时器的初始化参数是通过初始化函数timer_init实现的。例如
timer_init(TIMER5, timer_initpara);第一个参数确定定时器 第二个参数定时器初始化化参数结构体指针结构体类型为 timer_parameter_struct其结构体定义为
typedef struct
{ uint32_t prescaler; // 预分频值 uint32_t alignedmode; // 对齐模式 uint32_t countermode; // 计数器模式 uint32_t period; // 自动重载值 uint32_t clockdivision; // 时钟分频因子 uint32_t repetitioncounter; // 重复计数器值
} timer_parameter_struct;
3设置允许更新中断。即TIMERx-DMAINTEN
因为我们要使用TIMER5的更新中断,寄存器的相应位便可使能更新中断。在库函数里面定时器中断使能是通过timer-interrupt-enable()函数来实现的。 void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt)
timer_periph选择定时器取值为TIMERx(x0.13). interrupt用来指明使能的定时器中断的类型定时器中断的类型有很多种包括TIMER-INTUP、TIMER_INT_TRG、TIMER_INT_BRK、TIMER_INT_CH0等。 例如
timer_interrupt_enable(TIMER5,TIMER_INT_UP);4中断优先级设置。
定时器中断使能后因为要产生中断所以要设置中断NVIC相关寄存器设置中断优先级。 例如
void timer1_nvic_config(void)
{nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);nvic_irq_enable(TIMER5_IRQn, 0, 1);
}5使能定时器
允许定时器工作即开启定时器。配置完定时器后要启动定时器通过TIMER_CTL0的TIMER_CTL0_CEN来设置通常是通过函数timer_enableTIMERx来实现。例如
timer_enableTIMER56编写中断服务函数
此函数的功能是用来处理定时器产生的相关中断。在中断产生后通过状态寄存器的值去判断此次产生的中断属于什么类型。 然后执行相关的操作大多使用更新(溢出)中断即中断标志寄存器TIMER_INTF的最低位。处理完中断之后应想TIMER_INTF最低位写零来清楚中断标志。
来读取中断状态寄存器的值来判断中断类型的函数是 timer_interrupt_flag_get
读取该函数的目的是判断定时器的中断类型是否发生中断。例如 判断定时器5是否发生更新溢出中断方法为
ifSET timer_interrupt_flag_get(TIMER1,TIMER_INT_UP)
{timer_interrupt_flag_clear(TIMER1,TIMER_INT_UP);//清除中断标志位//其它程序……}五、定时器核心配置示例定时1ms
/*brief configure the TIMER peripheralparam[in] noneparam[out] noneretval none*/
void timer5_init(void)
{/* TIMER5 configuration: generate 1msSystemCoreClock 72MHZTIMER1CLK SystemCoreClock / 72 1MHz */timer_parameter_struct timer_initpara; //定时器参数// 时钟使能 rcu_periph_clock_enable(RCU_TIMER1); timer_deinit(TIMER5);/*初始化定时器参数*//* TIMER1 configuration */timer_initpara.prescaler 71;timer_initpara.alignedmode TIMER_COUNTER_EDGE;timer_initpara.counterdirection TIMER_COUNTER_UP;timer_initpara.period 999;timer_initpara.clockdivision TIMER_CKDIV_DIV1;timer_init(TIMER5, timer_initpara);timer_auto_reload_shadow_enable(TIME5);timer_interrupt_flag_clear(TIMER5,TIMER_INT_UP);/* 设置允许更新中断TIMERx-DMAINTEN*/ timer_interrupt_enable(TIMER5,TIMER_INT_UP); /*中断优先级设置*///TIMER1 interrupt setting, preemptive priority 0, sub-priority 3nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);nvic_irq_enable(TIMER5_IRQn, 0, 3); /* 使能定时器*/timer_enable(TIMER5); // rcu_periph_clock_disable(RCU_TIMER5);/*先关闭等待使用*/
}/** 中断服务程序* brief This function handles TIMER1 interrupt request.* param None* retval None*/
void TIMER5_IRQHandler(void)
{if ( SET timer_interrupt_flag_get(TIMER5 , TIMER_INT_UP) ) {timer_interrupt_flag_clear(TIMER5 , TIMER_INT_UP);time;}
}/*主函数*/
volatile uint32_t time 0; // ms 计时变量
int main(void)
{//system clocks configurationsystemclk_init();/* configure the TIMER peripheral */timer5_init();/* configure LED1 GPIO port */led_init(LED1);//Enable TIMER1 clock// rcu_periph_clock_enable(RCU_TIMER1);while(1) {if ( time 1000 ) /* 1000 * 1 ms 1s 时间到 */{time 0;/* LED 取反 */ led_toggle(LED1); } }
}
或者直接定时1s进行使用。
void TIME_Ms(uint32_t ms)
{timer_val ms;while(timer_val);
}
void TIMER5_IRQHandler(void)
{if(SET timer_interrupt_flag_get(TIMER5, TIMER_INT_FLAG_UP)){timer_interrupt_flag_clear(TIMER5, TIMER_INT_FLAG_UP);if(timer_val) --timer_val;}
}/*主函数*/
volatile uint32_t timer_val 0; // ms 计时变量
int main(void)
{//system clocks configurationsystemclk_init();/* configure the TIMER peripheral */timer5_init();/* configure LED1 GPIO port */led_init(LED1);//Enable TIMER1 clock// rcu_periph_clock_enable(RCU_TIMER1);while(1) {TIME_Ms(1000); /* 1000 * 1 ms 1s 时间到 */led_toggle(LED1); }
}
六、定时器定时溢出时间计算
1、定时器的时钟源。
以下均以基本定时器time5为例time5在APB1后分频所得 定时器时钟CK_TIMER5经 APB1 预分频器后分频提供。 如果 APB1 预分频系数等于 1则频率不变否则频率乘以 2库函数中 APB1 预分频的系数是 2关注 RCU_APB1_CKAHB_DIV2;即 PCLK136M所以定时器时钟 CK_TIMER36*272M即和系统时钟的值相同。 参考【GD32】_时钟架构及系统时钟频率配置
其时钟初始化代码在system_stm32f20x.c定义的这里使用的默认配置具体时钟设置函数是system_clock_72m_hxtal()代码如下
static void system_clock_72m_hxtal(void)
{uint32_t timeout 0U;uint32_t stab_flag 0U;/* enable HXTAL */RCU_CTL | RCU_CTL_HXTALEN;/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */do {timeout;stab_flag (RCU_CTL RCU_CTL_HXTALSTB);} while((0U stab_flag) (HXTAL_STARTUP_TIMEOUT ! timeout));/* if fail */if(0U (RCU_CTL RCU_CTL_HXTALSTB)) {while(1) {}}/* HXTAL is stable *//* AHB SYSCLK */RCU_CFG0 | RCU_AHB_CKSYS_DIV1;/* APB2 AHB/2 */RCU_CFG0 | RCU_APB2_CKAHB_DIV2;/* APB1 AHB/2 */RCU_CFG0 | RCU_APB1_CKAHB_DIV2;/* CK_PLL (CK_PREDIV0) * 9 72 MHz *///当晶振为8M时RCU_CFG0 ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLDV | RCU_CFG0_PLLSEL);RCU_CFG0 | (RCU_PLLSRC_HXTAL_IRC48M| RCU_PLL_MUL6);//选择外部晶振12M/* enable PLL1 */RCU_CTL | RCU_CTL_PLL1EN;/* wait till PLL1 is ready */while((RCU_CTL RCU_CTL_PLL1STB) 0U) {}/* enable PLL */RCU_CTL | RCU_CTL_PLLEN;/* wait until PLL is stable */while(0U (RCU_CTL RCU_CTL_PLLSTB)) {}/* select PLL as system clock */RCU_CFG0 ~RCU_CFG0_SCS;RCU_CFG0 | RCU_CKSYSSRC_PLL;/* wait until PLL is selected as system clock */while(0U (RCU_CFG0 RCU_SCSS_PLL)) {}
}
2、定时器频率
TIMER5上的时钟为72Mhz定时器分频系数为71因此TIME5的频率为
CK_CNTTIMERxCLK/(PSC1)1MHz
3、自动重装载值
Prtscaler (定时器分频系数) : 71
Counter Mode(计数模式) Up(向上计数模式)
Counter Period(自动重装载值) : 999
CKD(时钟分频因子) No Division 不分频
所以溢出时间Tout 1/1MHZ *(9991) 1ms
自动重装载值计算溢出时间要加1这是因为自动重装载寄存器 TIMERx_CAR是从0开始计数的。