当前位置: 首页 > news >正文

STM32中的ADC

ADC的介绍

什么是ADC?

全称:Analog-to-Digital Converter,指模拟/数字转换器。

        ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。

  • 12 位 ADC 是一种 逐次逼近型模拟数字转换器(0~4095。它有多达 18 个通道,可测量 16 个外部和 2 内部信号源
  • 各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。
  • ADC 结果 可以 左对齐右对齐 方式存储在 16 位数据寄存器中
  • 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高 / 低阀值。
  • ADC 的输入时钟不得超过 14MHz,它是由 PCLK2 经分频产生。
  • STM32F103C8T6 ADC资源:ADC1ADC210 个外部输入通道(这个芯片中引出的引脚个数,最大有18个)。

ADC的工作原理(逐次逼近型)

说明:

  • 当输入模拟量时,控制与定时器会给逐次逼近寄存器发出指令,逐次逼近寄存器会产生数字信号,经过D/A转化器生成模拟信号,与输入的模拟量经过比较器进行比较。
  • 当产生的模拟量相比于输入的模拟量过大过小时,会反馈给逐次逼近寄存器,重新修正,当产生的模拟量与输入的模拟量近似相同时,逐次逼近寄存器中的数字量会转运到输出缓冲器中D0~D7的位置。

ADC的性能指标:(量程、分辨率、转化时间)

  • 量程:能测量的 电压范围 。
  • 分辨率:ADC能辨别的最小模拟量,通常以输出二进制数的位数表示,比如:8101216位等;位数越多,分辨率越高,一般来说分辨率越高,转化时间越长。
  • 转化时间(采样时间):从转换开始到获得稳定的数字量输出所需要的时间称为转换时间。转换时间越长,转换结果相对越准确,但是转换速度就越慢。

ADC特性:(供电电压、ADC输入范围、转化速度)

  • 12 位精度下转换速度可高达1MHZ
  • 供电电压:VSSA :0VVDDA :2.4V~3.6V
  • ADC输入范围:VREF- VIN VREF+0~3.3V。
  • ADC 的结果可以 左对齐 或 右对齐 方式存储在 16 位数据寄存器(低16位是ADC1的数据位,高16位是ADC2的数据位)中。

ADC的框图

  • 简图:

  • 参考手册上的框图: 

 ADC的输入通道

(16个外部通道和2个内部通道(温度传感器和内部参考电压)

其中16个通道在转化时又分成规则组通道(最多有16路)和注入组通道(最多有4路)

外部的16个通道在转换时又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4路。 

转化部分

规则组/注入组

解释:规则组和注入组-----(利用厂里员工检测零部件进行对比)

  • 规则组好比是待检测的零部件,最多有16个,工人进行依次按顺序进行检测;
  • 注入组好比是老板临时加入的紧急待测件,最多有4个,工人放下手中的规则组零部件,开始按顺序依次检测注入组的零部件,检测完成后,开始检测规则组的零部件。

转化顺序

  • 规则组的转化顺序

原因:每个 ADC 规则通道只有一个数据寄存器,16个通道一起共用这个寄存器,所以需要指定规则转换通道的转换顺序。

控制转化顺序的3个寄存器:SQR1、SQR2、SQR3(都是32位寄存器)

SQR 寄存器控制着转换通道的数目和转换顺序,只要在对应的寄存器位SQx 中写入相应的通道,这个通道就是第 x 个转换。
  • 注入组的转化顺序

和规则通道转换顺序的控制一样,注入通道的转换也是通过注入寄存器来控制,只不过只有1个JSQR寄存器来控制,控制关系如下:

        注入序列的转换顺序是从JSQx[ 4 : 0 ] x= 4- JL[1:0] 开始。
例:只有当  JL=4  的时候,注入通道的转换顺序才会按照 JSQ1 JSQ2 JSQ3 JSQ4 的顺序执行。

触发转化的方式 

方式1:软件触发

        通过向 控制寄存器 ADC-CR2 的 ADON 位写 1 来开启 ADC ,再将 SWSTART 位置 1 ,启动规则通道转换

方式2:外部事件(如定时器)触发

由寄存器 EXTSEL 中的 3位进行控制,所以,总共有2^3=8中触发方式。 

转化时间

转换时间 采样时间 + 12.5 个周期
补充:周期为ADC经PCLK2分频后得到的频率的倒数

周期: ADC 是挂载在 APB2 总线(PCLK2)上的,经过分频器得到 ADC 时钟(ADCCLK),最高 14 MHz。但是,在STM32F103C8T6芯片上的只能进行2/4/6/8分频,因此,最高 12 MHz。

采样时间(可以自己手动设置):共8种

举例:

  • 在STM32F103C8T6开发板中,最少的转化时间: 采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us
  • 若其他芯片中,周期为14MHz的倒数,最低采样时间是1us。

 单次转换和连续转换

  • 单次转换:只转换一次。
  • 连续转换:转换一次之后,立马进行下一次转换。

扫描模式 

  • 关闭扫描模式:只转换 ADC_SQRx 或 ADC_JSQR 选中的第一个通道。
  • 打开扫描模式:扫描所有被 ADC_SQRx 或 ADC_JSQR 选中的所有通道。

输出部分 (中断及事件)

  • DMA请求(只适用于规则组:只有一个数据寄存器,防止数据进行覆盖) 

        规则组每个通道转换结束后,除了可以产生中断外,还可以产生DMA请求,我们利用DMA及时把转换好的数据传输到指定的内存里,防止数据被覆盖。

校准

  • ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。
  • 通过设置ADC_CR2寄存器的CAL位启动校准。一旦校准结束, CAL位被硬件复位,可以开始正常转换。建议在上电时执行一次ADC校准。校准阶段结束后,校准码储存在ADC_DR中。
  • 建议在每次上电后执行一次校准。

ADC的寄存器

ADC状态寄存器(ADC_SR)

ADC控制寄存器 1(ADC_CR1)

 ADC控制寄存器 2(ADC_CR2)

ADC采样时间寄存器 1(ADC_SMPR1)

 ADC采样时间寄存器 2(ADC_SMPR2)

ADC看门狗高阀值寄存器(ADC_HTR) 

ADC看门狗低阀值寄存器(ADC_LRT)

 ADC规则序列寄存器 1(ADC_SQR1)

ADC规则序列寄存器 2(ADC_SQR2)

ADC规则序列寄存器 3(ADC_SQR3)

ADC注入序列寄存器(ADC_JSQR)

ADC 注入数据寄存器x (ADC_JDRx) (x= 1..4) 

ADC规则数据寄存器(ADC_DR) 

ADC的库函数

  • stm32f1xx_hal_adc.c

  • stm32f1xx_hal_adc_ex.c 

小实验1:ADC单通道采集实验

实验目的

使用ADC1采集单通道1的电压值,通道1接光敏电阻传感器。

硬件清单

开发板、光敏传感器、ST-Link、USB转TTL

配置代码流程 

文件代码 

  • adc.c文件代码 
#include "adc.h"ADC_HandleTypeDef adc_handle = {0}; 
void adc_init(void){adc_handle.Instance = ADC1;adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                    /* 数据对齐:常用右对齐 */adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;                    /* 需不需扫描:这里只有一个通道,不扫描 */adc_handle.Init.ContinuousConvMode = DISABLE;                       /* 连续转化 */adc_handle.Init.NbrOfConversion = 1;                                /* 转化的个数 */adc_handle.Init.DiscontinuousConvMode = DISABLE;                    /* 间断模式 */adc_handle.Init.NbrOfDiscConversion = 0;                            /* 间断的个数 */adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;              /* 触发模式的选择:软件触发 */HAL_ADC_Init(&adc_handle);HAL_ADCEx_Calibration_Start(&adc_handle);                           /* ADC的校准 */
}void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc){if(hadc->Instance == ADC1){RCC_PeriphCLKInitTypeDef  adc_clk_init = {0};__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;          /* 外设时钟的选择 */adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;             /* ADC的预分频:这里6分频,12MHz */HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                       /* 由于ADC转化的时钟是12MHz,要进行改变,进行预分频 */GPIO_InitTypeDef gpio_initstruct;gpio_initstruct.Pin = GPIO_PIN_1;gpio_initstruct.Mode = GPIO_MODE_ANALOG;gpio_initstruct.Pull = GPIO_PULLUP;gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA,&gpio_initstruct);}
}/**
* @breif    封装一个配置ADC通道的函数。
* @param    配置的ADC1,通道,通道序列,采样时间
* @retval   无
*/void adc_channel_config(ADC_HandleTypeDef* hadc,uint32_t ch,uint32_t rank,uint32_t stime){ADC_ChannelConfTypeDef adc_ch_config = {0};adc_ch_config.Channel = ch;                                     /* 选择配置的通道 */adc_ch_config.Rank = rank;                                      /* 通道的优先级,序列 */adc_ch_config.SamplingTime = stime;                             /* 通道的采样时间 */HAL_ADC_ConfigChannel(&adc_handle,&adc_ch_config);
}/**
* @breif    封装一个获取DR寄存器值得函数
* @note     配置的流程:配置通道,打开ADC,阻塞函数等待转化完成,获取DR寄存器数据的值,(uint16_t)将数据强转为十进制数。
* @param    通道,uint32_t ch
* @retval   获取的DR寄存器中的数值
*/
uint32_t adc_get_result(uint32_t ch){adc_channel_config(&adc_handle,ch,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_239CYCLES_5);       /* 通道的配置 */HAL_ADC_Start(&adc_handle);                                    /* 打开ADC */HAL_ADC_PollForConversion(&adc_handle,10);                     /* 等待转化完成,超时时间:10ms*/return (uint16_t)HAL_ADC_GetValue(&adc_handle);/* ADC1转化的结果放在DR寄存器的低16位,这里强转为uint16_t就可以直接获取。DR寄存器的高16位存放的是ADC2转化的结果。 */}
  • adc.h文件代码 
