前言

学习了之后才知道原来STM32F03自带的ADC功能还是挺强大的,10位ADC,一次可以扫描16个通道。还可以使用DMA来读取转换结果,最重要的是不用加ADC外设了。

ADC知识点

多的就不说了,手册上写的也是很详细的(不会真有人学习STM32不看手册把!不会吧!不会吧!不会吧!)

点这里下载手册   提取码:x49i

1.STM32F103有三个ADC外设分别是ADC.ADC2和ADC3

2.ADC一共有18个通道 其中:ADC1的模拟输入通道16和通道17在芯片内部分别连到了温度传感器和VREFINT。ADC2的模拟输入通道16和通道17在芯片内部连到了VSS。ADC3模拟输入通道9、14、15、16、17与Vss相连。其余的通道都是共用GPIO的。

3.ADC转换时有两种转换方式分组,分别是,规则转换组和注入转换组。转换时都是按照这两个分组进行的。我们正常使用的是规则转换,注入转换就相当于一个中断,在规则转换时,如果注入组被触发,就会先转换注入组里的通道,转换完成后接着转换规则组。也就是说注入组的转换优先级更高。

4.ADC各个通道的转换模式有:单次、连续、扫描或间断模式。规则组和注入组都可以设置成这四种模式。

单次模式:只执行单次转换.按规则组(或是注入组)里的转换顺序逐个通道转换一次直到最后一个通道转换完成后结束。软件触发只适用规则组,

连续模式:连续执行转换,和单次模式同理i,只是最后一个通道转换完成后不结束开始新的一轮转换。注入组是不会连续转换的,因为注入只是规则组的中途插入转换(中断),如果一直连续转换就没意义了。

扫描模式:打开扫描模式就是多通道转换,根据规则组(或是注入组)里规定的转换顺序进行转换,关闭扫描模式就是单通道转换,只转换规则组(或是注入组)里转换顺序为1的通道。

间断模式:把规则组(或是注入组)分成若干个子分组进行转换,子分组的通道数可以通过寄存器设置最多8个。注意注入组是不可以设置的,通道数只能为1,按注入组顺序逐个转换。

接下来看代码配置这里只用标准库代码为例

代码解析

打开ADC时钟:我这里只用到ADC1

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  //打开ADC1时钟

再打开用到的通道对应GPIO的时钟,然后配置GPIO为复用输入模式,比如配置通道5

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOA,&GPIO_InitStructure);

接下来配置ADC

 ADC1_InitStructure.ADC_Mode = ADC_Mode_Independent;     //ADC模式(是否启用双ADC模式) 使用独立模式ADC1_InitStructure.ADC_ScanConvMode = ENABLE;           //扫描模式(单通道与多通道) 使能扫描模式ADC1_InitStructure.ADC_ContinuousConvMode = ENABLE;    //连续模式(连续模式或是单次模式) 使能连续模式ADC1_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  //规则组触发启动转换方式 配置软件触发ADC1_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //转换结果数据对齐方式 右对齐ADC1_InitStructure.ADC_NbrOfChannel = 2;                //规则组通道数(范围1到16) 2个通道ADC_Init(ADC1, &ADC1_InitStructure);                    //设置参数

上面只是完成了一部分配置还不足以进行ADC转换,可以理解为通用配置,下面进行细节配置

要进行校准的话先配置

      ADC_StartCalibration(ADC1);                     //开始ADC1的校准程序while(ADC_GetCalibrationStatus(ADC1)!=SET);     //判断校准是否结完成

 配置规则组或是注入组转换顺序表 以内部温度传感器为例

 //规则组ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_55Cycles5);  //规则组序号2配置和设置采样时间 设置为通道17ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_55Cycles5);  //规则组序号1配置和设置采样时间 设置为通道16//注入组ADC_InjectedChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_55Cycles5);ADC_InjectedChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_55Cycles5);//还要配合ADC_InjectedSequencerLengthConfig(ADC1,2);  //设置注入组序列长度 范围1到4

DMA请求有需要就打开 随便使能内部CPU温度传感器

ADC_DMACmd(ADC1, ENABLE);                    //使能ADC使用DMA请求ADC_TempSensorVrefintCmd(ENABLE);            //使能内部温度传感器和内部参考电压

然后是启动规则或是注入转换,注入组是不可以单独启动的,我们一开始启动的是规则组,然后才可以通过外部触发或是自动在规则转换完成之后启动。

