你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32l051 adc怎么改cubemx配置都不准

[复制链接]
猎★奇士 提问时间:2018-2-8 09:20 /
本帖最后由 猎★奇士 于 2018-2-8 14:07 编辑

    l051c8t6通过adc测量芯片内部温度传感器和外部电池电压不准,电池电压本来是3.6V的,现在却有7V,温度也是230多℃,相似cubemx配置的ADC采样在stm32f103板子上没问题。而l0不断更改配置cubemx,连DMA都试了,还是错的!只有配置过采样模式电压降过3.8,但降实际电池电压(模拟的)改成3.5V,采集到的电压又升4.2V了,所以有什么可能原因和解决方法?
cubemx配置和测试工程我发上来,大家看看是我配置有问题还是芯片有问题,感激不尽。

关键代码:
  1. void MX_ADC_Init(void)
  2. {
  3.   ADC_ChannelConfTypeDef sConfig;

  4.   hadc.Instance = ADC1;
  5.   hadc.Init.OversamplingMode = DISABLE;
  6.   hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  7.   hadc.Init.Resolution = ADC_RESOLUTION_12B;
  8.   hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
  9.   hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  10.   hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  11.   hadc.Init.ContinuousConvMode = DISABLE;
  12.   hadc.Init.DiscontinuousConvMode = ENABLE;
  13.   hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  14.   hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  15.   hadc.Init.DMAContinuousRequests = DISABLE;
  16.   hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  17.   hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  18.   hadc.Init.LowPowerAutoWait = DISABLE;
  19.   hadc.Init.LowPowerFrequencyMode = DISABLE;
  20.   hadc.Init.LowPowerAutoPowerOff = DISABLE;
  21.   if (HAL_ADC_Init(&hadc) != HAL_OK)
  22.   {
  23.     Error_Handler();
  24.   }

  25.   sConfig.Channel = ADC_CHANNEL_9;
  26.   sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  27.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  28.   {
  29.     Error_Handler();
  30.   }

  31.   sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  32.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  33.   {
  34.     Error_Handler();
  35.   }
  36. }



  37. #define TEMP130_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007E))
  38. #define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007A))
  39. #define VDD_CALIB ((uint16_t) (300))
  40. #define VDD_APPLI ((uint16_t) (330))
  41. int32_t ComputeTemperature(uint32_t ADValue)
  42. {
  43.   int32_t temperature;
  44.   temperature = (((int32_t)(130 - 30)) * (ADValue - (int32_t)*TEMP30_CAL_ADDR)) / ((int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR));
  45.   temperature = temperature + 30;
  46.   return (temperature);
  47. }

  48. void ADC_GetValue()
  49. {
  50.         uint8_t i=0;
  51.         double VCC=3.3, BAT_VAL=0,CGVol_VAL=0,temperate=0;  
  52.         uint32_t VrefADvalue=0;
  53.         uint32_t temp=0,AD_Value_T=0,AD_Value_BAT=0;
  54.   
  55.         for(i=0;i<16;i++)                                                                  
  56.         {
  57.              HAL_ADC_Start(&hadc);                                                         
  58.              HAL_ADC_PollForConversion(&hadc, 50);                                          
  59.              if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc), HAL_ADC_STATE_REG_EOC))
  60.              {
  61.                  temp = HAL_ADC_GetValue(&hadc);
  62.               }
  63.               AD_Value_BAT+=temp;
  64.               //printf("Bat_ADC9=%d V",temp);
  65.       
  66.                HAL_ADC_Start(&hadc);                                                            
  67.                HAL_ADC_PollForConversion(&hadc, 50);                                            
  68.                if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc), HAL_ADC_STATE_REG_EOC))
  69.               {
  70.                   temp = HAL_ADC_GetValue(&hadc);
  71.               }
  72.               AD_Value_T+=temp;
  73.              //printf("Temperate=%d ¡æ",temp);
  74.               HAL_ADC_Stop(&hadc);   
  75.               HAL_Delay(100);     
  76.       }
  77.         AD_Value_T=AD_Value_T>>4;        
  78.         printf("AD_T%d \r\n",AD_Value_T);
  79.         AD_Value_BAT=AD_Value_BAT>>4;
  80.         printf("AD_V%d \r\n",AD_Value_BAT);
  81.   
  82.         //temperate=(float)AD_Value_T*(VCC/4096);                                                            
  83.         //temperate=( V30-temperate)/0.00161+30;                                   
  84.         temperate=ComputeTemperature(AD_Value_T);
  85.         printf("Temperate=%lf \r\n",temperate);
  86.    
  87.         BAT_VAL=VCC*4096/AD_Value_BAT;
  88.         printf("BAT_VAL=%lf V\r\n",BAT_VAL);     
  89. }
