GD32F470之Timer定时功能开发

文章详细介绍了GD32F470芯片中定时器的配置方法,包括时钟源的选择,如25MHz外部晶振和200MHz系统时钟,APB总线的分频设置,以及定时器挂载在APB1总线上的情况。定时时间计算涉及预分频值和重装载值,举例展示了不同设置下的定时时间差异,并提供了定时器初始化函数和中断处理示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

关于Timer部分,之前一值使用STM32型MCU,定时器时钟大多数都是基于APB1或APB2上分频获得,再设置预分频值和装载值,即可计算出定时时间。但GD32F470型定时器使用定时时间计算与之有很大区别。

时钟源

使用定时器,首先需要从时钟树上获取以下几个信息:

1、外部晶振:本文举例选用25MHz;

2、系统时钟:通过system_gd32f4xx.c文件中开启对应晶振和系统时钟的宏定义。支持8M、16M和25M三种晶振,系统时钟分别为120MHz、168MHz、200MHz以及240MHz。

本文举例使用25M晶振,系统时钟为200MHz。对应宏定义如下:

#define __SYSTEM_CLOCK_200M_PLL_25M_HXTAL       (uint32_t)(200000000)

此时系统时钟CK_SYS  :200MHz

AHB:CK_SYS       CFG0->APHPSC:0X00  不分频       200MHz

APB1:CK_AHB/4    CFG0->APB1PSC:0X05  4分频      50MHz

APB2:CK_AHB/2    CFG0->APB2PSC:0X04  2分频      100MHz

3、时钟树中定时器挂在哪个总线上

选用Timer1,定时器1挂接在APB1总线上 

4、时钟源选择CFG1->TIMERSEL

CFG1->TIMERSEL默认为0时:

CFG0->APB1PSC:0X05时,时钟源CK_TIMER1 = 2*CK_APB1 = 2*CH_AHB/4 = 100MHz

CFG1->TIMERSEL选择为1时:

CFG0->APB1PSC:0X05时,时钟源CK_TIMER1 = CH_AHB = 200MHz

5、定时时间计算

prescaler:设置用来作为TIMx时钟频率除数的预分频值;

period:设置在下一个更新事件装入活动的自动重装载寄存器周期的值;

定时时间: (prescaler+1)/ CK_TIMER1* (period+1)

例如:prescaler为9(计数从0开始,到prescaler值结束,因而共(prescaler+1)个时钟),period为1999(计数从0开始,到period值结束,因而共(period+1)个时钟)时,CFG1->TIMERSEL为0时,定时时间2ms; CFG1->TIMERSEL为1时,定时时间1ms

 定时器参数配置

定时器实现函数如下:

void DRV_TIM_Config(unsigned int arr, unsigned int psc)
{
    timer_parameter_struct initpara;
    rcu_periph_clock_enable(RCU_TIMER1);//开启时钟
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);//对应时钟源选择CFG1->TIMERSEL选择为1
    initpara.prescaler         = psc;//设置用来作为TIMx时钟频率除数的预分频值
    initpara.period            = arr;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
 //   initpara->alignedmode       = TIMER_COUNTER_EDGE;
    initpara.counterdirection  = TIMER_COUNTER_UP;
    initpara.clockdivision     = TIMER_CKDIV_DIV1;

    timer_init(TIMER1, &initpara);
    //清状态,设置中断
    timer_flag_clear(TIMER1, TIMER_FLAG_UP);
    timer_interrupt_enable(TIMER1, TIMER_INT_UP);
    //定时器中断
    /* enable and set timer interrupt priority */
    nvic_irq_enable(TIMER1_IRQn, 1U, 1U);
    timer_enable(TIMER1);
}

main函数中调用以下语句:

DRV_TIM_Config(99,1999);//1ms定时  200MHZ

//定时器中断

void TIMER1_IRQHandler(void)

{

    static unsigned int tcntt = 0;

    if(SET == timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_UP))

    {

        //添加定时处理代码

        tcntt++;

        timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);

    }

}

总结:

GD32F470定时器使用时,需要根据定时器时钟挂接总线时钟,定时器时钟源CFG1->TIMERSEL以及预分频值和重装载值来计算定时时间。