#ifndef __ADC_H__
#define __ADC_H__#include "stm32f1xx.h"void adc_init(void);
uint32_t adc_get_result(uint32_t ch);#endif
  • mian.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "adc.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* LED初始化 */uart1_init(115200);printf("hello,world");adc_init();while(1){ printf("adc:result:%f v\r\n",(float)adc_get_result(ADC_CHANNEL_1) / 4096 * 3.3);delay_ms(500);}
}

总结: (代码流程图)

  1. 初始化ADC的函数;
  2. 初始化Msp的函数;
  3. 配置ADC的通道;
  4. 封装一个函数,取出DR寄存器中的数值。

注意:在HAL_DMA_MspInit( )函数中,要对ADC的时钟进行分频,一般采用的分频系数是6分频。调用的函数如下:

 小实验2:ADC单通道采集实验+DMA读取

 实验目的

使用ADC1采集通道1的电压值+DMA读取,通道1连接光敏传感器。

硬件清单

开发板、ST-Link、光敏电阻传感器、USB转TTL 

配置流程 

文件代码

  • adc.c文件代码 
#include "adc.h"ADC_HandleTypeDef adc_handle = {0}; 
void adc_config(void){adc_handle.Instance = ADC1;adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                    /* 数据对齐:常用右对齐 */adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;                    /* 需不需扫描:这里只有一个通道,不扫描 */adc_handle.Init.ContinuousConvMode = ENABLE;                       /* 连续转化 */adc_handle.Init.NbrOfConversion = 1;                                /* 转化的个数 */adc_handle.Init.DiscontinuousConvMode = DISABLE;                    /* 间断模式 */adc_handle.Init.NbrOfDiscConversion = 0;                            /* 间断的个数 */adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;              /* 触发模式的选择:软件触发 */HAL_ADC_Init(&adc_handle);HAL_ADCEx_Calibration_Start(&adc_handle);                           /* ADC的校准 */
}DMA_HandleTypeDef dma_handle = {0};
void dma_config(void){__HAL_RCC_DMA1_CLK_ENABLE();dma_handle.Instance = DMA1_Channel1;dma_handle.Init.Direction  = DMA_PERIPH_TO_MEMORY;dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;  /*ADC的DR寄存器是16,传输的数据是半字符。*/dma_handle.Init.MemInc = DMA_MINC_ENABLE;dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;dma_handle.Init.PeriphInc = DMA_PINC_ENABLE;dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;dma_handle.Init.Mode = DMA_CIRCULAR;__HAL_LINKDMA(&adc_handle,DMA_Handle,dma_handle);HAL_DMA_Init(&dma_handle);
}void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc){if(hadc->Instance == ADC1){RCC_PeriphCLKInitTypeDef  adc_clk_init = {0};__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;          /* 外设时钟的选择 */adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;             /* ADC的预分频:这里6分频,12MHz */HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                       /* 由于ADC转化的时钟是12MHz,要进行改变,进行预分频 */GPIO_InitTypeDef gpio_initstruct;gpio_initstruct.Pin = GPIO_PIN_1;gpio_initstruct.Mode = GPIO_MODE_ANALOG;gpio_initstruct.Pull = GPIO_PULLUP;gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA,&gpio_initstruct); }
}/**
* @breif    封装一个配置ADC通道的函数。
* @param    配置的ADC1,通道,通道序列,采样时间
* @retval   无
*/void adc_channel_config(ADC_HandleTypeDef* hadc,uint32_t ch,uint32_t rank,uint32_t stime){ADC_ChannelConfTypeDef adc_ch_config = {0};adc_ch_config.Channel = ch;                                     /* 选择配置的通道 */adc_ch_config.Rank = rank;                                      /* 通道的优先级,序列 */adc_ch_config.SamplingTime = stime;                             /* 通道的采样时间 */HAL_ADC_ConfigChannel(&adc_handle,&adc_ch_config);
}/**
* @breif    封装一个获取DR寄存器值得函数
* @note     配置的流程:配置通道,打开ADC,阻塞函数等待转化完成,获取DR寄存器数据的值,(uint16_t)将数据强转为十进制数。
* @param    通道,uint32_t ch
* @retval   获取的DR寄存器中的数值
*/
uint32_t adc_get_result(uint32_t ch){adc_channel_config(&adc_handle,ch,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_239CYCLES_5);       /* 通道的配置 */HAL_ADC_Start(&adc_handle);                                    /* 打开ADC */HAL_ADC_PollForConversion(&adc_handle,10);                     /* 等待转化完成,超时时间:10ms*/return (uint16_t)HAL_ADC_GetValue(&adc_handle);/* ADC1转化的结果放在DR寄存器的低16位,这里强转为uint16_t就可以直接获取。DR寄存器的高16位存放的是ADC2转化的结果。 */}void adc_dma_init(uint32_t *mar){adc_config();adc_channel_config(&adc_handle,ADC_CHANNEL_1,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_239CYCLES_5);dma_config();HAL_ADC_Start_DMA(&adc_handle,mar,1);          /* Length: The length of data to be transferred from ADC peripheral to memory.  转运一个数据 */
}
  •  adc.h文件代码
