嵌入式基本外设札记(一):ADC

一.ADC功能框图分析

在这里插入图片描述

1.①电压输入范围

ADC输入范围为VREF- ≤ VIN ≤ VREF+ ,由VREF-、VREF+、VDDA、VSSA四个外部引脚决定。
在设计原理图时一般把VSSA、VREF-接地,VDDA、VREF+接3V3,得到ADC的输入电压范围为0~3.3V。
如果想要让输入的电压范围变宽,可以测试负电压或更高的正电压,需要在外部添加一个电压调理电路,把需要转换的电压抬升或降压到0~3.3V就可以用ADC测量了。

2.②输入通道

STM32的ADC多达18个通道, 外部16个通道就是框图中的ADCx_IN0、ADCx_IN1…ADCx_IN5。分别对应着不同的IO口。
ADC1/2/3还有内部通道: 通道ADC1_IN16连接到芯片内部的温度传感器, 通道ADC1_IN17连接到内部参考电压VREFINT。
外部16个通道在转换的时候又分为规则通道和注入通道。其中规则通道最多16路,注入通道最多4路。平时一般使用的就是规则通道,注入通道则是在规则通道转换的时候强行插入的一种通道。在规则通道转换过程中有注入通道插队就要先转换完注入通道,等注入通道转换完成后再回到规则通道的转换流程。

3.③转换顺序

(1)规则序列

规则序列寄存器有3个,分别为SQR3、SQR2、SQR1。
在这里插入图片描述
SQR3控制着规则序列中的第一个到第六个转换,对应的位为:SQ1[4:0]~SQ6[4:0],如果通道16想第一次转换,那么在SQ1[4:0]写通道16即可。SQR1的位L[3:0]决定使用多少个通道,最多16个通道。

(2)注入序列

注入序列寄存器JSQR只有一个,最多支持4个通道,具体多少个由JSQR的JL[2:0]决定。如果JL的值小于4的话,则JSQR跟SQR决定转换顺序的设置不一样,第一次转换的不是JSQR1[4:0],而是JCQRx[4:0] ,x = (4-JL),跟SQR刚好相反。如果JL=00(1个转换),那么转换的顺序是从JSQR4[4:0]开始,而不是从JSQR1[4:0]开始。当JL等于4时,跟SQR一样。
在这里插入图片描述

4.④触发源

ADC转换可以由ADC控制寄存器2: ADC_CR2的ADON这个位来控制, 写1的时候开始转换,写0的时候停止转换。
ADC还支持外部事件触发转换,包括内部定时器触发和外部IO触发。具体选择哪一种触发源,由ADC控制寄存器2:ADC_CR2的EXTSEL[2:0]和JEXTSEL[2:0]位来控制。EXTSEL[2:0]用于选择规则通道的触发源,JEXTSEL[2:0]用于选择注入通道的触发源。选定的触发源是否要激活,则由ADC控制寄存器2:ADC_CR2的EXTTRIG和JEXTTRIG这两位来控制。
如果使能了外部触发事件还可以通过设置ADC控制寄存器2:ADC_CR2的EXTEN[1:0]和JEXTEN[1:0]来控制触发极性,有4种状态,分别是:禁止触发检测、上升沿检测、下降沿检测以及上升沿和下降沿均检测。

5.⑤转换时间

(1)ADC时钟

ADC输入时钟ADC_CLK由PCLK2经过分频产生,最大值是36MHz,典型值为30MHz,分频因子由ADC通用控制寄存器ADC_CCR的ADCPRE[1:0]设置, 可设置的分频系数有2、4、6和8,注意这里没有1分频。对于STM32F407ZGT6一般设置PCLK2=HCLK/2=84MHz。 所以程序一般使用4分频(21MHz)或者6分频(16MHz)。

(2)采样时间

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

ADC的总转换时间跟ADC的输入时钟和采样时间有关:
Tconv = 采样时间 + 12个周期
当ADCCLK = 30MHz,即PCLK2为60MHz,ADC时钟为2分频,采样时间设置为3个周期,那么总的转换时间为:Tconv = 3 + 12 = 15个周期 =0.5us。(取ADC输入时钟典型值)
一般设置PCLK2=84MHz,经过ADC预分频器能分频到最大的时钟只能是21M,采样周期设置为3个周期,算出最短的转换时间为0.7142us。

