一:ADC知识
ADC 即模拟-数字转换器(Analog-to-digital converter),是一种用于将连续的模拟信号转换为离散的数字信号的器件。就比如我们可以将我们生活中的温度、压力、声音这样的模拟信号通过ADC转化为可以通过单片机处理的数字信号。
MCU包含12位逐次逼近A/D转换器(ADC12)单元。最多可选择13个模拟输入通道、温度传感器输出和内部参考电压进行转换。
A/D转换精度可选12位、10位和8位,从而在生成数字值时优化速度与分辨率之间的权衡。
ADC12支持以下工作模式:
单扫描模式,按通道编号升序转换选定通道的模拟输入
连续扫描模式,可按通道编号升序连续转换所选通道的模拟输入。
分组扫描模式,将通道的模拟输入分为两组(A组和B组),并根据通道编号从小到大依次对每组选定通道的模拟输入进行转换。
在群组扫描模式下,请选择两个群组(群组A和B)。您可分别选择每个群组(群组A、B)的扫描起始条件,并分别在不同的时间开始对各群组进行扫描。此外,当设置群组A的优先级控制操作时,ADC12会在群组B进行A/D转换期间接受群组A的扫描起始请求,从而暂停群组B的转换过程。这可使您能够对群组A的A/D转换起始赋予更高的优先级。
在双触发模式下,选定通道的模拟输入会在单扫描模式或群组扫描模式(群组A)下进行转换,而由第一和第二A/D转换启动触发器所转换的数据则被分别存储在不同的寄存器中,从而实现A/D转换数据的双工传输。
每次扫描开始时执行一次自诊断,ADC12生成的三个参考电压值之一被进行A/D转换。
温度传感器输出值和内部参考电压可同时与通道的模拟输入一起进行选择。首先对该通道的模拟输入进行第一次A/D转换,随后是对温度传感器输出值的转换,最后是对内部参考电压的转换。
ADC12还具备比较功能(窗口A和窗口B)。该比较功能用于指定窗口A的上参考值和窗口B的下参考值,并在所选通道的A/D转换值满足比较条件时输出中断信号。
A/D数据存储缓冲区是一个环形缓冲区,由16个缓冲区组成,用于依次存储A/D转换后的数据。
二:FSP库的配置

ADC属性配置如下所示:
● Name:g_adc0该 ADC 实例的名称,在代码中用于引用此 ADC 设备。
● Unit:0表示使用的是 ADC0 设备(MCU 可能有多个 ADC 单元,如 ADC0、ADC1 等)。
● Resolution:12-Bit选择 ADC 分辨率为 12 位,即转换后的数值范围为 0~4095(2^12 = 4096)。
● Alignment:Right选择数据右对齐,即 ADC 结果存储时,低 12 位有效,高位填充 0。
● Clear after read:On每次读取 ADC 结果后,寄存器会自动清除,防止旧数据干扰新采样。
● Mode:Single Scan单次扫描模式,即每次触发 ADC 转换后,仅采样一次选中的通道。
● Normal/Group A Trigger:SoftwareADC 触发方式为软件触发,即需要手动调用 API R_ADC_ScanStart() 来启动转换。
● Callback(回调函数):指定回调函数 adc_callback,用于 ADC 转换完成后的事件处理。
● Scan End Interrupt Priority(扫描结束中断优先级):Priority 2ADC 扫描结束中断的优先级设置为 2(数值越小,优先级越高)。
● AN012 → P014 :ADC 通道 12(AN012)映射到 P014 引脚,即 ADC 采样的模拟信号输入在 P014 引脚。
三:软件代码:
3.1 初始化ADC
void adc0_init(void)
{
fsp_err_t err = FSP_SUCCESS;
/* Initializes the module. */
/* Initializes the module. */
err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Enable channels. */
err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
assert(FSP_SUCCESS == err);
}
3.2 ADC 读取函数以及位移处理函数
void ReadAdcValue(void)
{
/* Enable scan triggering from ELC events. */
(void) R_ADC_ScanStart(&g_adc0_ctrl);
scan_complete_flag = false;
while (!scan_complete_flag)
{
/* Wait for callback to set flag. */
}
err = R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_12, &adc_data1);
assert(FSP_SUCCESS == err);
a0=(double)(adc_data1/4095.0)*3.3;
/* printf(" ADC data=%d, voldata = %f\n",adc_data1,a0);*/
}
float Displace ;
void JudeLegth(void)
{
ReadAdcValue();
Displace = adc_data1/4095.0 *25.000 ;
printf("Displace = %f\n",Displace);
}
四:实物验证图如下所示:

如上图所示,这里我采用的是电阻式位移传感器,若采样其他类型的传感器,需要在硬件上面做一些处理。
串口接收数据如下所示:
用手推动位移传感器,可以看到位移数据从大到小变化,而且很稳定。当然我们也可以采用AD滤波的形式,对AD采样的数据进行一下处理。


全部评论