#ifndef __ADC_H__
#define __ADC_H__#include "stm32f1xx.h"void adc_dma_init(uint32_t *mar);#endif
  •  mian.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "adc.h"uint32_t adc_result = 0;
int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* LED初始化 */uart1_init(115200);printf("hello,world");adc_dma_init(&adc_result);while(1){ printf("adc:result:%f v\r\n",(float)adc_result / 4096 * 3.3);delay_ms(500);}
}

注意事项:

  • 在初始化ADC的函数中,开启连续模式
  • 在初始化DMA的函数中,数据位是半字符,模式是循环模式
  •  一定要注意使用__HAL_LINKDMA( )函数中的参数。第一个外设的据饼,第二个外设句柄的参数,第三个,DMA的句柄;

adc.c中的文件的书写流程:

  1. 初始化ADC;
  2. 初始化ADC相关的外设,MSP函数;
  3. 初始化DMA,并用函数将ADC外设与内存进行连接;
  4. 配置ADC的通道(ADCx,channelx,rank,sampleTime);
  5. 书写一个封装函数:ADC初始化函数->ADC通道的配置->初始化DMA的函数->调用打开ADC和DMA的函数。

小实验3:ADC多通道采集实验+DMA读取

实验目的

使用ADC1采集通道0~3的电压值+DMA读取,通道1连接光敏电阻传感器。