复制代码


test.zip

下载

543.84 KB, 下载次数: 30, 下载积分: ST金币 -1

评分

参与人数 1 ST金币 -5 收起 理由
Tcreat -5 连相关的电路也不配上 大神也是人 不是神~.

查看全部评分

收藏 评论15 发布时间:2018-2-8 09:20

举报

15个回答
dxx-381677 回答时间:2018-2-26 14:29:34
新年快乐。给朋友几个建议

1.L051  A/D的输入阻抗我记得跟速度是有关系的,速度越慢,输入阻抗越大。我看你分压电阻是兆欧级的,而输入阻抗估计只有50K欧左右,你快速的连续采集必然会使得电压不准;那么你采样的时候,全靠104电容放电维持AD的输入采集。你如果采集多次,每次采集的电压会越来越低。建议你2,3秒最好只采一次,不要连续采很多次取平均值。同理DMA也是行不通的。
关于STM32F1系列,AD的最大输入阻抗在300K欧左右,效果要好点,但依然存在这个问题。
2.关于内部的温度。同样的道理,我记得手册上有提到。切换到测量温度通道后,需要保持一段时间,让电平稳定,然后采集一次就可以了,否则采集的电压依然会越来越低。

更具体的数据,请参考芯片手册了。
猎★奇士 回答时间:2018-2-8 10:21:44
本帖最后由 猎★奇士 于 2018-2-8 10:23 编辑

电池分压图片已上传,上面写5V,但我接了直流电流源的3.6V,1A,也没别的ADC脚了,内部温度传感器也不对,还有我程序的温度公式用下图的公式可以吗
电池分压.png
计算公式.png
Tcreat 回答时间:2018-2-8 09:54:38
如果说怀疑IO口被烧坏了  可以换个AD口测试下 但是不要轻易的怀疑芯片本身有问题 另外你的电池电压都达到3V+了 ,电池AD采样这块应该有相关的分压电路 请问你配套的电路呢 社区的大神是很多 但是毕竟都是人 不是神

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

feixiang20 回答时间:2018-2-8 10:27:31
你可以先换个芯片看看结果是否仍旧,测试一下原来的芯片在资料中各个脚位数据是否正确,至于程序相信都是原版设计,你把你修改的地方重新检查, 还是建议一部分一部分的去检查。至于分压电路,你可以先计算理论上的数据,再测量实际的数据做对比,然后调节参数来检测问题。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

Tcreat 回答时间:2018-2-8 10:54:18
本帖最后由 Tcreat 于 2018-2-8 10:56 编辑

