ADC——电压采集

模拟技术

2414人已加入

描述

ADC——电压采集

25.1. ADC简介

ADC即模拟数字转换器,ADC英文全称(Analog-to-digital converter), 是一种用于将模拟电压的连续信号转换为离散的数字信号。 就比如我们可以将我们生活中的温度、压力、声音这样的模拟信号通过ADC转化为我们可以通过单片机处理的数字信号。

RA6M5 有2个ADC单元,每个ADC单元有12位、10位、8位读取数据的格式可以选择,在单元0上有13个ADC通道,而在单元1上有16个ADC通道。 ADC单元具有三种扫描方式分别为:单次描模式、连续扫描模式和分组扫描模式, 对于RA6M5来说ADC单元具有强大的功能,具体我们可以通过ADC特性和ADC的结构框图中分析每个部分的功能。

25.1.1. ADC特性

  1. 2 个ADC转换单元。
  2. 可以进行TrustZone安全设置。
  3. 支持内部温度检测,内部参考电压。
  4. 逐次逼近型ADC,支持的分辨率:12-bit, 10-bit, 8-bit。
  5. 转换时间短:0.4 μs/每通道(12-bit ADC、时钟PCLKC (ADCLK)等于50 MHz的条件下)。
  6. 可启用A/D 数据存储缓冲区是一个环形缓冲区,由16个缓冲区组成,用于顺序存储A/D转换后的数据。
  7. 自诊断在每次扫描开始时执行一次,在ADC执行生成中的三个参考电压值中选择一个A/D转换值。

25.2. ADC的结构框图

模拟数字转换器### 25.2.1. 电压输入范围

ADC输入范围为:VREFL- ≤ VIN ≤ VREFH+。 RA6M5的参考电压是由VREFL、VREFH 、AVCC0 、AVSS0 这四个外部引脚决定,且每个单元可以设置不同的参考电压,具体我们可以通过设置不同通道的VREFL、VREFH进行改变。

我们在设计原理图的时候一般把AVSS0和VREFL接地,把AVCC0和VREFH接3V3,得到ADC的输入电压范围为:0-3.3V。 如果我们想让输入的电压范围变宽,可以测试负电压或者更高的正电压,我们可以在外部加一个电压调理电路, 把需要转换的电压抬升或者降压到0~3.3V,这样ADC就可以测量了,为了测量的准确性我们还可以加上磁珠进行滤波。

25.2.2. 工作模式

在ADC单元0中有多达13个模拟输入通道,而在ADC单元1中有多达16个模拟输入通道以及内部的温度传感器输出, 两个ADC单元加起来总共就拥有了29个ADC通道,这么多的ADC通道我们该如何使用它们呢? 在这里我们就可以引入工作模式的概念, 我的单片机上的ADC处在什么样的工作模式进行ADC转换以及我们该如何进行设置。

模拟数字转换器

  1. 单次扫描模式:在单次扫描下,一次扫描一个或多个指定通道。
  2. 连续扫描模式:在连续扫描下,一个或多个指定的通道被重复扫描,直到软件设置寄存器ADCSR.ADST位为0。
  3. 分组扫描模式:将所选择的模拟输入通道上分为A组和b组,然后按组对所选择的模拟输入通道进行一次A/D转换。 A、B组可独立选择扫描启动条件,可独立启动A、B组的A/D转换。

在单次扫描模式下和在连续扫描模式下,都会从最小的扫描通道开始从低到高进行A/D转换。 如果开启了自诊断模式,在每次扫描开始时执行一次, 并转换三个参考电压中选择一个。 每一种转换都有着它的优点和缺点,但具体使用什么模式进行ADC转换,就需要通过我们的项目的需求需要什么样的效果来决定。

25.2.3. 转换过程顺序

有三种扫描转换模式分别为:单次扫描模式、连续扫描模式、组扫描模式。 在扫描中,A/D转换是按顺序对指定通道的模拟输入进行的。