硬件清单

开发板、光敏电阻传感器、ST-Link、USB转TTL 

配置流程

和单通道+DMA转运的流程基本相同

文件代码

  • adc.c文件代码
#include "adc.h"ADC_HandleTypeDef adc_handle = {0}; 
void adc_config(void){adc_handle.Instance = ADC1;adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                    /* 数据对齐:常用右对齐 */adc_handle.Init.ScanConvMode = ADC_SCAN_ENABLE;                    /* 需不需扫描:这里只有一个通道,不扫描 */adc_handle.Init.ContinuousConvMode = ENABLE;                       /* 连续转化 */adc_handle.Init.NbrOfConversion = 3;                                /* 转化的个数 */adc_handle.Init.DiscontinuousConvMode = DISABLE;                    /* 间断模式 */adc_handle.Init.NbrOfDiscConversion = 0;                            /* 间断的个数 */adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;              /* 触发模式的选择:软件触发 */HAL_ADC_Init(&adc_handle);HAL_ADCEx_Calibration_Start(&adc_handle);                           /* ADC的校准 */
}DMA_HandleTypeDef dma_handle = {0};
void dma_config(void){__HAL_RCC_DMA1_CLK_ENABLE();dma_handle.Instance = DMA1_Channel1;dma_handle.Init.Direction  = DMA_PERIPH_TO_MEMORY;dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;  /*ADC的DR寄存器是16,传输的数据是半字符。*/dma_handle.Init.MemInc = DMA_MINC_ENABLE;dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;dma_handle.Init.Mode = DMA_CIRCULAR;__HAL_LINKDMA(&adc_handle,DMA_Handle,dma_handle);HAL_DMA_Init(&dma_handle);
}void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc){if(hadc->Instance == ADC1){RCC_PeriphCLKInitTypeDef  adc_clk_init = {0};__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;          /* 外设时钟的选择 */adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;             /* ADC的预分频:这里6分频,12MHz */HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                       /* 由于ADC转化的时钟是12MHz,要进行改变,进行预分频 */GPIO_InitTypeDef gpio_initstruct;gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2;gpio_initstruct.Mode = GPIO_MODE_ANALOG;gpio_initstruct.Pull = GPIO_PULLUP;gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA,&gpio_initstruct); }
}/**
* @breif    封装一个配置ADC通道的函数。
* @param    配置的ADC1,通道,通道序列,采样时间
* @retval   无
*/void adc_channel_config(ADC_HandleTypeDef* hadc,uint32_t ch,uint32_t rank,uint32_t stime){ADC_ChannelConfTypeDef adc_ch_config = {0};adc_ch_config.Channel = ch;                                     /* 选择配置的通道 */adc_ch_config.Rank = rank;                                      /* 通道的优先级,序列 */adc_ch_config.SamplingTime = stime;                             /* 通道的采样时间 */HAL_ADC_ConfigChannel(&adc_handle,&adc_ch_config);
}void adc_dma_init(uint32_t *mar){adc_config();adc_channel_config(&adc_handle,ADC_CHANNEL_0,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_239CYCLES_5);adc_channel_config(&adc_handle,ADC_CHANNEL_1,ADC_REGULAR_RANK_2,ADC_SAMPLETIME_239CYCLES_5);adc_channel_config(&adc_handle,ADC_CHANNEL_2,ADC_REGULAR_RANK_3,ADC_SAMPLETIME_239CYCLES_5);dma_config();HAL_ADC_Start_DMA(&adc_handle,mar,3);          /* Length: The length of data to be transferred from ADC peripheral to memory.  转运3个数据 */
}

