【GD32450I-EVAL】定时器 测试ADC速度
[复制链接]
本帖最后由 tinnu 于 2020-10-8 13:57 编辑
测试ADC速度需要定时器的加持,所以必须先将定时器功能摸清楚。
(一)定时器时钟
定时器的时钟是经过:AHB——APB——定时器
我们使用的是TIMER1
有意思的是CK_APB1总线最高只能到50M,而从CK_APB1出来的时钟却可以到达200M,这是中间有一个倍频的功能。
1-CK_APB1的时钟
关于这个时钟可以看:UART
USART使用的是PCLK1时钟,目前CK_APB1的时钟是最高的50M
2-TIMER时钟
TIMER1使用的是CK_APB1倍频后的时钟。关于倍频系数可以参考 RCU_CFG1寄存器:
在复位状态下为0,即2倍频。这里2倍频是100M。
(二)设置
例程的配合代码:
timer_parameter_struct timer_initpara;
timer_initpara.prescaler = 9999;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 9999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1,&timer_initpara);
") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;">
有一个预分频器和比较器。在100M的时钟下,一次更新的时间为(9999+1)*(9999+1)=100M,刚好1S。
使能中断:
timer_interrupt_enable(TIMER1, TIMER_INT_UP);
nvic_irq_enable(TIMER1_IRQn, 2U, 0U);
") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;">
使能定时器:
timer_enable(TIMER1);
") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;">
实际上运行之后会发现无法触发外部中断,这是因为TIMER1的时钟要额外使能:
rcu_periph_clock_enable(RCU_TIMER1);
") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;">
(三)中断服务函数与测试ADC速度的代码
ADC这里需要失能中断,在主循环里面操作,因为在使能了ADC的连续读写功能后,ADC的转换速度是惊人的,中断的速度根本跟不上读写的速度,甚至主循环里面多一句代码都会严重影响测试的准确度。这也是为何ADC建议采用DMA方式读写的原因,但是DMA不方便测试速度,因此还是采用轮询的方式。
1-使能ADC连续转换功能
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;">
2-在初始化的时候使能一次
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
") rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;">
3-主循环里面不能进行多余的操作
if (adc_interrupt_flag_get(ADC0, ADC_INT_FLAG_EOC) == SET)
{
adc_regular_data_read(ADC0);
adc_counter++;
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
}
4-定时器的中断服务函数
void TIMER1_IRQHandler(void)
{
char t_char[30] = "";
gd_eval_led_toggle(LED1);
sprintf(t_char, "ADC for one second:%d\r\n", adc_counter);
PRINTF_UART0(t_char);
adc_counter = 0;
timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
}
(四)效果
当采样速度为ADC_SAMPLETIME_112
ADC for one second:403225
ADC for one second:402292
ADC for one second:402292
ADC for one second:402291
ADC for one second:402291
ADC for one second:402291
ADC for one second:402292
ADC for one second:402292
一秒400K的速度。
当采样速度为ADC_SAMPLETIME_15
ADC for one second:1010101
ADC for one second:1007662
ADC for one second:1007662
ADC for one second:1007661
ADC for one second:1007661
已经有1M了。
但必须注意到,采用速度的增加并没有跟上转换速度增加的比例,这可能还是存在轮询耗时的问题。毕竟1M的转换速度下,实际上每次只有200个机器时钟。
(五)ADC执行也放进中断
之后尝试了把ADC的执行操作也放入ADC中断,这里设置定时器中断的抢断优先级更高一点:
nvic_irq_enable(TIMER1_IRQn, 1U, 0U);
当采样速度为ADC_SAMPLETIME_112:
ADC for one second:403225
ADC for one second:402292
ADC for one second:402292
竟然和轮询的时候一模一样,看来在400k低速情况下中断是不会成为转换的瓶颈
当采样速度为ADC_SAMPLETIME_15
ADC for one second:925925
ADC for one second:923779
ADC for one second:923778
这时候就明显小于轮询了
|