单次扫描模式

在单次扫描模式转换期间,我们可以通过ADST为来判断ADC是否处在工作状态,在ADC转换的期间ADST为将一直保持为1,当所有选定通道的ADST转换完成时,将自动设置为0。 然后ADC将进入一个等待状态。

  1. 当ADCSR.ADST位通过软件触发器、同步触发器输入(ELC)和异步触发器输入被置1的时候,ADC转换开始。 对在ADANSA0和ADANSA1寄存器中选择的ANn通道进行A/D转换,从编号最小的n的通道开始。
  2. 每当单个信道的A/D转换完成时,A/D转换结果都被存储在关联的A/D数据寄存器(ADDRy)中。
  3. 当所有选定通道的A/D转换完成时,将生成一个ADC12i_ADI(i = 0,1)中断请求。

连续扫描模式

在连续扫描模式下,对指定信道的模拟输入重复执行A/D转换。 这里的ADCSR.ADST位不会自动清除,只要ADCSR.ADST位保持1时就会一直的重复步骤2、步骤3、步骤4,直到ADCSR.ADST位通过软件被置0时ADC单元转换才会停止,之后ADC单元进入等待状态。

  1. 当ADCSR.ADST位通过软件触发器、同步触发器输入(ELC)和异步触发器输入被置1的时候,ADC转换开始。 对在ADANSA0和ADANSA1寄存器中选择的ANn通道进行A/D转换,从编号最小的n的通道开始。
  2. 每当单个信道的A/D转换完成时,A/D转换结果都被存储在关联的A/D数据寄存器(ADDRy)中。
  3. 当所有选定通道的A/D转换完成时,将生成一个ADC12i_ADI(i = 0,1)中断请求。
  4. 对在ADANSA0和ADANSA1寄存器中选择的ANn通道进行A/D转换,从编号最小的n的通道开始。

组扫描模式

在群组扫描模式下,请选择A、B两组,分别选择A、B两组的开始扫描条件,并在不同的时间开始扫描。 另外我们还可以设置优先级,假设我们设置A组优先级高于B组优先级操作时,就可以在B组A/D转换时打断它, 使得A组进行A/D转换,而B组暂停A/D转换。

我们以ELC为列例子:使用GPT作为A组的触发源,并使用A组作为B组的触发源。

  1. 当ELC0上的GPT触发ELC_ADC(A组)时,A组的ADC开始转换。
  2. 当组A扫描完成时,将生成一个ADC12i_ADI(i = 0,1)中断。
  3. B组的扫描由ELC_ADC(A组)开始。
  4. 当B组扫描完成时,如果ADCSR.GBADIE位为1时将生成一个ADC12i_GBADI(i = 0,1)中断。

25.2.4. 触发源

通道选好了,工作模式也设置好了,那么接下来就需要设置我们的触发源了。 我们可以设置软件来触发ADC、或者通过使用ELC进行触发、甚至我们还可以使用外部中断进行触发。 最终我们的目的是为了使得ADCSR.ADST位被置1,以至于我们可以使用不同的方式进行触发。

下图为我们可以在FSP里选择的模式:

模拟数字转换器

25.2.5. ADC转换时间

25.2.5.1. ADC时钟

ADC输入时钟(转换时钟)ADCLK由PCLKC经过分频产生,最大值是四分频50MHz,ADC允许的最大值是50MHz,当我们使用50 MHz的时候12-bit转换时间为0.4 μs。 PCLKA 和 PCLKC (ADCLK) 的分频比可以设置为 1:1, 2:1, 4:1, 8:1, 1:2, 1:4。

25.2.5.2. 采样时间

模拟数字转换器扫描转换时间(tSCAN)包括:扫描开始时间(tD)、断开检测辅助处理时间(tDIS)*1、自诊断A/D转换处理时间(tDIAG和tDSD)*2、A/D转换处理时间(tCONV)、扫描结束时间(tED)。