遇到的问题: 

在DMA初始化函数中,关于外设指针递增,要采取不递增,如下代码所示:

        如果采用指针递增的模式的话,通道2和通道3没有数据显示,因为外设只有一个数据,递增的话第一个数据后面没有数据,是空数据。

  • adc.h文件代码
#ifndef __ADC_H__
#define __ADC_H__#include "stm32f1xx.h"void adc_dma_init(uint32_t *mar);#endif
  •  main.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "adc.h"uint32_t adc_result[3] = {0};
int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* LED初始化 */uart1_init(115200);printf("hello,world");adc_dma_init(adc_result);while(1){ printf("通道1电压:%f v\r\n",(float)adc_result[0] / 4096 * 3.3);printf("通道2电压:%f v\r\n",(float)adc_result[1] / 4096 * 3.3);printf("通道3电压:%f v\r\n\r\n",(float)adc_result[2] / 4096 * 3.3);delay_ms(500);}
}

相比于单通道+DMA转运,多通道+DMA转运的区别和一些注意事项: 

  • 利用多通道配置的话,在初始化ADC的函数中,要开启扫描模式
  • DMA初始化函数中,外设指针不递增。
  • 封装一个配置通道的函数,方便在后面函数中配置不同的通道。
  • 在主函数中创建一个数组接收不同通道传来的数据。
