在 STM32 上使用 DMA,可以大幅提高外设与内存之间的数据传输效率,减少 CPU 的负担。下面是一个常见的 STM32 DMA 应用的实现步骤。
配置 DMA
启用 DMA 外设时钟:首先,需要启用 DMA 控制器和相关外设的时钟。
配置 DMA 流:DMA 控制器有多个通道和流,每个流可以与不同的外设进行数据传输。
配置 DMA 流时,需要指定源地址、目标地址、传输大小、传输方向等参数。
配置 DMA 传输模式:选择传输模式,如单次传输模式或循环模式,并设置传输的数据量。
启动 DMA 传输:启动 DMA 外设并启动传输。在传输过程中,DMA 控制器会自动完成数据传输。
DMA 示例代码
以下是一个简单的例子,演示如何使用 STM32 的 DMA 从 ADC 获取数据并传输到内存:
c
复制代码
#include "stm32f4xx_hal.h"
#define ADC_BUFFER_SIZE 100
// ADC 采样数据缓冲区
uint16_t ADC_Buffer[ADC_BUFFER_SIZE];
// ADC DMA 句柄
DMA_HandleTypeDef hdma_adc;
// ADC 配置
ADC_HandleTypeDef hadc1;
void ADC_DMA_Init(void)
{
// 启用 ADC 和 DMA 时钟
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
// 配置 ADC
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = ADC_CONTINUOUS_MODE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
HAL_ADC_Init(&hadc1);
// 配置 DMA
hdma_adc.Instance = DMA2_Stream0;
hdma_adc.Init.Channel = DMA_CHANNEL_0;
hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc.Init.Mode = DMA_CIRCULAR; // 循环模式
hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
HAL_DMA_Init(&hdma_adc);
// 将 DMA 配置与 ADC 绑定
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc);
// 启动 DMA 与 ADC
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Buffer, ADC_BUFFER_SIZE);
}
void ADC_DMA_IRQHandler(void)
{
if (__HAL_ADC_GET_FLAG(&hadc1, ADC_FLAG_EOC)) {
// 处理 ADC 数据
// 这里可以将 ADC_Buffer 中的数据进行处理或发送到其他外设
}
}
在上面的代码中,STM32 启用了 DMA 传输模式,将 ADC 的采样数据直接传输到内存缓冲区 ADC_Buffer 中,避免了 CPU 参与每个数据项的传输。这样,CPU 可以在 DMA 传输过程中执行其他任务,极大地提高了数据采集的效率。
|