久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 34506|回復: 14
打印 上一主題 下一主題
收起左側

STM32如何通過內部VREF得到實際的VDDA值

  [復制鏈接]
跳轉到指定樓層
樓主
ID:94349 發表于 2015-11-10 15:06 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
我們經常會使用STM32 ADC功能測試外部電壓,在一些精度不高的場合,我們一般就用3.3V作為參考電壓來計算測到的電壓值。不過,這種情況很少見,可能只有單片機學習板才會這樣使用。因為我們使用的3.3V穩壓芯片,很少有標準的3.300V輸出,有可能是3.270V,也可能是3.345V,而且,還存在個體差異,這個板子上的電壓是3.294V,另外一個板子上面,就可能是3.312V。如果我們都用3.300來計算的話,同樣的電壓,測出來的結果就會存在mV級別的差異。
在實際使用中,我們一般使用外部基準電壓芯片,例如,100腳的STM32一般都有VREF引腳,就是用來接外部基準電壓芯片,例如REF3133,輸出的電壓是標準的3.300V。
為什么不用基準電壓芯片作為電源供電芯片?
因為基準電壓芯片的輸出電流都是小于25mA的,對于一般的電路板應用,這么點輸出電流不足以讓電路板工作。
不同的STM32 如何使用基準電壓芯片?
對于100腳及其以上的芯片,把基準電壓芯片連接到VREF芯片即可。
對于100腳以下的芯片,STM32沒有把VREF引腳引出來,所以,我們只能把基準電壓芯片連接到VDDA引腳。注意,STM32單片機上面有好多電源引腳,其中有若干VDD引腳,只有一個VDDA引腳,VDDA引腳就是模擬供電引腳。不過,需要注意,VDDA的電壓不是隨便定義的。例如,STM32F051系列單片機就規定,VDDA必須要大于或者等于VDD才可以正常工作,所以這時候,最好是給單片機3.0V供電,再給VDDA采用一個3.3V的基準電壓芯片供電。

不用電壓基準電壓芯片可以嗎?
如果在你的應用中,VDDA引腳和VDD引腳連在一起,都是由電源芯片供電,這時候,如果你能知道VDDA的實際電壓,也可以得到精確的ADC結果。例如,你可以用萬用表測到VDDA電壓,例如,是3.286V,你就可以使用3286來計算。不過,這也只能是在實驗的時候,在實際使用中,如果你做了1萬個板子,然后需要用萬用表量1萬個板子的電源電壓,然后再給每個板子修改程序,顯示是不可能的。
所以,STM32給我們又一個解決方案,STM32在內部都有一個參考電壓引腳,可以通過配置,把這個腳連接到ADC輸入引腳,是內部連接。然后再計算實際的VDDA值。不過,STM32也存在個體差異,所以,它并沒有在手冊上給出我們這個參考電壓是多大。而是用出廠時調教好的校準值和得到的參考電壓值一起使用。如下圖:

VREFINT_CAL是校準值,這個值,每個單片機都不一樣,被存儲到了0X1FFFF7BA和0X1FFFF7BB,使用的時候,需要先讀出來。
說多了都是眼淚,不說了,給你個程序看吧,程序當中,有讀取VREFINT_CAL和VREFINT_DATA值的語句。你可以看個究竟。這個程序已經實踐驗證過了,不會有問題,下面是實驗結果:

我把測到的VDDA值,發送到了串口查看。然后我用萬用表測了一下實際的VDDA值,由于我的萬用表精度有限,只能測到小數點后2位數字,萬用表得到的是3.32V和3.31V之間跳動。串口發送的值,小數點后第三位四舍五入之后,結果也是3.32V和3.31V。結果是一致的。說明這種方法也是可取的。
點擊下載源程序: stm32f051計算VDDA測試程序.7z (781.2 KB, 下載次數: 360) (程序使用KEIL 5)
                                       
                              
  1. /****************************************************/
  2. // 程序用途:用來測試通過內部基準電壓計算外部VDDA的值
  3. // 程序作者:孟瑞生
  4. // 微信公眾號:科技老頑童
  5. /****************************************************/
  6. #include "stm32f0xx.h"
  7. #include "stdio.h"

  8. __IO uint16_t VREFINT_CAL;
  9. __IO uint16_t VREFINT_DATA;
  10. __IO float VDDA_VAL;

  11. // 下面三個延時函數,是用示波器試出來的,非精確延時(48MHz)
  12. void delay_1us(void)
  13. {
  14.         volatile uint16_t i=1;
  15.         
  16.         while(i--);        
  17. }

  18. void delay_us(uint16_t us)
  19. {
  20.         while(us--)
  21.         {
  22.                 delay_1us();
  23.         }
  24. }

  25. void delay_ms(uint16_t ms)
  26. {
  27.         while(ms--)
  28.         {
  29.                 delay_us(995);
  30.         }
  31. }

  32. /**
  33.   * @brief  ADC Configuration
  34.   * @param  None
  35.   * @retval None
  36.   */
  37. static void ADC_Config(void)
  38. {
  39.   ADC_InitTypeDef     ADC_InitStructure;
  40.   GPIO_InitTypeDef    GPIO_InitStructure;
  41.   
  42.   /* GPIOC Periph clock enable */
  43.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  44.   
  45.   /* ADC1 Periph clock enable */
  46.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  47.   
  48.   /* Configure ADC Channel 0 as analog input */
  49.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  50.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  51.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  52.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  53.   
  54.   /* ADCs DeInit */  
  55.   ADC_DeInit(ADC1);
  56.   
  57.   /* Initialize ADC structure */
  58.   ADC_StructInit(&ADC_InitStructure);
  59.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  60.         ADC_Init(ADC1, &ADC_InitStructure);
  61.         
  62.         /* Convert the ADC1 Channel 0 with 239.5 Cycles as sampling time */
  63.   ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_239_5Cycles);
  64.         ADC_VrefintCmd(ENABLE);
  65.         
  66.   /* 得到基準電壓校準值 */
  67.         VREFINT_CAL = *(__IO uint16_t *)(0X1FFFF7BA);
  68.         
  69.         /* ADC Calibration */
  70.   ADC_GetCalibrationFactor(ADC1);
  71.         
  72.         /* Enable the ADC peripheral */
  73.   ADC_Cmd(ADC1, ENABLE);     
  74.   
  75.   /* Wait the ADRDY flag */
  76.   while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY));
  77.   
  78.   /* ADC1 regular Software Start Conv */
  79.   ADC_StartOfConversion(ADC1);
  80. }

  81. /**
  82.   * @brief  UART1 Configuration
  83.   * @param  None
  84.   * @retval None
  85.   */
  86. void UART1_Init()
  87. {
  88.         GPIO_InitTypeDef GPIO_InitStructure;
  89.         NVIC_InitTypeDef NVIC_InitStructure;
  90.         USART_InitTypeDef USART_InitStructure;
  91.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  92.         /* Enable USART1 Clock */
  93.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  94.         
  95.         /* USART1 Pins configuration ************************************************/
  96.   /* Connect pin to Periph */
  97.   GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
  98.   GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);   
  99.   
  100.   /* Configure pins as AF pushpull */
  101.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
  102.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  103.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  104.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  105.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  106.   GPIO_Init(GPIOA, &GPIO_InitStructure);

  107.         /* USART1 IRQ Channel configuration */
  108.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  109.   NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
  110.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  111.   NVIC_Init(&NVIC_InitStructure);        
  112.         
  113.         /* USART1  configured as follow:
  114.   - BaudRate = 9600 baud  
  115.   - Word Length = 8 Bits
  116.   - One Stop Bit
  117.   - No parity
  118.   - Hardware flow control disabled (RTS and CTS signals)
  119.   - Receive and transmit enabled
  120.   */
  121.   USART_InitStructure.USART_BaudRate = 115200;
  122.   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  123.   USART_InitStructure.USART_StopBits = USART_StopBits_1;
  124.   USART_InitStructure.USART_Parity = USART_Parity_No;
  125.   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  126.   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  127.         USART_Init(USART1, &USART_InitStructure);
  128.    
  129.         /* Enable the USART1 */
  130.         USART_Cmd(USART1, ENABLE);
  131. }

  132. int fputc(int ch, FILE *f)
  133. {
  134.         /* Place your implementation of fputc here */
  135.   /* e.g. write a character to the USART */
  136.   USART_SendData(USART1, (uint8_t) ch);

  137.   /* Loop until transmit data register is empty */
  138.   while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

  139.   return ch;
  140. }

  141. // 主函數
  142. int main(void)
  143. {
  144.         delay_ms(200);
  145.         ADC_Config();
  146.         UART1_Init();
  147.         
  148.         while(1)
  149.         {
  150.                 VREFINT_DATA =ADC_GetConversionValue(ADC1);
  151.                 VDDA_VAL = (3.3*VREFINT_CAL)/VREFINT_DATA;
  152.                 printf("\n\rVDDA:%.3fV\n\r",VDDA_VAL);
  153.                 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  154.                 delay_ms(1000);
  155.         }
  156. }

復制代碼

評分

參與人數 1黑幣 +3 收起 理由
yexiumywife + 3 很給力

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏7 分享淘帖 頂2 踩
回復