6.⑥数据寄存器

ADC转换后的数据,规则组的数据放在ADC_DR寄存器,注入组的数据放在ADC_JDRx寄存器。如果是使用双重或者三重模式,规矩组的数据是存放在通用规矩寄存器ADC_CDR内的。

(1)规则数据寄存器ADC_DR

ADC规则组数据寄存器ADC_DR只有一个,是32位寄存器仅低16位有效,只用于独立模式存放转换完成的数据。
ADC最大精度是12位,ADC_DR是16位有效,ADC存放数据时可以选择左对齐或右对齐,由ADC_CR2的11位ALIGN设置。
如果多通道转换,前一个时间点转换的通道数据会被下一个时间点的另外一个通道转换的数据覆盖掉。所以在通道转换完成后应该把数据及时取走,或者使用DMA模式把数据传输到存储器中。如果没有使用DMA传输一般需要使用ADC状态寄存器ADC_SR获取当前ADC转换的进度状态,从而进行程序控制。

(2)注入数据寄存器ADC_JDRx

ADC注入组最多有4个通道,注入数据寄存器也有4个,每个通道对应一个寄存器,不存在类似规则寄存器数据覆盖的问题。ADC_JDRx也是32位寄存器低16位有效,数据存放同样分为左对齐和右对齐,由ADC_CR2的11位ALIGN设置。

(3)通用规则数据寄存器ADC_CDR

规则数据寄存器ADC_DR仅适用于独立模式,通用数据寄存器ADC_CDR适用于双重、三重模式。独立模式就是仅适用于三个ADC使用其中一个,双重模式是同时使用ADC1和ADC2,三重模式是三个ADC同时使用。双重、三重模式一般需要配合DMA数据传输使用。

7.⑦中断

(1)转换结束中断

数据转换结束后,可以产生中断,中断分为四种:规则通道转换结束中断,注入转换通道转换结束中断,模拟看门狗中断和溢出中断。其中转换结束中断很好理解,有相应的中断标志位和中断使能位,可以根据中断类型写相应配套的中断服务程序。

(2)模拟看门狗中断

当被ADC转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是开启了模拟看门狗中断,其中低阈值和高阈值由ADC_LTR和ADC_HTR设置。例如设置高阈值是2.5V,那么模拟电压超过2.5V的时候,就会产生模拟看门狗中断,反之低阈值也一样。

(3)DMA溢出中断

如果发生DMA传输数据丢失,会置位ADC状态寄存器ADC_SR的OVR位,如果同时使能了溢出中断,在转换结束后会产生一个溢出中断。

(4)DMA请求

规则和注入通道转换结束后,除了产生中断外,还可以产生DMA请求,把转换好的数据直接存储在内存里面。要注意的是只有ADC1和ADC3可以产生DMA请求。

8.⑧电压转换

模拟电压经过ADC转换后,是一个12位的数字值,通过串口以16进制打印出来的话,可读性较差,需要把数字电压转换成模拟电压。
在设计原理图的时候会把ADC的输入电压范围设定在:0~3.3v,因为ADC是12位的,那么12位满量程对应的就是3.3V,12位满量程对应的数字值是:212。数值0对应的就是0V。如果转换后的数值为X ,X对应的模拟电压为Y,那么会有这么一个等式成立: 212 / 3.3 = X / Y,则 Y = (3.3 * X ) / 2^12。

二.ADC初始化结构体

1.ADC_HandleTypeDef结构体

typedef struct {
   ADC_TypeDef          *Instance; /*寄存器基地址指针*/
   ADC_InitTypeDef      Init; /*ADC初始化参数结构体*/
   __IO uint32_t        NbrOfCurrentConversionRank;//正在转换序列的ADC数目
   DMA_HandleTypeDef    *DMA_Handle; /* DMA处理程序指针 */
   HAL_LockTypeDef      Lock; /*ADC锁定对象 */
   __IO uint32_t        State; /*ADC通信状态*/
   __IO uint32_t        ErrorCode; /*ADC错误码 */
} ADC_HandleTypeDef;