http://www.xdnf.cn/news/552871.html

相关文章:

  • CSS之box-sizing、图片模糊、计算盒子宽度clac、(重点含小米、进度条案例)过渡
  • 喷涂喷漆机器人详解
  • python-leetcode 68.有效的括号
  • RSA加解密实战指南:Java与JavaScript实现详解 + 在线工具推荐
  • PyTorch 之 torch.distributions.Categorical 详解
  • Vue 3.0 Transition 组件使用详解
  • 高等数学笔记——向量代数与空间解析几何1
  • Mujoco 学习系列(一)安装与部署
  • C#新建打开文件对话框
  • 机器学习 集成学习方法之随机森林
  • Oracle中如何解决LATCH:CACHE BUFFERS LRU CHAIN
  • 精益数据分析(73/126):黏性阶段的功能优先级法则——七问决策模型与风险控制
  • 【神经网络与深度学习】扩散模型之原理解释
  • 调皮用法|python语言中的self参数
  • python训练营打卡第29天
  • 【实用教程】如何快速搭建一套私有的埋点系统?
  • 国产视频转换LT6211UX:HDMI2.0转LVDS/MIPI芯片简介,支持4K60Hz
  • Zenmap代理情况下无法扫描ip
  • MongoDB 学习(三)Redis 与 MongoDB 的区别
  • EasyOCR 模型文件下载
  • 开源运维工具HHDESK源码开发
  • Linux(ubuntu18.04)下安装instant-ngp环境
  • JWT单双token实现机制记录
  • 精益数据分析(71/126):从移情到黏性——创业阶段的关键跨越与数据驱动策略
  • JavaScript性能优化实战(13):性能测试与持续优化
  • Mysql面经
  • 基于Python批量删除文件和批量增加文件
  • List介绍
  • Java操作Elasticsearch 之 [Java High Level REST Clientedit]
  • 数据库索引是什么,什么时候不适合使用?