### GD32F470VET6 定时器7 触发 ADC DMA 数据采集 配置 示例 以下内容详细描述了如何使用 GD32F470VET6 的定时器7触发 ADC 进行 DMA 数据采集的配置方法。此过程包括时钟使能、GPIO 配置、ADC 初始化、DMA 配置以及定时器7的触发配置。 #### 1. 硬件和时钟配置 在开始之前,需要确保相关外设的时钟已正确使能,并将 ADC 输入通道对应的 GPIO 配置为模拟输入模式。 ```c rcu_periph_clock_enable(RCU_GPIOA); // 使能 GPIOA 时钟 rcu_periph_clock_enable(RCU_ADC); // 使能 ADC 时钟 rcu_periph_clock_enable(RCU_DMA0); // 使能 DMA0 时钟 rcu_periph_clock_enable(RCU_TIMER7); // 使能 TIMER7 时钟 // 配置 PA0 为模拟输入 gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_0); ``` #### 2. ADC 初始化 设置 ADC 的分辨率、对齐方式、扫描模式等参数,并启用 DMA 模式。 ```c adc_init(ADC0, ADC_SCAN_DISABLE, ADC_CONTINUOUS_DISABLE, ADC_DMACFG_ONESHOT); adc_resolution_set(ADC0, ADC_RESOLUTION_12B); adc_data_align_set(ADC0, ADC_DATAALIGN_RIGHT); // 配置 ADC 通道 adc_channel_length_set(ADC0, ADC_REGULAR_CHANNEL, 1); adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_56); // 启用 ADC 并进行校准 adc_enable(ADC0); adc_calibration_enable(ADC0); ``` #### 3. DMA 配置 配置 DMA 以实现数据从 ADC 到内存的自动传输。 ```c uint16_t adc_value[1]; // 存储 ADC 转换结果 dma_parameter_struct dma_init_struct; dma_deinit(DMA0, DMA_CH0); // 取消初始化 DMA0 通道 0 dma_init_struct.periph_addr = (uint32_t)&ADC_RDATA(ADC0); // 外设地址 dma_init_struct.memory_addr = (uint32_t)adc_value; // 内存地址 dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init_struct.number = 1; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_DISABLE; dma_init_struct.periph_inc = DMA_PERIPHERAL_INCREASE_DISABLE; dma_init(DMA0, DMA_CH0, &dma_init_struct); dma_circulation_disable(DMA0, DMA_CH0); dma_memory_to_memory_disable(DMA0, DMA_CH0); dma_channel_enable(DMA0, DMA_CH0); // 启用 DMA 通道 // 配置 ADC 使用 DMA adc_dma_mode_enable(ADC0); adc_dma_enable(ADC0); ``` #### 4. 定时器7 配置 配置定时器7以触发 ADC 转换。通过设置定时器的更新事件来触发 ADC 转换。 ```c timer_parameter_struct timer_initpara; // 配置 TIMER7 基本参数 timer_deinit(TIMER7); timer_initpara.prescaler = 8399; // 设置预分频器,假设系统时钟为 168MHz,则定时器时钟为 20kHz timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 999; // 自动重装载值,定时器周期为 50ms timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_init(TIMER7, &timer_initpara); // 配置定时器7更新事件触发 ADC timer_master_mode_output_config(TIMER7, TIMER_MASTER_OUTPUT_UPDATE); timer_master_mode_config(TIMER7, TIMER_TRGO_RESET, TIMER_MASTER_SLAVE_MODE_ENABLE); // 启用定时器7 timer_enable(TIMER7); ``` #### 5. 中断处理(可选) 如果需要在 DMA 传输完成后执行某些操作,可以配置 DMA 中断。 ```c void DMA1_Channel0_IRQHandler(void) { if (SET == dma_interrupt_flag_get(DMA1, DMA_CH0, DMA_INT_FLAG_FTF)) { dma_interrupt_flag_clear(DMA1, DMA_CH0, DMA_INT_FLAG_FTF); // 清除中断标志 // 在此处添加用户代码,例如处理采集到的数据 } } ``` 以上配置实现了通过定时器7触发 ADC 进行 DMA 数据采集的功能[^1]。 ####
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值