2.ADC_InitTypeDef结构体

ADC_InitTypeDef初始化结构体被ADC_HandleTypeDef结构体引用。
typedef struct {
   uint32_t ClockPrescaler;        /*ADC时钟分频系数 */
   uint32_t Resolution;            /*ADC分辨率选择 */
   uint32_t DataAlign;             /*输出数据对齐方式 */
   uint32_t ScanConvMode;          /*扫描转换模式 */
   uint32_t EOCSelection;          /*转换结束标志使用轮询或者中断*/
   uint32_t ContinuousConvMode;    /*连续转换模式 */
   uint32_t NbrOfConversion;       /*规格转换序列数目 */
   uint32_t DiscontinuousConvMode; /*不连续采样模式 */
   uint32_t NbrOfDiscConversion;   /*不连续采样通道 */
   uint32_t ExternalTrigConv;      /*外部事件触发选择 */
   uint32_t ExternalTrigConvEdge;  /*外部事件触发极性 */
   uint32_t DMAContinuousRequests; /*DMA连续请求转换 */
} ADC_InitTypeDef;
(1)ADC_DataAlign

转换结果数据对齐模式,可选右对齐ADC_DataAlign_Right或者左对齐ADC_DataAlign_Left。一般选择右对齐模式。

(2)ScanConvMode

可选参数为ENABLE和DISABLE,配置是否使用扫描。如果是单通道AD转换使用DISABLE,如果是多通道AD转换使用ENABLE。

(3)EOCSelection

可选参数为ENABLE和DISABLE,指定EOC(转换结束)标志使用轮询或中断。

(4)ContinuousConvMode

可选参数为ENABLE和DISABLE,配置连续转换还是单次转换。使用ENABLE配置为使能自动连续转换;使用DISABLE配置为单次转换,转换一次后停止需要手动控制才重新启动转换。

(5)NbrOfConversion

AD规则转换通道数目。

(6)DiscontinuousConvMode

不连续采样模式。一般为禁止模式。

(7)NbrOfDiscConversion

ADC不连续转换通道数目。

(8)ExternalTrigConv

外部触发选择,可根据项目需求配置触发来源。实际上,一般使用软件自动触发。

(9)ExternalTrigConvEdge

外部触发极性选择,如果使用外部触发,可以选择触发的极性,可选有禁止触发检测、上升沿触发检测、下降沿触发检测以及上升沿和下降沿均可触发检测。

(10)DMAContinuousRequests

DMA请求连续转换,开启DMA传输时用到。

3.ADC_ChannelConfTypeDef结构体