首先你的代码肯定是有问题的,你既不是多通道采样 也不是MDA采样 那么你for循环里采集的AD数值始终是你配置的最后一个通道的AD值(也就是temp的值,并没有采集电池电压的值),并不是你想象的那样 先采集电池电压,然后再采集TEMP的~
1.jpg
猎★奇士 回答时间:2018-2-8 11:19:19
本帖最后由 Tcreat 于 2018-2-8 11:41 编辑
Tcreat 发表于 2018-2-8 10:54
首先你的代码肯定是有问题的,你既不是多通道采样 也不是MDA采样 那么你for循环里采集的AD数值始终是你配置 ...

   谢谢版主的回复,但我配置的是多通道非DMA断续采集模式,每次启动采集只是采集一个通道,之前在f103c8t6上都能得到各自的值。然后刚才我又试了单独测试一个通道,结果还是一样的7.78多V,内部温度和外部电池电压都单独测了,电压AD值=1736左右,内部温度AD值=580左右其中一个测试函数:
  1. void ADC_GetValue()
  2. {
  3.    uint8_t i=0;
  4.    double VCC=3.3, BAT_VAL=0,CGVol_VAL=0,temperate=0;  
  5.    uint32_t VrefADvalue=0;
  6.    uint32_t temp=0,AD_Value_T=0,AD_Value_BAT=0;
  7.    HAL_ADC_Start(&hadc);                                                         
  8.    HAL_ADC_PollForConversion(&hadc, 50);                                          
  9.    if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc), HAL_ADC_STATE_REG_EOC))
  10.    {
  11.       temp = HAL_ADC_GetValue(&hadc);
  12.    }
  13.    AD_Value_BAT+=temp;
  14.    HAL_ADC_Stop(&hadc);
  15.    BAT_VAL=VCC*4096/AD_Value_BAT;
  16.    printf("BAT_VAL=%lf V\r\n",BAT_VAL);       //3.6V
复制代码


猎★奇士 回答时间:2018-2-8 11:21:22
其实DMA我也是试过的,得到的AD值也是一样,我现在也摸不着头脑,不知道哪里有问题,多余的板子目前也没有没法换着测。
Tcreat 回答时间:2018-2-8 11:41:26
猎★奇士 发表于 2018-2-8 11:19
谢谢版主的回复,但我配置的是多通道非DMA断续采集模式,每次启动采集只是采集一个通道,之前在f103c8t ...

电池AD 1736左右 根据你的电阻分压关系 得到的电压值 在3.8V 差别不是很大的呀
猎★奇士 回答时间:2018-2-8 12:00:28
Tcreat 发表于 2018-2-8 11:41
电池AD 1736左右 根据你的电阻分压关系 得到的电压值 在3.8V 差别不是很大的呀  ...

是这样的,我用过采样模式oversampling mode配置,得到电池电压AD=3470,根据我程序的计算公式得到的是3.89V,但关掉过采样,采集的电压AD就是1736,计算却得到7V+,肯定不对,难道是我计算公式错了?这是12bit采样时的计算式啊,基准电压就是VDD稳定=3.3V。
猎★奇士 回答时间:2018-2-8 12:03:02
还有内部温度按理说跟外部电路没关系,也不准就不知道怎么回事了,我温度的计算公式是根据l0完全手册上写的编的程序,不知道有没有用过l0内部温度传感器的大神说说,是不是像我这样配置、计算其温度
Tcreat 回答时间:2018-2-8 12:03:15
猎★奇士 发表于 2018-2-8 12:00
是这样的,我用过采样模式oversampling mode配置,得到电池电压AD=3470,根据我程序的计算公式得到的是3. ...

晕 3.3V 那就更对了 我用3.6V作为VDD计算得到3.8左右 如果3.3V结果在3.58V 所以没有问题 问题在于你计算有问题
猎★奇士 回答时间:2018-2-8 14:07:01
本帖最后由 猎★奇士 于 2018-2-8 14:10 编辑
Tcreat 发表于 2018-2-8 12:03
晕 3.3V 那就更对了 我用3.6V作为VDD计算得到3.8左右 如果3.3V结果在3.58V 所以没有问题 问题在于你计算 ...

版主你是对的,非常感谢版主您的帮助!我这是f103计算内部基准电压的计算公式,在f103测完直接就拿过来l0很自信的用,结果是取错公式了
我又看了内部温度传感器取值计算公式,用官方的例程测试了发现没问题,前面我列出来的程序不知道什么问题导致温度计算错了,我是因为没看懂官方代码,结果自己根据公式编的,结果哪里出错了,官方代码如下:
代码计算.png
中山无雪 回答时间:2018-2-8 19:26:09
猎★奇士 发表于 2018-2-8 12:00
是这样的,我用过采样模式oversampling mode配置,得到电池电压AD=3470,根据我程序的计算公式得到的是3. ...

再仔细看看转换计算代码
lydzzhx 回答时间:2018-4-23 00:32:58
我也在学习这款芯片 手头有现成的例程 一起分享吧 QQ:46439147
12下一页

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版