搜索
bottom↓
回复: 9

关于stm32的adc17内部参照电压的问题

[复制链接]

出0入0汤圆

发表于 2014-12-8 15:47:17 | 显示全部楼层 |阅读模式
之前用了一个64引脚封装的stm32做了一个ADC采集,后来发现没有提供参考电压,于是想用stm32的adc17通道采集stm32的内部1.2V的参照电压作为参考,对adc采样进行补偿。


  1. static void ADC1_GPIO_Config(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStructure;
  4.        
  5.         /* Enable DMA clock */
  6.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  7.        
  8.         /* Enable ADC1 and GPIOC clock */
  9.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
  10.        
  11.         /* Configure PC1  as analog input,voice */
  12.         /* Configure PC0  as analog input,power */
  13.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  14.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  15.         GPIO_Init(GPIOC, &GPIO_InitStructure);
  16. }

  17. void DMA_NVIC_Config(void)
  18. {
  19.         NVIC_InitTypeDef NVIC_InitStructure;
  20.        
  21.         /* Configure one bit for preemption priority */
  22.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  23.         /* Enable DMA channel1 IRQ Channel */
  24.         NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  25.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  26.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  27.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  28.         NVIC_Init(&NVIC_InitStructure);
  29. }

  30. static void ADC1_Mode_Config(void)
  31. {
  32.         DMA_InitTypeDef DMA_InitStructure;
  33.         ADC_InitTypeDef ADC_InitStructure;
  34.        
  35.         DMA_NVIC_Config();

  36.         /* DMA channel1 configuration */
  37.         DMA_DeInit(DMA1_Channel1);
  38.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  39.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&g_VOCSample;
  40.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  41.         DMA_InitStructure.DMA_BufferSize = VOC_SAMPLE_NUMBER;
  42.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  43.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  44.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  45.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  46.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  47.         DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
  48.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  49.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  50.        
  51.         /* Enable DMA channel1 */
  52.         DMA_Cmd(DMA1_Channel1, ENABLE);

  53.         DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);        //DMA通道1传输完成中断
  54.        
  55.         /* ADC1 configuration */
  56.         ADC_DeInit(ADC1);
  57.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  58.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  59.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  60.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  61.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  62.         ADC_InitStructure.ADC_NbrOfChannel = 2;
  63.         ADC_Init(ADC1, &ADC_InitStructure);

  64.         ADC_TempSensorVrefintCmd(ENABLE);
  65.        
  66.         /* ADC1 regular channel11 configuration */
  67.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5);
  68.         ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_239Cycles5);

  69.         /* Enable ADC1 DMA */
  70.         ADC_DMACmd(ADC1, ENABLE);
  71.        
  72.         /* Enable ADC1 */
  73.         ADC_Cmd(ADC1, ENABLE);
  74.        
  75.         /* Enable ADC1 reset calibaration register */   
  76.         ADC_ResetCalibration(ADC1);
  77.         /* Check the end of ADC1 reset calibration register */
  78.         while(ADC_GetResetCalibrationStatus(ADC1));
  79.        
  80.         /* Start ADC1 calibaration */
  81.         ADC_StartCalibration(ADC1);
  82.         /* Check the end of ADC1 calibration */
  83.         while(ADC_GetCalibrationStatus(ADC1));
  84.        
  85.         /* Start ADC1 Software Conversion */
  86.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  87. }
复制代码


整个代码如上,对ADC的GPIO,NVIC,DMA等都做了初始化设置,也使用了 ADC_TempSensorVrefintCmd(ENABLE) 语句打开stm32的内部参照电压。
但是我采样得到的内部参照电压数值为 1600 左右。而如果按照stm32数据手册所说,该1.2V参照电压的范围为 1.16~1.24V,那么采集出来的数值应该在 1440~1540 之内,不应该在 1600 左右。
请问,我的adc17通道采集的初始化正确吗?能不能用这种方法对外部adc采集进行一个补偿?

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2014-12-8 15:52:31 | 显示全部楼层
你采样1.2V的电压的ADC基准电压也是和其他AD一样的。所以不一定是1440和1540范围内,而且这个1.2V波动这么大,已经没有作为基准电压的必要了。如果很稳定的电压倒是可以一用。