typedef struct
{
  uint32_t Channel;                /*!< Specify the channel to configure into ADC regular group.
                                        This parameter can be a value of @ref ADC_HAL_EC_CHANNEL
                                        Note: Depending on devices and ADC instances, some channels may not be available on device package pins. Refer to device datasheet for channels availability. */

  uint32_t Rank;                   /*!< Specify the rank in the regular group sequencer.
                                        This parameter can be a value of @ref ADC_HAL_EC_REG_SEQ_RANKS
                                        Note: to disable a channel or change order of conversion sequencer, rank containing a previous channel setting can be overwritten by 
                                        the new channel setting (or parameter number of conversions adjusted) */

  uint32_t SamplingTime;           /*!< Sampling time value to be set for the selected channel.
                                        Unit: ADC clock cycles
                                        Conversion time is the addition of sampling time and processing time
                                        (12.5 ADC clock cycles at ADC resolution 12 bits, 10.5 cycles at 10 bits, 8.5 cycles at 8 bits, 6.5 cycles at 6 bits).
                                        This parameter can be a value of @ref ADC_HAL_EC_CHANNEL_SAMPLINGTIME
                                        Caution: This parameter applies to a channel that can be used into regular and/or injected group.
                                                 It overwrites the last setting.
                                        Note: In case of usage of internal measurement channels (VrefInt/Vbat/TempSensor),
                                              sampling time constraints must be respected (sampling time can be adjusted in function of ADC clock frequency and sampling time setting)
                                              Refer to device datasheet for timings values. */

  uint32_t SingleDiff;             /*!< Select single-ended or differential input.
                                        In differential mode: Differential measurement is carried out between the selected channel 'i' (positive input) and channel 'i+1' (negative input).
                                                              Only channel 'i' has to be configured, channel 'i+1' is configured automatically.
                                        This parameter must be a value of @ref ADC_HAL_EC_CHANNEL_SINGLE_DIFF_ENDING
                                        Caution: This parameter applies to a channel that can be used in a regular and/or injected group.
                                                 It overwrites the last setting.
                                        Note: Refer to Reference Manual to ensure the selected channel is available in differential mode.
                                        Note: When configuring a channel 'i' in differential mode, the channel 'i+1' is not usable separately.
                                        Note: This parameter must be modified when ADC is disabled (before ADC start conversion or after ADC stop conversion).
                                              If ADC is enabled, this parameter setting is bypassed without error reporting (as it can be the expected behavior in case 
                                        of another parameter update on the fly) */

  uint32_t OffsetNumber;           /*!< Select the offset number
                                        This parameter can be a value of @ref ADC_HAL_EC_OFFSET_NB
                                        Caution: Only one offset is allowed per channel. This parameter overwrites the last setting. */

  uint32_t Offset;                 /*!< Define the offset to be subtracted from the raw converted data.
                                        Offset value must be a positive number.
                                        Depending of ADC resolution selected (12, 10, 8 or 6 bits), this parameter must be a number between Min_Data = 0x000 and Max_Data = 0xFFF, 
                                        0x3FF, 0xFF or 0x3F respectively.
                                        Note: This parameter must be modified when no conversion is on going on both regular and injected groups (ADC disabled, or ADC enabled 
                                              without continuous mode or external trigger that could launch a conversion). */

}ADC_ChannelConfTypeDef;

Channel:ADC转换通道。
Rank:ADC序列数目
SamplingTime:ADC采样时间。

三.程序实现

1.独立模式单通道采集实验

编程要点

①IO配置
②模式配置
设置ADC的工作参数并初始化;
设置ADC工作时钟;
设置ADC转换通道顺序及采样时间;
③中断配置
配置使能ADC转换完成中断,在中断内读取转换完数据;

ADC转换结果数据使用中断方式读取,这里没有使用DMA进行数据传输。

static void Rheostat_ADC_GPIO_Config(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   // 使能 GPIO 时钟
   RHEOSTAT_ADC_GPIO_CLK_ENABLE();
   // 配置 IO
   GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN;
   GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;//模拟输入模式
   GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉
   HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);
}


