找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 33834|回复: 13
打印 上一主题 下一主题
收起左侧

STM32 ADC电压采集代码与原理讲解

  [复制链接]
跳转到指定楼层
楼主
秉火的STM32 ADC电压采集的资料:




电压输入范围
输入电压:VREF- ≤ VIN ≤ VREF+
决定输入电压的引脚:VREF-、 VREF+ 、 VDDA 、 VSSA
VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,
得到ADC 的输入电压范围为: 0~3.3V。

超出0~3.3V的电压怎么测?

ADC可以测量:-10V~10V  


根据基尔霍夫定律(KCL),节点流入的电流等于流出的电流
(Vint – Vout)/R2 + (3V3-Vout)/R1 = Vout / R3
Vout = (Vint + 10) /6  

R1 / R2 / R3 的值怎么确定?

每个ADC具有18个通道,其中外部通道16个


每个ADC具有18个通道,其中外部通道16个


外部的 16 个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有 16路,注入通道最多有 4 路。那这两个通道有什么区别?在什么时候使用?

规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道。
注入通道:注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。



1、软件触发:ADC_CR2 :ADON/SWST ART/JSWSTART
2、外部事件触发:内部定时器/外部IO
选择:ADC_CR2 :EXTSEL[2:0]和 JEXTSEL[2:0]
激活:ADC_CR2 :EXTEN 和 JEXTEN

ADC_CLK:ADC模拟电路时钟,最大值为14M,由PCLK2提供,还可分频,2/4/6/8,RCC_CFGR 的 ADCPRE[1:0]设置。PCLK2=72M。
转换时间:Tconv = 采样时间 + 12.5 个周期
数字时钟:RCC_APB2ENR,用于访问寄存器

采样时间:ADC 需要若干个 ADC_CLK 周期完成对输入的模拟量迚行采样,采样的周期数可通过ADC 采样时间寄存器
ADC_SMPR1 和 ADC_SMPR2 中的 SMPx[2:0]位设置,
ADC_SMPR2控制的是通道 0~9, ADC_SMPR1 控制的是通道 10~17。每个通道可以分别用不同的时间采样。其中采样周期最小是 1.5 个,即如果我们要达到最快的采样,那么应该设置采样周期为 31.5个周期,这里说的周期就是 1/ADC_CLK。

最短的转换时间:Tconv = 采样时间 + 12.5 个周期

PCLK2 = 72M,ADC_CLK = 72/6 = 12M
Tconv = 1.5+12.4 = 14周期 = 14/12us=1.17us

一切准备就绪后, ADC 转换后的数据根据转换组的不同,规则组的数据放在ADC_DR 寄存器,注入组的数据放在 JDRx。



1-16位有效,用于存放独立模式转换完成数据
2- ADC_CR2 :ALIGN
3-只有一个,多通道采集的是最好使用DMA



1-16位有效,用于存放注入通道转换完成数据
2- ADC_CR2 :ALIGN
3-有4个这样的寄存器



1-电压输入范围为:0~3.3V
2-分辨率为12位
3-最小精度为:3.3/2^12
4-设数字量为X,则有模拟量 Y = (3.3 / 2^12)*X
怎么根据数据量算出模拟量

单片机源程序如下:
  1. /**
  2.   ******************************************************************************
  3.   * @file    main.c
  4.   * @author  fire
  5.   * @version V1.0
  6.   * @date    2013-xx-xx
  7.   * @brief   串口中断接收测试

  8.   ******************************************************************************
  9.   */


  10. #include "stm32f10x.h"
  11. #include "bsp_usart.h"
  12. #include "bsp_adc.h"


  13. extern __IO uint16_t ADC_ConvertedValue[NOFCHANEL];

  14. // 局部变量,用于保存转换计算后的电压值         
  15. float ADC_ConvertedValueLocal[NOFCHANEL];        

  16. // 软件延时
  17. void Delay(__IO uint32_t nCount)
  18. {
  19.   for(; nCount != 0; nCount--);
  20. }

  21. /**
  22.   * @brief  主函数
  23.   * @param  无
  24.   * @retval 无
  25.   */
  26. int main(void)
  27. {        
  28.   /*初始化USART 配置模式为 115200 8-N-1,中断接收*/
  29.   USART_Config();
  30.         printf("欢迎使用秉火STM32开发板\n\n\n\n");
  31.         
  32.         ADCx_Init();

  33.         while (1)
  34.         {   
  35.                         ADC_ConvertedValueLocal[0] =(float) ADC_ConvertedValue[0]/4096*3.3;
  36.                         ADC_ConvertedValueLocal[1] =(float) ADC_ConvertedValue[1]/4096*3.3;
  37.                         ADC_ConvertedValueLocal[2] =(float) ADC_ConvertedValue[2]/4096*3.3;
  38.                         ADC_ConvertedValueLocal[3] =(float) ADC_ConvertedValue[3]/4096*3.3;
  39.                         ADC_ConvertedValueLocal[4] =(float) ADC_ConvertedValue[4]/4096*3.3;
  40.                         ADC_ConvertedValueLocal[5] =(float) ADC_ConvertedValue[5]/4096*3.3;
  41.                
  42.                         printf("\r\n CH0 value = %f V \r\n",ADC_ConvertedValueLocal[0]);
  43.                         printf("\r\n CH1 value = %f V \r\n",ADC_ConvertedValueLocal[1]);
  44.                         printf("\r\n CH2 value = %f V \r\n",ADC_ConvertedValueLocal[2]);
  45.                         printf("\r\n CH3 value = %f V \r\n",ADC_ConvertedValueLocal[3]);
  46.                         printf("\r\n CH4 value = %f V \r\n",ADC_ConvertedValueLocal[4]);
  47.                         printf("\r\n CH5 value = %f V \r\n",ADC_ConvertedValueLocal[5]);
  48.                
  49.                         printf("\r\n\r\n");
  50.                         Delay(0xffffee);                 
  51.         }
  52. }

  53. /*********************************************END OF FILE**********************/
