【GD32450I-EVAL】ADC:软件触发+中断+单次转换模式
[复制链接]
(一)ADC性能
GD32F450拥有3个ADC,每个ADC的采样速度最高可以达到2.6Mpsp,这还是在12位最高精度的条件下,如果降低精度还能更快。
(二)ADC概念
GD32的各种设计与国外大厂的很像:
1-注入组和规则组
规则组为常规转换,注入组类似于中断,中间插入一次计划外的转换
2-通道
有3个ADC,每个ADC有19路通道,每个ADC的每个通道都映射到固定的引脚,这可以在数据手册中查询到。
3-转换序列
相当于一个工作队列,序列第一位的转化完,第二位的接着,全部转化完后可以重新再转化一轮
规则组可以控制多达16个序列
注入组少一点,只能支持4个序列
(三)ADC与IO映射关系
每个ADC的每个通道都映射到固定的引脚
比如本次使用的PC3引脚
就是与ADC012三个ADC的IN13通道映射起来的,只要配置了PC3为模拟功能(AFIO),ADC任意一个使能了13通道就可以获取该引脚的模拟量值。
配置代码:
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3);
![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==) ![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
(四)ADC寄存器
ADC的寄存器看上去不少,但实际上只使用规则组进行单个通道转化的时候绝大部分都是用不到的。
看门狗、过采样、注入、摘要这些都不需要管。
因为转换的只有一个通道,就不需要涉及多个通道轮流转换的问题(即转换序列),因此同步相关配置也暂时无用。
所以需要配置的寄存器只有控制寄存器01、采样时间寄存器01、规则序列寄存器012
(五)ADC配置流程
如果采用最简单的单次转化的工作方式,参考手册给出了配置流程:
看着有8步,实际上:
第1步是设置ADC工作方式,在单次转化中,这些相关位都是保持为0,即复位值,如果是初始化配置根本不需要理睬。
第4步是配置硬件触发方式
第5-8步都不是初始化的工作
即实际最简单初始化只需要做第2、3步
(六)初始化
1-配置RSQ:
调用函数,设置该ADC有多少个序列,这里只有一个通道需要转换,只有一个序列:
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);
![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==) ![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
操作 ADC_RSQ0 的 RL位 规则通道序列长度 规则通道转换序列中的总的通道数目为 RL[3:0]+1。
操作 ADC_ISQ 的 TL 位 注入通道组长度 注入组总的通道数目为 IL[1:0]+1。
参数功能:
2-规则组或者注入组
3-多少个序列
2-配置SAMPT
设置具体哪个通道对应哪个序列
adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_13, ADC_SAMPLETIME_15);
![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==) ![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
操作寄存器的过程比较复杂,同时操作了 ADC_RSQ2 寄存器
和操作 ADC_SAMPT1 寄存器 设置通道采样时间
函数参数功能:
2-第三个参数配置的通道,在规则组哪个序列
3-哪个通道
4-转换多少个时钟
(七)使能中断功能
ADC的所有中断都在同一个中断向量里:
使能:
adc_interrupt_enable(ADC0, ADC_INT_EOC);
nvic_irq_enable(ADC_IRQn, 2U, 0U);
![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==) ![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
服务函数:
void ADC_IRQHandler(void)
{
uint16_t i=0;
char t_char[30] = "";
if(adc_interrupt_flag_get(ADC0, ADC_INT_FLAG_EOC)==SET)
{
i = adc_regular_data_read(ADC0);
sprintf(t_char, "adc:%x\t%f\r\n", i, (float)i/0xFFF*3.3);
PRINTF_UART0(t_char);
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
}
}
![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==) ![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
(八)软件启动转换
前面第五步提到,软件启动是置位 SWRCST ,这个位会硬件复位。对应库函数:
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==) ![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
在主循环中调用:
1-使能ADC并校准
adc_enable(ADC0);
delay_ms(1);
adc_calibration_enable(ADC0);
![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==) ![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
2-主循环内
while(1){
delay_ms(4);
if(t_ledshark >20){
t_ledshark = 0;
gd_eval_led_toggle(LED1);
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}
t_ledshark++;
}
(九)效果
更清晰的视频等审核之后再传
|