static void Rheostat_ADC_Mode_Config(void)
{
   // 开启ADC时钟
   RHEOSTAT_ADC_CLK_ENABLE();
   // -------------------ADC Init 结构体 参数 初始化-----------------------
   // ADC1
   ADC_Handle.Instance = RHEOSTAT_ADC;
   // 时钟为fpclk 4分频
   ADC_Handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
   // ADC 分辨率
   ADC_Handle.Init.Resolution = ADC_RESOLUTION_12B;
   // 禁止扫描模式,多通道采集才需要
   ADC_Handle.Init.ScanConvMode = DISABLE;
   // 连续转换
   ADC_Handle.Init.ContinuousConvMode = ENABLE;
   // 非连续转换
   ADC_Handle.Init.DiscontinuousConvMode = DISABLE;
   // 非连续转换个数
   ADC_Handle.Init.NbrOfDiscConversion   = 0;
   //禁止外部边沿触发
   ADC_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
   //使用软件触发,外部触发不用配置,注释掉即可
   //ADC_Handle.Init.ExternalTrigConv      = ADC_EXTERNALTRIGCONV_T1_CC1;
   //数据右对齐
   ADC_Handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
   //转换通道 1个
   ADC_Handle.Init.NbrOfConversion = 1;
   //使能连续转换请求
   ADC_Handle.Init.DMAContinuousRequests = ENABLE;
   //转换完成标志
   ADC_Handle.Init.EOCSelection          = DISABLE;
   // 初始化ADC
   HAL_ADC_Init(&ADC_Handle);
   //-------------------------------------------------------------------
   ADC_Config.Channel      = RHEOSTAT_ADC_CHANNEL;
   ADC_Config.Rank         = 1;
   // 采样时间间隔
   ADC_Config.SamplingTime = ADC_SAMPLETIME_56CYCLES;
   ADC_Config.Offset       = 0;
   // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为56个ADC周期
   //采样周期选择:采样周期越短,ADC转换数据输出周期就越短但数据精度也越低,采样周期越长,ADC转换数据输出周期就越长同时数据精度越高。
   HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config);
   //使能ADC转换完成中断,并在中断服务函数中读取转换结果数据。
   HAL_ADC_Start_IT(&ADC_Handle);
}
// 配置中断优先级
static void Rheostat_ADC_NVIC_Config(void)
{
   HAL_NVIC_SetPriority(Rheostat_ADC_IRQ, 0, 0);
   HAL_NVIC_EnableIRQ(Rheostat_ADC_IRQ);
}
//ADC转换完成中断服务函数
void ADC_IRQHandler(void)
{
   HAL_ADC_IRQHandler(&ADC_Handle);
}
/**
* @brief  转换完成中断回调函数(非阻塞模式)
* @param  AdcHandle : ADC句柄
* @retval 无
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
   /* 获取结果 */
   ADC_ConvertedValue = HAL_ADC_GetValue(AdcHandle);
}

HAL_ADC_IRQHandler是HAL中自带的一个中断服务函数,处理过程中会指向一个回调函数给去添加用户代码,在ADC转换完成后就会进入中断服务函数,再进入回调函数,在回调函数内直接读取ADC转换结果保存在变量ADC_ConvertedValue中。

2.独立模式多通道采集实验

