STM32F407ZGT6 ADC多通道采样

编程入门 行业动态 更新时间:2024-10-06 19:20:27

STM32F407ZGT6 ADC多<a href=https://www.elefans.com/category/jswz/34/1769997.html style=通道采样"/>

STM32F407ZGT6 ADC多通道采样

学习ADC多通道采样,参考野火的开发手册和代码

1.特点

  • 精度

    • 12/10/8/6
  • 通道

    • 16 个外部通道
    • 两个内部 ADC 源
    • Vbat( 在ADC1上 )
  • IO

    • A/B/C/F
  • MODE

    • 独立模式
    • 双重模式
    • 三重模式
  • 转换通道

    • 规则通道 16 个 (正常排队)
    • 注入通道 4 个 (插队)

2. 寄存器

2.1 规则序列寄存器

  • SQR3
    • 一个通道占 4 个位( 最多配置6个通道 )
    • 这个优先级比较高,所以是从这里开始算优先级
    • 如果想配置某个通道第一次转换,那么配置那个通道到这个寄存器的[4:0]位即可
  • SQR2
  • SQR1

2.2 注入序列寄存器( JSQR )

只有一个JSQR,最多支持4个通道,JL[2:0]决定。
注意:如果JL<=4,则JSQR跟SQR的转换顺序不一样,刚好是相反的。如果JL==4,那么还是跟SQR一样,从最低位开始。

寄存器功能取值
JSQ1[4:0]设置第1个转换的通道通道1~4
JSQ2[4:0]设置第2个转换的通道通道1~4
JSQ3[4:0]设置第3个转换的通道通道1~4
JSQ4[4:0]设置第4个转换的通道通道1~4
JL[1:0]需要转换多少个通道1~4

2.3 数据寄存器

2.3.1 规则数据寄存器ADC_DR
  • 只有一个
  • 32位
    • 低16位有效(用来存储数据)
    • 对齐
      • 左12位对齐
      • 右12位对齐
  • 由ADC_CR2 的11位ALIGN设置
  • 注意
    • 16 个 规则通道 公用一个 数据寄存器
    • 可能数据会被覆盖
    • 最好 采用 DMA 传输 或者 软件控制转换
  • 仅适用于独立模式
2.3.2 通用规则数据寄存器 ADC_CDR
  • 双重、三重模式下使用
  • 配合 DMA 数据传输
2.3.3 注入数据寄存器ADC_JDRx
  • 数据寄存器有 4 个
  • 32位
    • 配置跟上面同理

3. 使用

  • CR2开启

    • ADON 位
      • 1:启动 0:停止
    • 外部触发
      • 极性
        • 状态
          • 禁止触发检测
          • 上升沿检测
          • 下降沿检测
          • 上升、下降都检测
        • 配置
          • EXTEN[1:0]
          • JEXTEN[1:0]
      • EXTSEL[2:0]
        • 选择触发规则通道的触发源
        • 还需要配置 EXTIRIG (CR2) 才能激活
      • JEXTSEL[2:0]
        • 选择注入通道的触发源
        • 还需要配置 JEXTTRIG (CR2) 才能激活
  • 时钟配置

    • ADC_CCR (PCLK2)
      • 最大值为 36 Mhz
      • 典型值为 30 Mhz
      • 分屏系数2/4/6/8(常用的是4/6)
    • 采样时间
      • 最小配置采样周期是(采样时间) 3
      • ADC_SMPRx
        • x = 1
          • 控制通道10 ~ 17
        • x = 2
          • 控制通道 0 ~ 9
        • 通过配置 SMP[2:0]
      • 总采样时间
        • Tconv = 采样时间 + 12个周期(这是固定默认的)
  • 数据保存

    • 存储
      • 规则数据保存在ADC_DR
      • 注入数据保存在JDRx
      • 无论是双重或者是三重模式都是存储到ADC_CDR
  • 中断

    • 转换结束中断
      • 检测标志位即可(可触发中断)
    • 模拟看门狗中断
      • 模拟电压低于 低阈值 或 高于高阈值时会产生中断
    • 溢出中断
      • 数据丢失会置位 ADC_SR的OVR位,可触发溢出中断,会在转换结束后产生中断(记得先使能中断才会响应)
    • DAM 请求
      • 无论是规则还是注入转换接受后,除了产生中断外,还可以产生DMA请求,把数据存储到内存中。

