文章目录
一.概要
ADC(Analog to Digital Converter),即模数转换器,是将连续的模拟信号转换为离散的数字信号的单片机外设。典型的模拟数字转是将模拟信号转换为表示一定比例电压值的数字信号,比如温度传感器等一些传感器,输出的信号是0~3.3V的电压信号。
例如温度传感器输出电压0V代表采集到的温度是0°C,输出电压3.3V代表温度是100°C,温度跟电压成线性比例关系,如果单片机ADC外设采集的到电压是1.65V,那就代表温度是50°C(100°C*1.65/3.3),如果单片机ADC外设采集到的电压是3.3V,那就代表温度是100°C。
二.GD32F103C8T6单片机ADC外设特点
GD32F103C8T6含有2个12位的模拟/数字转换器(ADC0,ADC1),每个ADC共用多达10个外部通道,可以实现单次或连续转换,1MHz转换速率,转换范围:0~3.6V,ADC供电要求:2.4V~3.6 V。ADC0同时含有2个内部通道:连接到芯片内部温度传感器和内部参考电压(VREFINT = 1.2V),ADC输入范围:VREFN ≤VIN ≤VREFP。
10个外部通道对应的单片机上的引脚如下图
三.GD32单片机ADC内部结构图
ADC内部结构图如下
1.ADC相关引脚说明
(1)VDDA(Analog Supply Voltage)
ADC模块的模拟电源引脚,通常连接到MCU的模拟电源线路。VDDA提供ADC模块所需的模拟电源电压,确保ADC的正常工作和准确的模拟信号转换。
(2)VSSA(Analog Ground Voltage)
ADC模块的模拟地引脚,通常连接到MCU的模拟地线路。
(3)VREFP(Positive Voltage Reference)
ADC模块的正参考电压引脚,通常连接到外部提供的正参考电压源。VREFP确定了ADC转换过程中的上限电压参考点,通常对应于模拟输入信号的最大量程值。在ADC转换过程中,被测量的模拟信号会与VREFP进行比较,以确定其对应的数字量,GD32F103C8T6是没有这个引脚,64脚和小于64脚的GD32F103型号,其VREFP在芯片内部与VCC信号线相连,没有引到片外,这样ADC的参考电压就是VCC上的电压。
(4)VREFN(Negative Voltage Reference)
ADC模块的负参考电压引脚,通常连接到外部提供的负参考电压源或地。VREFN确定了ADC转换过程中的下限电压参考点,通常对应于模拟输入信号的最小量程值。
GD32F103C8T6也没有这个引脚,内部相当于GND来替代。
2.ADC通道分类
在GD32的ADC模块中,分成了两种不同类型的通道类型:规则通道和注入通道,它们适应于不同的采集场景。
功能框图如下所示:
ADC规则通道
规则通道顾名思义就是,最平常的通道、也是最常用的通道,平时的ADC转换都是用规则通道模式的。它允许用户配置ADC以便按照预定的顺序对这些通道进行连续或单次采样。
ADC注入通道
注入通道是相对于规则通道的,注入通道可以在规则通道转换时,强行插入转换,相当于一个“中断通道”吧。当有注入通道需要转换时,规则通道的转换会停止,优先执行注入通道的转换,当注入通道的转换执行完毕后,再回到之前规则通道进行转换。这种功能使得注入通道特别适合于采集突发事件或需要高优先级响应的应用,比如实时监控或故障检测。
3.触发源
ADC转换的输入、通道、转换顺序都已经说明了,但ADC转换是怎么触发的呢?就像通信协议一样,都要规定一个起始信号才能传输信息,ADC也需要一个触发信号来实行模/数转换。
1.ADC_CTL1寄存器中的ADCON位是ADC模块的使能开关,就可以进行转换,比较好理解。
2.另外,还可以通过内部定时器或者外部IO触发转换,也就是说可以利用内部时钟让ADC进行周期性的转换,也可以利用外部IO使ADC在需要时转换,具体的触发由控制寄存器ADC_CTL1寄存器决定。
4.转换周期
ADC使用若干个ADCCLK周期对输入电压采样,采样周期数目可以通过ADC_SAMPT0和
ADC_SAMPT1寄存器的SPTn[2:0]位更改。每个通道可以用不同的时间采样。在12位分辨率的情况下,总转换时间=采样时间+12.5个ADCCLK周期。
例如:
ADCCLK = 14MHz ,采样时间为1.5个周期,那么总的转换时间为:(1.5+12.5)个ADCCLK周期,即1us。
注意:如果想要获取较稳定的采集数据需要降低ADC的采样时钟,增大采样周期,硬件运
行的情况下减小外部输入阻抗。
5.电压转换计算
AD转换后,从ADC_RDATA寄存器读到的数据是一个12位的二进制数,我们需要把这个二进制数代表的模拟量(电压)用数字表示出来。比如测量的电压范围是0~3.3V,ADC转换后的寄存器读到的数是x,因为12位ADC在转换时将电压的范围大小(也就是3.3)分为4096(2^12)份,所以真实电压的计算方法就是: y=3.3* x / 4096(V)
6.更精确电压转换计算
1.GD32F103C8T6是VDD3.3V做参考电压,但是这种方法在供电电压有可能随外部一些其他用电器工作使用的大电流而导致电压不稳定,内部参考电压能更加精确计算采样到的电压,具体方法是在测量某个通道的电压值之前,先读出参照电压的ADC测量数值(Vrefint Channel),记为VREFINT;再读出要测量通道的ADC转换数值,记为ADchx;则要测量的电压为:
Vchx = VREFINT * (ADchx/ADrefint)
2.前置校准,ADC带有一个前置校准功能。在校准期间,ADC计算一个校准系数,这个系数是应用于ADC内部的,它直到ADC下次掉电才无效。在校准期间,应用不能使用ADC,它必须等到校准完成。在A/D转换前应执行校准操作。通过软件设置CLB=1来对校准进行初始化,在校准期间CLB位会一直保持1,直到校准完成,该位由硬件清0。
四.规则通道ADC采集的单次模式跟连续模式
1.单次转换模式
配置为单次模式使能。这样ADC的这个通道,转换一次后,就停止转换,需要下一次再触发才可以。
规则通道单次转换结束后,转换数据将被存放于ADC_RDATA寄存器中,EOC将会置1。如果EOCIE位被置1,将产生一个中断。
2.连续转换模式
配置为连续模式使能。这样ADC的这个通道,转换一次后,接着进行下一次转换,只需一开始触发一次就可以。
五.GD32F103C8T6单片机ADC采集例程
STLINK接GD32F103C8T6开发板,STLINK接电脑USB口。
GD32F103C8T6开发板的PA4 引脚上的进行 ADC 电压采集,杜邦线连接 PA4 引脚与 VDD(3.3V),应该能读到单片机供电的电压值。
主要代码:
uint16_t adc_value;//采样值
uint16_t Vol_Value;//转换后的电压值
//ADC使能
void adc_config(void)
{
/* reset ADC */
adc_deinit(ADC1);
// /* ADC mode config */
adc_mode_config(ADC_MODE_FREE);
/* ADC continous function enable */
adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE); //连续模式
/* ADC data alignment config */
adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);//右对齐
/* ADC resolusion 6B */
/* ADC channel length config */
adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 1);
/* ADC regular channel config */
adc_regular_channel_config(ADC1, 0, ADC_CHANNEL_4, ADC_SAMPLETIME_55POINT5);
/* ADC trigger config */
adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);
adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);
/* enable ADC interface */
adc_enable(ADC1);
delay_1ms(1);
/* ADC calibration and reset calibration */
adc_calibration_enable(ADC1);//前置校准
}
int main(void)
{
rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV1);//设置主频108M(#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)),8M外部晶振 (#define HXTAL_VALUE ((uint32_t)8000000))
systick_config();//配置1ms SysTick
rcu_periph_clock_enable(RCU_AF);//AF时钟使能
//配置PA4 ADC引脚
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
/* enable ADC1 clock */
rcu_periph_clock_enable(RCU_ADC1);
/* config ADC clock */
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);
//配置ADC
adc_config();
adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL);//软件触发
while(1)
{
adc_flag_clear(ADC1,ADC_FLAG_EOC);
while(SET != adc_flag_get(ADC1,ADC_FLAG_EOC)){//判断是否转换完成
}
adc_value = ADC_RDATA(ADC1);//读取ADC数据
Vol_Value=adc_value*3300/4095;//转换成电压值
delay_1ms(500);
}
}
实验结果:
用Keil运行程序,全速运行,查看Keil调试Watch界面,如下图,PA4引脚的采样值adc_value
为0xfff,电压值为3300mV。
六.工程源代码下载
通过百度网盘分享的文件:3.ADC实验.zip
链接:https://pan.baidu.com/s/1BEVUhw-zl97scnExLU5RQQ
提取码:1aa2
如果链接失效,可以联系博主给最新链接
程序下载下来之后解压就行
七.小结
ADC外设是GD32单片机开发中的最基本操作,学会了ADC,可以采集外部的一些传感器的模拟信号,适应更多模块的数据采样。