//ADC GPIO初始化
static void Rheostat_ADC_GPIO_Config(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   /*=====================通道1======================*/
   // 使能 GPIO 时钟
   RHEOSTAT_ADC_GPIO_CLK1_ENABLE();
   // 配置 IO
   GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN1;
   GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
   GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉
   HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT1, &GPIO_InitStructure);
   /*=====================通道2======================*/
   // 使能 GPIO 时钟
   RHEOSTAT_ADC_GPIO_CLK2_ENABLE();
   // 配置 IO
   GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN2;
   GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
   GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉
   HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT2, &GPIO_InitStructure);
   /*=====================通道3======================*/
   // 使能 GPIO 时钟
   RHEOSTAT_ADC_GPIO_CLK3_ENABLE();
   // 配置 IO
   GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN3;
   GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
   GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉
   HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT3, &GPIO_InitStructure);
}
//配置ADC工作模式、DMA工作模式
static void Rheostat_ADC_Mode_Config(void)
{
   // ------------------DMA Init 结构体参数 初始化-------------------------
   // ADC1使用DMA2,数据流0,通道0,这个是手册固定死的
   // 开启DMA时钟
   RHEOSTAT_ADC_DMA_CLK_ENABLE();
   // 数据传输通道
   DMA_Init_Handle.Instance = RHEOSTAT_ADC_DMA_STREAM;
   // 数据传输方向为外设到存储器
   DMA_Init_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
   // 外设寄存器只有一个,地址不用递增
   DMA_Init_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
   // 存储器地址固定
   DMA_Init_Handle.Init.MemInc = DMA_MINC_ENABLE;
   // // 外设数据大小为半字,即两个字节
   DMA_Init_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
   //  存储器数据大小也为半字,跟外设数据大小相同
   DMA_Init_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
   // 循环传输模式
   DMA_Init_Handle.Init.Mode = DMA_CIRCULAR;
   // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
   DMA_Init_Handle.Init.Priority = DMA_PRIORITY_HIGH;
   // 禁止DMA FIFO ,使用直连模式
   DMA_Init_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
   // FIFO 大小,FIFO模式禁止时,这个不用配置
   DMA_Init_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
   DMA_Init_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
   DMA_Init_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
   // 选择 DMA 通道,通道存在于流中
   DMA_Init_Handle.Init.Channel = RHEOSTAT_ADC_DMA_CHANNEL;
   //初始化DMA流,流相当于一个大的管道,管道里面有很多通道
   HAL_DMA_Init(&DMA_Init_Handle);
   HAL_DMA_Start (&DMA_Init_Handle,RHEOSTAT_ADC_DR_ADDR,
   (uint32_t)&ADC_ConvertedValue,RHEOSTAT_NOFCHANEL);
   // 开启ADC时钟
   RHEOSTAT_ADC_CLK_ENABLE();
   // -------------------ADC Init 结构体 参数 初始化-----------------------
   // ADC1
   ADC_Handle.Instance = RHEOSTAT_ADC;
   // 时钟为fpclk 4分频
   ADC_Handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
   // ADC 分辨率
   ADC_Handle.Init.Resolution = ADC_RESOLUTION_12B;
   // 扫描模式,多通道采集才需要
   ADC_Handle.Init.ScanConvMode = ENABLE;
   // 连续转换
   ADC_Handle.Init.ContinuousConvMode = ENABLE;
   // 非连续转换
   ADC_Handle.Init.DiscontinuousConvMode = DISABLE;
   // 非连续转换个数
   ADC_Handle.Init.NbrOfDiscConversion   = 0;
   //禁止外部边沿触发
   ADC_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
   //使用软件触发,外部触发不用配置,注释掉即可
   //ADC_Handle.Init.ExternalTrigConv      = ADC_EXTERNALTRIGCONV_T1_CC1;
   //数据右对齐
   ADC_Handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
   //转换通道个数
   ADC_Handle.Init.NbrOfConversion = RHEOSTAT_NOFCHANEL;
   //使能连续转换请求
   ADC_Handle.Init.DMAContinuousRequests = ENABLE;
   //转换完成标志
   ADC_Handle.Init.EOCSelection          = DISABLE;
   // 初始化ADC
   HAL_ADC_Init(&ADC_Handle);
   //-------------------------------------------------------------------
   // 配置 ADC 通道1转换顺序为1,第一个转换,采样时间为3个时钟周期
   ADC_Config.Channel      = RHEOSTAT_ADC_CHANNEL1;
   ADC_Config.Rank         = 1;
   ADC_Config.SamplingTime = ADC_SAMPLETIME_3CYCLES;// 采样时间间隔
   ADC_Config.Offset       = 0;
   HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config);
   // 配置 ADC 通道2转换顺序为2,第二个转换,采样时间为3个时钟周期
   ADC_Config.Channel      = RHEOSTAT_ADC_CHANNEL2;
   ADC_Config.Rank         = 2;
   ADC_Config.SamplingTime = ADC_SAMPLETIME_3CYCLES; // 采样时间间隔
   ADC_Config.Offset       = 0;
   HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config);
   // 配置 ADC 通道3转换顺序为3,第三个转换,采样时间为3个时钟周期
   ADC_Config.Channel      = RHEOSTAT_ADC_CHANNEL3;
   ADC_Config.Rank         = 3;
   ADC_Config.SamplingTime = ADC_SAMPLETIME_3CYCLES;// 采样时间间隔
   ADC_Config.Offset       = 0;
   HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config);
   HAL_ADC_Start_DMA(&ADC_Handle, (uint32_t*)&ADC_ConvertedValue,1);//使能ADC的DMA请求,控制ADC转换启动
}

设置外设基地址就是ADC的规则数据寄存器地址;存储器的地址就是我们指定的数据存储区空间,ADC_ConvertedValue是我们定义的一个全局数组名,它是一个无符号16位含有4个元素的整数数组;ADC规则转换对应只有一个数据寄存器所以地址不能递增,而我们定义的存储区是专门用来存放不同通道数据的,所以需要自动地址递增。ADC的规则数据寄存器只有低16位有效,实际存放的数据只有12位而已,所以设置数据大小为半字大小。ADC配置为连续转换模式DMA也设置为循环传输模式。设置好DMA相关参数后就使用HAL_DMA_Init函数初始化。

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值