4. 库函数

4.1 结构体

主要有两个结构体,一个是通用ADC结构体(模式、分屏系数、DMA/采样间隔)。另一个是配置是否连续转换、通道、外部触发、分辨率、数据对齐。

typedef struct{uint32_t ADC_Mode;               // ADC模式选择uint32_t ADC_Prescaler;         // ADC分频系数uint32_t ADC_DMAAccessMode;     // DMA模式配置(在独立模式无效)uint32_t ADC_TwoSamplingDelay;  //采样延迟(在独立模式无效)
}ADC_InitTypeDef;typedef struct{uint32_t ADC_Resolution;                //ADC分辨率选择FunctionalState ADC_ScanConvMode;       //ADC扫描模式(不扫描通道, 扫描通道)FunctionalState ADC_ContinuousConvMode; //ADC连续转换模式(只转换一次或者连续转换)uint32_t ADC_ExternalTrigConvEdge;      //ADC外部触发极性(禁止极性、上升沿、下降、两者沿)uint32_t ADC_ExternalTrigConv;          //ADC触发选择(外部触发、定时器触发、其他)uint32_t ADC_DataAlign;                 //输出数据对齐方式uint8_t ADC_NbrOfChannel;               //转换通道数目}ADC_InitTypeDef;

4.2 函数

注意
配置ADC通道转换顺序和采样周期是通过函数配置,而不是结构体。
ADC_RegularChannelConfig(ADCx,ch,顺序(就是谁先来),采样周期)

中断

ADC_IDConfig(ADCx, 寄存器中中断位(ADC_IT_EOC), ENABLE/DISABLE);使能中断

在中断中使用 ADC_GetITStatus来检测标志位,通过ADC_ClearITPendingBit来清除中断标志位。

获取转换数据

ADC_GetConversionValue(ADCx);
这个函数可以获取到转换的数据

DMA

使能DMA请求
ADC_DMARequestAfterLastTransfercmd(ADCx,ENABLE/DISABLE);

使能ADC DMA
ADC_DMACmd(ADCx,EANBLE/DISABLE);

5. 代码实现

1. bsp_dac.h

#ifndef __BSP_ADC_H
#define __BSP_ADC_H/***************************************************************** 头文件*/
#include "stm32f4xx.h"/***************************************************************** 宏定义*/
#define CHANEEL_NUM (3)/***************************************************************** 声明变量*/extern vu16 ConvVoltage[CHANEEL_NUM];   /*!< 通道数量    >*//***************************************************************** 函数声明*/
void ADC_ALLInit(void);#endif // !__BSP_ADC_H

2.bsp_dac.c

/*** @file bsp_dac.c* @brief DAC多通道测试* @author DFY (dfy1999@foxmail)* @version 1.0* @date 2020-08-06* * @copyright Copyright (c) 2020  DFY* * @par * <table>* <tr><th>Date       <th>Version <th>Author  <th>Description* <tr><td>2020-08-06 <td>1.0     <td>DFY     <td>创建文件* </table>*/
/***************************************************************** 头文件*/
#include "bsp_adc.h"/***************************************************************** 模块全局变量*/
/** 通道数据保存区  */
vu16 ConvVoltage[CHANEEL_NUM];/***************************************************************** 步骤* 1.配置GPIO*  1.1 引脚、模式* 2.配置DMA*  2.1 外设、内存(寄存器)、大小、方向、数量* 3.配置ADC*  3.1 模式(独立模式)分频(4分频21Mhz)*  3.2 分辨率(12)扫描模式(启动)连续转换(启动)外部触发及极性(不使用)数据对齐(右对齐)*  3.3 DMA请求使能、使能ADC DMA* 4.初始化外设***************************************************************//*** @brief 配置ADC的引脚初始化*/
static void ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;/** 使能时钟 */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/** 配置Pin_4,5,6   */GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;GPIO_Init(GPIOA, &GPIO_InitStructure);
}/*** @brief 配置ADC的DMA初始化*/
static void ADC_DMA_Config(void)
{DMA_InitTypeDef DMA_InitStructure;/*** 使用DMA2、数据流0、通道0*/RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);/*** @brief 应该还要检查当前流是否可以使用的,以后补充*///通道0DMA_InitStructure.DMA_Channel               = DMA_Channel_0;//外设到内存DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralToMemory;//数据量DMA_InitStructure.DMA_BufferSize            = CHANEEL_NUM;//循环模式DMA_InitStructure.DMA_Mode                  = DMA_Mode_Circular;//优先级为高DMA_InitStructure.DMA_Priority              = DMA_Priority_High;//外设地址DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)&ADC1->DR;//指针不递增DMA_InitStructure.DMA_PeripheralInc         = DMA_PeripheralInc_Disable;//数据大小为半字DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_HalfWord;//单次突发DMA_InitStructure.DMA_PeripheralBurst       = DMA_PeripheralBurst_Single;//内存地址DMA_InitStructure.DMA_Memory0BaseAddr       = (uint32_t)ConvVoltage;//指针递增DMA_InitStructure.DMA_MemoryInc             = DMA_MemoryInc_Enable;//数据大小为半字DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_HalfWord;//单次突发DMA_InitStructure.DMA_MemoryBurst           = DMA_MemoryBurst_Single;//禁止FIFO模式 参数可不配置DMA_InitStructure.DMA_FIFOMode              = DMA_FIFOMode_Disable;//由于禁止FIFO模式 参数可不配置DMA_InitStructure.DMA_FIFOThreshold         = DMA_FIFOThreshold_HalfFull;//初始化DMADMA_Init(DMA2_Stream0, &DMA_InitStructure);//使能DMA2 Stream0DMA_Cmd(DMA2_Stream0,ENABLE);
}/*** @brief ADC配置*/
static void ADC_Config(void)
{ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//独立模式ADC_CommonInitStructure.ADC_Mode                = ADC_Mode_Independent;//4分频(84/4 = 21Mhz)ADC_CommonInitStructure.ADC_Prescaler           = ADC_Prescaler_Div4;/** 下面这两个在独立模式中无效  */ADC_CommonInitStructure.ADC_DMAAccessMode       = ADC_DMAAccessMode_Disabled;ADC_CommonInitStructure.ADC_TwoSamplingDelay    = ADC_TwoSamplingDelay_11Cycles;ADC_CommonInit(&ADC_CommonInitStructure);ADC_StructInit(&ADC_InitStructure);//12位分辨率ADC_InitStructure.ADC_Resolution                = ADC_Resolution_12b;//通道扫描模式ADC_InitStructure.ADC_ScanConvMode              = ENABLE;//连续转换模式ADC_InitStructure.ADC_ContinuousConvMode        = ENABLE;//数据右对齐ADC_InitStructure.ADC_DataAlign                 = ADC_DataAlign_Right;//通道数量ADC_InitStructure.ADC_NbrOfConversion           = CHANEEL_NUM;/** 不使用外部触发,下面这两个无效 */   ADC_InitStructure.ADC_ExternalTrigConvEdge      = ADC_ExternalTrigConvEdge_None;ADC_InitStructure.ADC_ExternalTrigConv          = ADC_ExternalTrigConv_T1_CC1;ADC_Init(ADC1, &ADC_InitStructure);//配置通道4为第一个转换 采样周期是3ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_3Cycles);//配置通道5为第一个转换 采样周期是3ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_3Cycles);//配置通道6为第一个转换 采样周期是3ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 3, ADC_SampleTime_3Cycles);//允许DMA的请求ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE);//使能ADC DMAADC_DMACmd(ADC1, ENABLE);//使能ADC外设ADC_Cmd(ADC1, ENABLE);//软件触发 开始转换 后面就不用触发了 因为是连续转换ADC_SoftwareStartConv(ADC1);
}/*** @brief ADC初始化*/
void ADC_ALLInit(void)
{//初始化GPIOADC_GPIO_Config();//初始化DMAADC_DMA_Config();//初始化ADCADC_Config();
}
/****************************END**********************************/

3.main.c

	float channel_4,channel_5,channel_6;ADC_ALLInit();while(1){channel_4 = ConvVoltage[0] * (3.3/4096);channel_5 = ConvVoltage[1] * (3.3/4096);channel_6 = ConvVoltage[2] * (3.3/4096);printf("channel_4 = %fv	channel_5 = %fv	channel_6 = %fv\r\n\r\n",channel_4,channel_5,channel_6);delay_ms(400);}

更多推荐

STM32F407ZGT6 ADC多通道采样

本文发布于:2024-02-27 16:11:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1707302.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:通道   ADC

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!