//这里以软件触发启动规则组
ADC_Cmd(ADC1, ENABLE);                       //ADC使能  ADC1使能一定要在启动之前
ADC_SoftwareStartConvCmd(ADC1, ENABLE);      //使能软件触发启动规则组转换
//软件启动注入组
ADC_Cmd(ADC1, ENABLE);
ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE);//外部触发启动大同小异 只是注入组在使能之前要调用外部触发启动配置函数 注意是配置函数不是使能函数
ADC_ExternalTrigConvCmd(ADC1,ENABLE);  //规则胡外部触发启动使能 配置在一开始的通用配置里设置的ADC_ExternalTrigInjectedConvConfig(ADC1,ADC_ExternalTrigInjecConv_T1_CC4); //配置注入组外部触发启动 这里只是举个例子
ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //使能注入组外部触发启动

下面看下ADC的中断,和配置串口中断的方法是一样的。这里要注意下:ADC1和ADC2的中断映射在同一个中断向量上,而ADC3的中断有自己的中断向量。意思是ADC1和ADC2共用同一个中断。规则和注入组转换结束时能产生中断,当模拟看门狗状态位被设置时也能产生中断。它们都有独立的中断使能位。中断源:

1.ADC_IT_EOC   规则组中断

2.ADC_IT_JEOC   注入组中断

3.ADC_IT_AWD   看门狗中断

 NVIC_InitTypeDef NVIC_InitStructure;     //定义中断初始化结构体变量ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);                         //使能ADC1中断并设置中断源ADC_ClearITPendingBit(ADC2, ADC_IT_EOC);                        //清除ADC ADC_IT_EOC中断标志NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;               //指定串口1的中断NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //使能串口1中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;       //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;              //中断优先级NVIC_Init(&NVIC_InitStructure);                                 //初始化中断NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);                 //中断优先级分组

接下来配置DMA: 外设地址就是ADC转换后的数据寄存器 DR,在标准库里为 ADC1->DR然后要把这个地址转换为32位的无符号类型。内存地址也是同理,可以定义一个16位的无符号数组,数组的元素个数可以是通道数。

 DMA1_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);   //设置外设地址DMA1_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Internal1;        //内存地址DMA1_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                  //设置传输方向 这里设置设置外设为传输来源DMA1_InitStructure.DMA_BufferSize = DMA_MemoryDataSize_HalfWord;     //设置指定DMA通道的缓存大小 这里设置16位半字DMA1_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    //外设地址是否递增 这里设置不递增DMA1_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;             //内存地址是否递增 这里设置递增DMA1_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度 16位DMA1_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存数据宽度 16位DMA1_InitStructure.DMA_Mode = DMA_Mode_Circular;                     //DMA工作模式 设置为循环模式DMA1_InitStructure.DMA_Priority = DMA_Priority_Low;                  //设置通道的软件优先级 这里设置低优先级DMA1_InitStructure.DMA_M2M = DMA_M2M_Disable;                        //DMA的内存到内存传输设置 这里选择不设置DMA_Init(DMA1_Channel1,&DMA1_InitStructure);                         //结构体初始化DMA_SetCurrDataCounter(DMA1_Channel1,2);                             //设置DMA1的通道1 传输数量DMA_Cmd(DMA1_Channel1,ENABLE);                                       //使能DMA1的通道1 因为ADC1和2的DMA请求在DMA1的通道1

这里看下具体配置,以规则转换后自动启动注入