使用道具 舉報

來自 2#
ID:690448 發表于 2020-4-5 13:17 | 只看該作者
本帖最后由 my808 于 2020-4-8 21:43 編輯


謝謝樓主,按樓主的方法成了。
回復

使用道具 舉報

板凳
ID:121312 發表于 2016-5-16 22:38 | 只看該作者
本帖最后由 雷霆跳蚤 于 2016-5-16 22:39 編輯

樓主,我以前在讀資料的時候發現有這個功能,就是關于VERINT_CAL和VERINT_DATA這兩個值,但是一直都不知道這兩個值應該怎么取,讀了你的貼子才知道這兩個值在哪里,非常感謝你的分享,解決了困擾我很久的問題,以后可以用的上,但可惜看到的人不多。我很好奇的是,你怎么知道這兩個值是在0X1FFFF7BA和0X1FFFF7BB?在哪份文檔里有提到這兩個值的位置,能告之嗎?
回復

使用道具 舉報

地板
ID:169106 發表于 2017-3-8 14:00 | 只看該作者
請問如果ad原來是一個序列的轉換,現在要加vref校準。怎么加?
回復

使用道具 舉報

5#
ID:216746 發表于 2018-8-7 10:05 | 只看該作者
非常感謝樓主細致的講解,學習了,這就去試試!
回復

使用道具 舉報

6#
ID:370640 發表于 2018-11-10 12:15 | 只看該作者
感謝樓主, 測試一下
回復

使用道具 舉報

7#
ID:211788 發表于 2018-12-2 23:24 | 只看該作者
樓主,我今天用到STM32F030F4測量VDDA引腳電壓,我把VDDA引腳和VDD引腳共同接在+3.3V電源上。我把你的STM32F051源程序移植成STM32F040F4的程序,怎么測出來VDDA的電壓是1.228V啊?

stm32f051改成STM32F030計算VDDA等于1.228V測試程序.7z

782.16 KB, 下載次數: 29, 下載積分: 黑幣 -5

回復

使用道具 舉報

8#
ID:240600 發表于 2018-12-25 15:55 | 只看該作者
不知道對F103系列通用不
回復

使用道具 舉報

9#
ID:476548 發表于 2019-4-24 14:03 | 只看該作者
這兩個參數從哪個文檔找到的,為什么我找不到
回復

使用道具 舉報

10#
ID:214152 發表于 2019-5-6 10:45 | 只看該作者
感謝樓主, 測試一下
回復

使用道具 舉報

11#
ID:67222 發表于 2019-7-26 13:55 | 只看該作者
感謝樓主,下載測試下看有用沒。
回復

使用道具 舉報

12#
ID:397421 發表于 2020-1-3 14:45 | 只看該作者
非常感謝樓主,
回復

使用道具 舉報

13#
ID:247015 發表于 2020-3-29 16:18 | 只看該作者
謝謝分享  
回復

使用道具 舉報

14#
ID:800207 發表于 2020-7-9 10:03 | 只看該作者
小弟初來報到,看不到附件,嗚嗚
回復

使用道具 舉報

15#
ID:795009 發表于 2023-11-15 14:14 | 只看該作者
雷霆跳蚤 發表于 2016-5-16 22:38
樓主,我以前在讀資料的時候發現有這個功能,就是關于VERINT_CAL和VERINT_DATA這兩個值,但是一直都不知道 ...

數據手冊里直接搜有的
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国内自拍偷拍视频 | 97精品国产97久久久久久免费 | 91精品一区二区三区久久久久久 | 亚洲日本激情 | 欧美日韩精品区 | 成人久久网 | 精品一区二区三区四区 | 国产99精品 | 精品久久久久久久久久久久 | 国产精品久久国产精品 | 一级片在线播放 | 一区二区视频在线 | 婷婷99| 一区二区三区在线播放视频 | 激情一区二区三区 | 国产日韩欧美一区 | 午夜av电影 | 人人色视频 | 欧美性久久 | 亚洲视频免费在线看 | 天天操天天射综合网 | 亚洲第一女人av | 国产精品视频网站 | 一级毛毛片 | 不卡一区二区三区四区 | 免费黄色a视频 | 日本一二区视频 | 亚洲人成网站777色婷婷 | 欧美aaaaa| av一级久久 | 国产成人高清 | 亚洲欧美综合精品另类天天更新 | 日韩中文字幕 | 欧美日韩一本 | 国产乱码精品一区二区三区中文 | 久久精品视频12 | 精品国产乱码久久久久久1区2区 | 精品视频在线观看 | 欧美成人h版在线观看 | 日日夜夜视频 | 狠狠干天天干 |