复制代码

  1. #include "bsp_adc.h"

  2. __IO uint16_t ADC_ConvertedValue[NOFCHANEL]={0,0,0,0,0,0};

  3. static void ADCx_GPIO_Config(void)
  4. {
  5.         GPIO_InitTypeDef GPIO_InitStructure;
  6.         
  7.         // 打开 ADC IO端口时钟
  8.         ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
  9.         
  10.         // 配置 ADC IO 引脚模式
  11.         GPIO_InitStructure.GPIO_Pin = ADC_PIN1;
  12.         GPIO_InitStructure.GPIO_Pin = ADC_PIN2;
  13.         GPIO_InitStructure.GPIO_Pin = ADC_PIN3;
  14.         GPIO_InitStructure.GPIO_Pin = ADC_PIN4;
  15.         GPIO_InitStructure.GPIO_Pin = ADC_PIN5;
  16.         GPIO_InitStructure.GPIO_Pin = ADC_PIN6;
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  18.         
  19.         // 初始化 ADC IO
  20.         GPIO_Init(ADC_PORT, &GPIO_InitStructure);        
  21. }

  22. // ANSI C标准,C89 标准
  23. // C99
  24. // C11 2011

  25. static void ADCx_Mode_Config(void)
  26. {
  27.         DMA_InitTypeDef DMA_InitStructure;
  28.         RCC_AHBPeriphClockCmd(ADC_DMA_CLK, ENABLE);

  29.         DMA_DeInit(ADC_DMA_CHANNEL);
  30.         DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADC_x->DR ) );
  31.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue;
  32.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  33.         DMA_InitStructure.DMA_BufferSize = NOFCHANEL;    // 改
  34.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  35.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  // 改
  36.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  37.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  38.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
  39.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  40.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  41.         DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
  42.         DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);
  43. /*----------------------------------------------------------------------*/
  44.         
  45.         ADC_InitTypeDef ADC_InitStruct;        
  46.         ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
  47.         ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
  48.         ADC_InitStruct.ADC_ScanConvMode = ENABLE;        // 改
  49.         ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;        
  50.         ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  51.         ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
  52.         ADC_InitStruct.ADC_NbrOfChannel = NOFCHANEL;        
  53.         ADC_Init(ADC_x, &ADC_InitStruct);
  54.         
  55.         RCC_ADCCLKConfig(RCC_PCLK2_Div8);
  56.         
  57.         ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL1, 1, ADC_SampleTime_55Cycles5);
  58.         ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL2, 2, ADC_SampleTime_55Cycles5);
  59.         ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL3, 3, ADC_SampleTime_55Cycles5);
  60.         ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL4, 4, ADC_SampleTime_55Cycles5);
  61.         ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL5, 5, ADC_SampleTime_55Cycles5);
  62.         ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL6, 6, ADC_SampleTime_55Cycles5);

  63.          // 使能ADC DMA 请求
  64.         ADC_DMACmd(ADC_x, ENABLE);

  65.         ADC_Cmd(ADC_x, ENABLE);        
  66.   // ADC开始校准
  67.         ADC_StartCalibration(ADC_x);
  68.         // 等待校准完成
  69.         while(ADC_GetCalibrationStatus(ADC_x));
  70.         
  71.         ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
  72. }

  73. void ADCx_Init(void)
  74. {
  75.         ADCx_GPIO_Config();
  76.         ADCx_Mode_Config();
  77. }
复制代码

全部资料51hei下载地址:
31-ADC—电压采集.zip (6.15 MB, 下载次数: 516)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏14 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:524338 发表于 2019-4-29 11:56 | 只看该作者
感谢楼主
回复

使用道具 举报

板凳
ID:582442 发表于 2019-7-11 16:41 | 只看该作者
感谢分享
回复

使用道具 举报

地板
ID:593904 发表于 2019-8-2 07:12 | 只看该作者
打包视频教程
回复

使用道具 举报

5#
ID:160995 发表于 2019-8-3 01:17 | 只看该作者
感谢分享
回复

使用道具 举报

6#
ID:90212 发表于 2019-8-14 11:02 | 只看该作者
请教下楼主,我需要测0~60V电压。现在分压电阻只能用 (5.1k+5.1k)/470 ,不能用20K以上的电阻,否则测量15V以上就会出现明显不等比例的现象
回复

使用道具 举报

7#
ID:392569 发表于 2019-8-14 12:33 | 只看该作者
太详细了
回复

使用道具 举报

8#
ID:85865 发表于 2019-8-14 13:11 | 只看该作者
感谢分享
回复

使用道具 举报

9#
ID:603929 发表于 2019-9-27 14:53 | 只看该作者
感谢分享
回复

使用道具 举报

10#
ID:686610 发表于 2020-1-16 11:38 | 只看该作者
感谢楼主
回复

使用道具 举报

11#
ID:142383 发表于 2020-2-20 08:24 | 只看该作者
感谢楼主分享,下载学习学习!
回复

使用道具 举报

12#
ID:416535 发表于 2020-4-2 14:52 | 只看该作者
简直变态的详细,太详细了,感谢分享!
回复

使用道具 举报

13#
ID:146632 发表于 2021-3-19 15:16 | 只看该作者
extern __IO uint16_t ADC_ConvertedValue  为何报错
回复

使用道具 举报

14#
ID:64366 发表于 2021-3-27 14:49 | 只看该作者
感谢楼主  正在做相关的东西
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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