STM32HAL库单ADC+DMA学习及测试记录

使用CubeMX可以方便地进行配置,在自动生成代码后只需在main函数中加入相应启动函数或是读取数据函数即可实现基本功能。

使用单片机为STM32F103ZET6,下图为ADC设置页面。

在只启用一个ADC时,Common_Settings中的Mode只能选择独立模式,Setings下依次是数据对齐(Data Alignment)、扫描模式(Scan Conversion Mode)、连续模式(Continuous Conversion Mode)、不连续模式(Discontinuous Conversion Mode),Regular_ConversionMode和Injiected_ConversionMode是两种不同转换模式,此篇暂只讨论Regular_ConversionMode即常规转换。此外ADC功能还有看门狗(WatchDog),可以监测数值是否在规定范围内,不详细介绍。

引脚设置

使用CubeMX配置时首先需要使能相关引脚,一种方法是在ADC页面的复选框中勾选需要使用的输入通道,可以自动设置对应引脚的模式,免去了自行查找引脚的麻烦。若已知所需ADC功能引脚也可以直接选择所需的引脚进行配置。

 

在将引脚配置为ADC输入(ADCx_INx)时不会自动设置引脚为模拟模式(GPIO_Analog),需自行设置。但实际上即使不手动设置为模拟模式对于ADC功能也没有影响,在设置为ADC模式时引脚只能被设置为模拟模式,在ADC界面下的GPIO设置选项卡中可以看到所有引脚都被自动设为了模拟模式,通过生成的代码也可以看到引脚被自动设为了模拟模式。

个人认为此处的GPIO_Analog选项是针对普通IO输入的设置,对于ADC功能则无需选择。如PA6选择了ADC1_IN6选项,若选上GPIO_Analog选项,则无法直接在ADC页面复选框中直接选择该通道,并以红色标注,如下图。

选择了GPIO_Analog选项的引脚可以在GPIO页面选择显示外设时被看到,PA6则未被显示,只能在选择显示全部时被看到。

不过当没有选择GPIO_Analog选项的引脚时,只选择了ADC_IN引脚也可以被显示。

常规模式

单通道

默认如下图所示,扫描模式是Disable,且此时无法使能,仅在有多通道时可以使用;连续模式和不连续模式都是Disable,不连续的Enable选项此时不可选。由字面看,连续模式和不连续模式是相互矛盾的,一种为真时另一种则为假,当设置其一为Enable时,另一只能选Disable,而看起来分别列出连续模式和不连续模式似乎有些多余,但测试表明并非如此,经后续DMA部分测试发现二者同时为Disable是一种独立的状态,加上连续模式或不连续模式为Enable的情况共有三种模式。

在默认基础上不改变其他设置,分别将连续模式设置Enable和Disable模式,使用HAL_ADC_GetValue查询获取值,并未发现不同现象,均为每查询一次返回一次值。

多通道

将转换数(Number Of Conversion)增加到3,此时自动切换到扫描模式且不能取消,即扫描模式是根据转换数(Number Of Conversion)强制自动切换的,数量为1时关闭,大于1时打开。此时不连续模式可以使能,使用HAL_ADC_Start_DMA查询获取值时应设置为不连续模式,使能不连续模式后出现不连续转换数选项,为使每个值都能被依次接收,此项应设为1,否则若设为n,将丢失后n-1次采集的ADC值。若使用连续模式,会发现不同通道数据随机乱序出现在所有相关变量中,原因为查询速率和连续转换速率不同步。

Rank选项数量随转换数(Number Of Conversion)改变,每一个Rank选项对应一个通道,在其中可以选择采集数值的通道,不同Rank中此项可以相同,ADC工作时将从Rank1开始依次采集对应通道,全部完成后再次从Rank1开始采集,可以通过设置Rank对应的通道实现按特定顺序对通道数值多次采集。

采样时间(Sampling Time)需根据外围电路阻值进行设置,由于ADC内部为一组电容,利用二分法,通过电容完全充放电时间来测量电压。当外部电阻增大时电容充电所需时间增加,要相应延长采样时间,否则无法准确测量输入值。

DMA

在DMA选项卡中Add添加ADC通道即可,右下两选项分别为外设和存储的地址递增,在只有一个ADC时无法选择外设地址递增。勾选存储地址递增可以实现将不同通道数分别存到数组不同位置,数组元素个数应大于等于HAL_ADC_Start_DMA中设置的数值。不勾选存储地址递增则只能存在基址位置。

DMA有Normal和Circular两种模式,Normal模式每使用一次start函数读取一次,Circular模式start后将持续搬运数值。Normal模式时连续、不连续模式选项都需要设为Disable,若设连续模式为Enable,则读取的数值为乱序,若设不连续模式为Enable,则无法读出数。使用Normal模式时设置如下二图。

 将DMA模式设置为Circular模式时,需设连续模式为Enable,否则无法读出数据。需要注意此时由于DMA不断向目标变量中搬运数值,会导致此时此值无法被正常读取,但可以观察到变量中存入了DMA传入的数值,在此例中HAL_ADC_Start_DMA中设置的数值等于通道数为3时无法正常将值赋给其他变量,改为21留出足够空余时间后可以正常运行。

### STM32 HALADCDMA配合使用 在STM32微控制器系列中,通过硬件抽象层(HAL)实现模数转换器(ADC)和直接存储器访问(DMA)之间的高效协作是一项常见需求。为了确保数据传输的准确性并避免潜在的数据丢失或损坏,在配置过程中需特别注意初始化参数以及回调函数的设计。 当利用HAL进行ADC-DMA交互编程时,建议采用循环模式而非次模式来处理连续采样任务[^1]。这有助于减少因频繁重启DMA而导致的资源消耗及可能引发的同步问题。下面给出一段基于CubeMX工具自动生成框架下的C语言源码片段作为参考: ```c // 初始化全局变量用于保存ADC采集到的结果数组指针 uint16_t aADCxConvertedData[BUFFER_SIZE]; void MX_ADC_Init(void) { /* USER CODE BEGIN ADC_Init 0 */ /* USER CODE END ADC_Init 0 */ /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. */ hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = DISABLE; // 通道模式 hadc1.Init.ContinuousConvMode = ENABLE; // 连续转换模式开启 hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } // 配置要读取的具体模拟输入引脚... } static void MX_DMA_Init(void) { __HAL_RCC_DMA_CLK_ENABLE(); hdma_adc1.Instance = DMA1_Channel1; hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc1.Init.Mode = DMA_CIRCULAR; // 循环模式启用 hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH; if (HAL_DMA_Init(&hdma_adc1) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1); } ``` 上述代码展示了如何正确地设置ADC的工作方式为连续转换,并且让DMA工作于循环模式下以持续不断地将来自ADC的数据搬运至内存缓冲区中去。此外还定义了一个名为`aADCxConvertedData`的一维数组用来暂存最终获得的数字化信号样本值集合。 值得注意的是,在实际项目开发当中应当依据具体应用场景灵活调整这些预设选项;比如对于某些实时性强的任务来说或许更适合选用中断驱动的方式来进行更细粒度的时间控制。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值