用不到的地方我就注释了

  uint16_t Internal1[2]; //存放ADC的转换结果void Init_ADC1_IN17_IN18() {RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    //打开DMA1时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  //打开ADC1时钟ADC_InitTypeDef ADC1_InitStructure;      //ADC1初始化结构体DMA_InitTypeDef DMA1_InitStructure;      //DMA1初始化结构体NVIC_InitTypeDef NVIC_InitStructure;     //定义中断初始化结构体变量DMA1_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);   //设置外设地址DMA1_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Internal1;        //内存地址DMA1_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                  //设置传输方向 这里设置设置外设为传输来源DMA1_InitStructure.DMA_BufferSize = DMA_MemoryDataSize_HalfWord;     //设置指定DMA通道的缓存大小 这里设置16位半字DMA1_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    //外设地址是否递增 这里设置不递增DMA1_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;             //内存地址是否递增 这里设置递增DMA1_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度 16位DMA1_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存数据宽度 16位DMA1_InitStructure.DMA_Mode = DMA_Mode_Circular;                     //DMA工作模式 设置为循环模式DMA1_InitStructure.DMA_Priority = DMA_Priority_Low;                  //设置通道的软件优先级 这里设置低优先级DMA1_InitStructure.DMA_M2M = DMA_M2M_Disable;                        //DMA的内存到内存传输设置 这里选择不设置DMA_Init(DMA1_Channel1,&DMA1_InitStructure);                         //结构体初始化DMA_SetCurrDataCounter(DMA1_Channel1,2);                             //设置DMA1的通道1 传输数量DMA_Cmd(DMA1_Channel1,ENABLE);                                       //使能DMA1的通道1 因为ADC1和2的DMA请求在DMA1的通道1ADC1_InitStructure.ADC_Mode = ADC_Mode_Independent;     //ADC模式 使用独立模式ADC1_InitStructure.ADC_ScanConvMode = ENABLE;           //扫描模式 使能扫描模式ADC1_InitStructure.ADC_ContinuousConvMode = ENABLE;     //连续模式 使能连续模式ADC1_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  //触发启动转换方式 配置软件触发ADC1_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //转换结果数据对齐方式 右对齐ADC1_InitStructure.ADC_NbrOfChannel = 2;                //规则组通道数(范围1到16) 2个通道ADC_Init(ADC1, &ADC1_InitStructure);                    //设置参数ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);                         //使能ADC1中断并设置中断源ADC_ClearITPendingBit(ADC2, ADC_IT_EOC);                        //清除ADC ADC_IT_EOC中断标志NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;               //指定串口1的中断NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //使能串口1中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;       //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;              //中断优先级NVIC_Init(&NVIC_InitStructure);                                 //初始化中断NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);                 //中断优先级分组ADC_StartCalibration(ADC1);                     //开始ADC1的校准程序while(ADC_GetCalibrationStatus(ADC1)!=SET);     //判断校准是否结完成ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_55Cycles5);  //规则组序号2配置和设置采样时间 设置为通道17ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_55Cycles5);  //规则组序号1配置和设置采样时间 设置为通道16//ADC_DMACmd(ADC1, ENABLE);                  //使能ADC使用DMA请求 ADC_TempSensorVrefintCmd(ENABLE);          //使能内部温度传感器和内部参考电压//ADC_ExternalTrigConvCmd(ADC1,ENABLE);    //规则胡使能外部触发启动//ADC_AutoInjectedConvCmd(ADC1, ENABLE);   //规则转换后自动进行注入转换//ADC_ExternalTrigInjectedConvConfig(ADC1,ADC_ExternalTrigConv_None);            //注入组外部触发启动配置 //ADC_InjectedSequencerLengthConfig(ADC1,1);                                     //设置注入组序列长度//ADC_InjectedChannelConfig(ADC1, ADC_Channel_17, 1, ADC_SampleTime_55Cycles5);  //注入组转换顺序配置//ADC_InjectedChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_55Cycles5);  //注入组转换顺序配置ADC_Cmd(ADC1, ENABLE);                            //ADC使能ADC_SoftwareStartConvCmd(ADC1, ENABLE);           //使能软件触发启动规则组转换//ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE);  //软件触发启动注入组转换//ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE);  //使能注入组外部触发启动配置
}

最后就是获取ADC的转换结果了:如果采用DMA的话,用的时候直接读取数组里的值就可以了,可以理解为DMA自动帮我们赋值好了我们直接用就可以了。ADC1和ADC2的中断换数固定写法void ADC1_2_IRQHandler(void),使用中断要注意只有当规则组或者是注入组里的通道全部转换完成后才产生中断。使用一般使用ADC都是开启DMA传输。