A/D转换处理时间(tCONV)由输入采样时间(tSPL)和逐次逼近转换时间(tSAM)组成。 采样时间(tSPL)用于在A/D转换器中对采样和保持电路充电。 如果由于模拟输入信号源的高阻抗而没有足够的采样时间,或者如果A/ D转换时钟(ADCLK)很慢,可以使用ADSSTRn寄存器来调整采样时间。

由逐次逼近(tSAM)转换的时间如下

  • 12位精度需要13个ADCLK
  • 状态10位精度需要11个ADCLK
  • 状态8位精度需要9ADCLK

选择通道数为n的单次描模式下的扫描转换时间(tSCAN)可确定为:

模拟数字转换器连续扫描模式下第一个周期的扫描转换时间为单次扫描减去tED的tSCAN。 连续扫描模式下第二次及后续周期的扫描转换时间固定如下:

模拟数字转换器

25.2.6. 数据寄存器

在RA6M5的ADC中的数据寄存器有很多种,用来保存不同描模式下的数据 比如:ADDRn寄存器是16位只读寄存器(n=0~15),用来存储A/D转换结果、ADTSDR寄存器用来保存内部的温度传感器数据寄存器、 ADRD寄存器是用来自动诊断数据寄存器、ADOCDR寄存器是ADC内部参考电压数据寄存器。

我们还可以通过一些寄存器来设置数据的格式比如: ADC转换精度选择由ADCER.ADPRC[1:0]位设置(12位、10位、8位可选)、 ADC数据寄存器格式选择位ADCER.ADRFMT位设置(左对齐或右对齐)

25.2.7. 电压转换

模拟电压经过ADC转换后,是一个12位的数字值,如果通过串口以16进制打印出来的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟实际的模拟电压(用万用表测)对比,看看转换是否准确。

我们一般在设计原理图的时候会把ADC的输入电压范围设定在:0~3.3v,因为ADC是12位的,那么12位满量程对应的就是3.3V,12位满量程对应的数字值是:2^12。 数值0对应的就是0V。 如果转换后的数值为 X ,X对应的模拟电压为Y,那么会有这么一个等式成立: 2^12 / 3.3 = X / Y,=> Y = (3.3 * X ) / 2^12。

25.3. ADC程序设计

25.3.1. 硬件设计