出0入0汤圆

发表于 2014-12-8 15:57:54 | 显示全部楼层
官方应该会把在3V工作电压下测得参考电压的ADC结果的LSB存在一个固定的地址的,详细看一下手册。。。。。。

出0入0汤圆

 楼主| 发表于 2014-12-8 16:00:06 | 显示全部楼层
niaojingxin 发表于 2014-12-8 15:52
你采样1.2V的电压的ADC基准电压也是和其他AD一样的。所以不一定是1440和1540范围内,而且这个1.2V波动这么 ...

就是因为之前没有加外部的稳压作为一个参考电压,才想到用这个方法补救的。我是听别人说这个1.2V的内部参照电压波动不会太大,所以才想试一试。但我也不确定究竟他的波动有多大,如果像你所说的波动很大,那确实是没有使用这个1.2V电压的必要了

出0入0汤圆

 楼主| 发表于 2014-12-8 16:12:41 | 显示全部楼层
dzrs0620 发表于 2014-12-8 15:57
官方应该会把在3V工作电压下测得参考电压的ADC结果的LSB存在一个固定的地址的,详细看一下手册。。。。。。 ...

我只知道有一个电压检测器PVD用于检测电压是否过低,还不知道哪个寄存器有保存3.3V的工作电压的adc结果

出0入0汤圆

发表于 2014-12-8 16:22:00 | 显示全部楼层
内部1.2V的电压,其稳定性还可以,可以作为电压参考。
为了提高1.2V电压的准确性,可以采用外部的准确电压对其进行校准。
大部分情况下,1.2V电压在1.19V到1.21V之间波动,不同的MCU,其值略有不同。

出0入0汤圆

 楼主| 发表于 2014-12-8 18:08:10 | 显示全部楼层
wuzhujian 发表于 2014-12-8 16:22
内部1.2V的电压,其稳定性还可以,可以作为电压参考。
为了提高1.2V电压的准确性,可以采用外部的准确电压 ...

那我adc采样出来大概得到 1600 的值(相当于1.29V)这个属于正常范围吗?我试了很多块stm32的芯片都差不多

出0入0汤圆

发表于 2014-12-8 18:24:48 | 显示全部楼层
如果是3.0V电压的话,正常。
你量一下AVDD引脚的电压。

出0入0汤圆

 楼主| 发表于 2014-12-9 09:11:10 | 显示全部楼层
wuzhujian 发表于 2014-12-8 18:24
如果是3.0V电压的话,正常。
你量一下AVDD引脚的电压。

vdda的电压确实是3V,为什么不是3.3V的呢?

出0入0汤圆

 楼主| 发表于 2014-12-11 16:03:25 | 显示全部楼层
本帖最后由 Garlic 于 2014-12-11 16:16 编辑

今天我自己做了一个实验,大概能说明100脚以下封装的stm32芯片在没有使用外部参考电压的情况下,内部参照电压能够提高一定的adc精度。

实验内容如下:
1、使用一个外部参考电压芯片提供一个2.5V的参考电压,直接接入stm32进行adc采样,测出ad值的变化范围为3329~3347,有18个字的波动

2、使用内部参照电压来校正2.5V电压的采样,校正公式为:Voutput = Vinput * (1.2 / 3.07 * 4096)/ Vref 。其中Vinput是我采样2.5V电压的ad值,Vref是我采样的内部      1.2V参照电压的ad值,(1.2 / 3.07 * 4096)是内部1.2V参照电压的理论值。通过这个校正,2.5V电压的ad值变化范围为3315~3318,有3个字的波动,波动值相对降低了很多。

其中要注意的是,计算内部1.2V参照电压时,我使用了3.07V的满量程值,这是因为我量到stm32芯片的VDDA引脚的值为3.07V。按照stm32数据手册上说,100脚一下的封装,没有外部Vref引脚,Vref引脚是直接接到VDDA上面的,所以我引用这个值来作为adc的满量程电压进行计算。

至于这个VDDA电压为什么是3.07V,我还没弄清楚......
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-19 01:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表