void ADC1_2_IRQHandler(void){if(ADC_GetITStatus(ADC1, ADC_IT_EOC)==SET){   //检查中断标志是否置位Internal1[0]=ADC_GetConversionValue(ADC1);  //把转换结果存储到数组中}ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);    //清除中断标志
}

之后就是数据的换算了。

ADC配置到此结束  这只是我的笔记

STM32F03学习笔记之ADC配置(含DMA配置)相关推荐

  1. HTML学习笔记(二)(含vscode配置html_vscode安装方法及常用插件)

    hey,guys.我是poem23. 本篇文章会介绍Visual Studio Code的以及关于html的插件下载. vsCode是一款轻量级的HTML编码工具. 如果你只是想试试用HTML编译,这 ...

  2. CAS学习笔记五:SpringBoot自动/手动配置方式集成CAS单点登出

    本文目标 基于SpringBoot + Maven 分别使用自动配置与手动配置过滤器方式实现CAS客户端登出及单点登出. 本文基于<CAS学习笔记三:SpringBoot自动/手动配置方式集成C ...

  3. STM32F407霸天虎HAL库学习笔记——使用ADC采集MQ135的数据并通过OLED显示

    STM32F407霸天虎HAL库学习笔记--使用ADC采集MQ135的数据并通过OLED显示 一.软件准备 二.硬件准备 三.CubeMX配置 四.Keil MQ135.c MQ135.h main函 ...

  4. STM32 FSMC学习笔记+补充(LCD的FSMC配置)

    STM32 FSMC学习笔记+补充(LCD的FSMC配置) STM32 FSMC学习笔记 STM32 FSMC的用法--LCD 转载于:https://www.cnblogs.com/LittleTi ...

  5. Windows x64内核学习笔记(一)—— 环境与配置

    Windows x64内核学习笔记(一)-- 环境与配置 前言 新特性 基础要求 实验环境 Guest Win10配置 问题解决 参考资料 前言 之前,跟着海哥学习了windows内核的一些机制,包括 ...

  6. python数据挖掘学习笔记】十三.WordCloud词云配置过程及词频分析

    #2018-03-28 09:59:40 March Wednesday the 13 week, the 087 day SZ SSMR 11,12因为涉及到数据库被我暂时放弃了 python数据挖 ...

  7. adg oracle,【学习笔记】Oracle ADG搭建与配置 windows平台11G ADG搭建与测试

    [学习笔记]Oracle ADG搭建与配置 windows平台11G ADG搭建与测试 时间:2016-10-26 20:09   来源:Oracle研究中心   作者:HTZ   点击: 次 天萃荷 ...

  8. oracle rac 环境配置文件,学习笔记:Oracle RAC spfile参数文件配置案例详解

    天萃荷净 rac中的spfile探讨,记录一下Oracle RAC搭建完成后关于spfile参数文件的配置案例,与更改RAC环境中参数文件的方法 今天朋友的的rac,因为被同事做数据库升级,分别在两个 ...

  9. AutoGLuon学习笔记(一):环境配置与API初识

    AutoGLuon学习笔记(一):环境配置与API初识 环境配置 CUDA安装 Autogluon安装 图片分类 数据集导入和处理 拟合模型 预测新图片 测试集准确率 保存模型 超参数优化 模型范围设 ...

  10. Boost库学习笔记(一)安装与配置

    Boost库学习笔记(一)安装与配置 1. 获取boost https://www.boost.org/users/history/version_1_79_0.html 任选其一 boost的目录结 ...

最新文章

  1. STM32 基础系列教程 32 – Ethnet+Lwip
  2. druid seata 配置_五分钟带你了解Seata分布式事务
  3. 解决标签回车后产生的空格
  4. Linux环境搭建 手把手教你配置Linux虚拟机
  5. 34.scrapy解决爬虫翻页问题
  6. Android 11正式版发布!
  7. 200 行 C 代码实现插件式 NOSQL 存储服务器(一)
  8. Maven:浅析依赖(dependency)关系中 scope 的含义(转)
  9. NTLDR的故事:用途和常见故障分析方法
  10. 【排序算法】冒泡排序(C语言)
  11. 三、用python实现平稳时间序列的建模
  12. MC34063中文资料及应用实例(转)
  13. 叉乘应用:判断三角形方向正反/三个点顺时针逆时针
  14. AliOS Things 编译体系
  15. 【转】波利亚酒鬼回家定理的证明
  16. Sql 从一个表往另一个表里插数据
  17. 原来我是个自由主义者
  18. android:sharedUserId=android.uid.system 的使用
  19. 如何通过百度指数分析用户的真实需求?
  20. Android图库/相册,禁止扫描指定的图片目录

热门文章

  1. java会签_工作流引擎会签,加签,主持人,组长模式 专题讲解
  2. 交叉编译openssl
  3. 【攻防世界7-12题】题解和解题心得
  4. 18款最佳Bug跟踪管理系统
  5. Shiro反序列化漏洞检测及修复(工具分享)
  6. Indilinx主控固态量产成功修复步骤
  7. C#编写中英文虚拟键盘
  8. 阿拉伯数字转换成中文数字 C++
  9. 【通知】4月18日22:00至4月19日2:00网站服务暂停公告
  10. jQuery-放大镜