模拟数字转换器ADC引脚 [](https://doc.embedfire.com/mcu/renesas/fsp_ra/zh/latest/doc/chapter25/chapter25.html#id22 "永久链接至表格")| ADC引脚 | P000 |
| ----------------- | ------ |

25.3.2. 软件设计

25.3.2.1. 新建工程

因为本章节的 ADC 相关实验例程需要用到板子上的串口功能,因此我们可以直接以前面的“19_UART_Receive_Send”工程为基础进行修改。

对于 e2 studio 开发环境:拷贝一份我们之前的 e2s 工程模板 “19_UART_Receive_Send” , 然后将工程文件夹重命名为 “25_ADC” ,最后再将它导入到我们的 e2 studio 工作空间中。

对于 Keil 开发环境:拷贝一份我们之前的 Keil 工程模板 “19_UART_Receive_Send” , 然后将工程文件夹重命名为 “25_ADC” ,并进入该文件夹里面双击 Keil 工程文件, 打开该工程。

25.3.2.2. FSP配置

我们先打开e2 studio软件里面的 Smart Configurator 配置FSP。

双击 configuration.xml 打开配置界面: 然后点开依次点击 Stacks -> New Stack -> Analog -> ADC(r_adc) 来配置ADC模块。

ADC页面的属性介绍

模拟数字转换器ADC 属性介绍 [](https://doc.embedfire.com/mcu/renesas/fsp_ra/zh/latest/doc/chapter25/chapter25.html#id23 "永久链接至表格")| ADC属性 | 描述 |
| - | - |
| ----------------------------- |

乌因特 指定要使用的ADC单元
再接 指定转换分辨率
对准 指定转换结果对齐方式
阅读后清除 读取转换结果后自动清除
模式 模式
双扳机装置 双触发
正常/A 组触发器 A的触发模式
回调 回调函数
扫描结束中断优先级 扫描完成中断优先级
模数转换器环形缓冲器 ADC环形缓冲区

配置完成之后可以按下快捷键“Ctrl + S”保存, 最后点右上角的 “Generate Project Content” 按钮,让软件自动生成配置代码即可。

25.3.2.3. ADC初始化

void adc_Init(void)
{
   fsp_err_t err;
   err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
   err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
   assert(FSP_SUCCESS == err);
}
  1. R_ADC_Open()为整个外设设置操作模式、触发源、中断优先级和配置。 如果启用了中断,该函数将注册一个回调函数指针,以便在扫描完成时通知用户。
  2. R_ADC_ScanCfg()配置ADC扫描参数。 通道特定设置是在这个函数中设置的。

25.3.2.4. ADC回调函数

volatile bool scan_complete_flag = false;
void adc_callback(adc_callback_args_t * p_args)
{
   FSP_PARAMETER_NOT_USED(p_args);
   scan_complete_flag = true;
}

在FSP配置页面注册回调函数以及优先级,我们就可以使用来自ADC的中断回调函数了。

注解

我们通过ADC的中断回调函数来判断ADC是否转换完成。 我们需要定义了一个布尔类型的数据scan_complete_flag来当做ADC读取完成的标志位。 当没有转换完成的时候scan_complete_flag的值一直为false,单ADC触发中断的时候将scan_complete_flag的值变为true。

25.3.2.5. 如果未启用中断

如果未启用中断,则可使用R_ADC_StatusGet() API 用于轮询 ADC 以确定扫描何时完成。 读取 API 函数用于访问转换后的 ADC 结果。 这适用于支持校准的MCU的普通扫描和校准扫描。

25.3.2.6. ADC读取转换后的数值

ADC读取思路,我们在这里调用R_ADC_ScanStart触发相应的adc通道转换,当ADC转换完成之后会将scan_complete_flag标志位变为true。 当我们判断到标志位变为true后我们使用R_ADC_Read()或R_ADC_Read32()读取转换完成的数值。

double adc_read(void)
{
   uint16_t adc_data;
   double a0;


   (void)R_ADC_ScanStart(&g_adc0_ctrl);
   scan_complete_flag = false;
   while (!scan_complete_flag)
   {
      ;
   }

   R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_0, &adc_data);
   a0 = (double)(adc_data*3.3/4095);
   return a0;
}
  1. R_ADC_ScanStart()启动软件扫描或启用扫描的硬件触发器,具体取决于触发器在R_ADC_Open调用中的配置方式。 如果该单元被配置为ELC或外部硬件触发,那么该功能允许触发信号到达ADC单元。 该函数不能控制触发器本身的生成。 如果该单元被配置为软件触发,则该功能启动软件触发扫描。
  2. R_ADC_Read()从单通道或传感器寄存器读取转换结果,返回的数据为uint16_t型。
  3. R_ADC_Read32()从单通道或传感器寄存器读取转换结果,返回的数据为uint32_t型。

25.3.2.7. hal_entry函数

void hal_entry(void)
{

   err = R_SCI_UART_Open(&g_uart4_ctrl, &g_uart4_cfg);
   printf("开始读取ADC的数值\\r\\n");
   adc_Init();


   while(1){
      printf("a0=%f\\r\\n",adc_read());
      R_BSP_SoftwareDelay(1000,BSP_DELAY_UNITS_MILLISECONDS); //大概1秒钟读取一次
   }



#if BSP_TZ_SECURE_BUILD
   /* Enter non-secure code */
   R_BSP_NonSecureEnter();
#endif
}

25.3.3. 下载验证

用USB线连接开发板“USB TO UART”接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板。 在串口调试助手可看到ADC引脚读出的模拟数值。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分