STM32 DMA

STM32标准库学习笔记-STM32 DMA

DMA简介

  • DMA(Direct Memory Access)直接存储器存取
  • DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源
  • 12个独立可配置的通道: DMA1(7个通道), DMA2(5个通道)
  • 每个通道都支持软件触发和特定的硬件触发
  • STM32F103C8T6 DMA资源:DMA1(7个通道)

DMA数据传输宽度与大小

DMA数据传输: 源端大于目标,高位舍弃。 源端小于目标,高位补零。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//全局变量,用于存储每次转运的字节数
uint16_t MyDMA_Size;

//配置时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

//DMA配置
DMA_InitTypeDef DMA_InitStructure;                              
DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = Size;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);

//DMA使能(这里未使能)
DMA_Cmd(DMA1_Channel1, DISABLE);

void MyDMA_Transfer(void)
{
    DMA_Cmd(DMA1_Channel1, DISABLE);
    DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);
    DMA_Cmd(DMA1_Channel1, ENABLE);
    while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
    DMA_ClearFlag(DMA1_FLAG_TC1);
}

DMA_InitTypeDef为DMA配置结构体

  • 外设配置:
  • DMA_PeripheralBaseAddr为外设基地址,转运来源
  • DMA_PeripheralDataSize为外设数据宽度
  • DMA_PeripheralInc为外设地址自增:
  • DMA_PeripheralInc_Enable开启
  • DMA_PeripheralInc_Disable关闭
  • 存储器配置:
  • DMA_MemoryBaseAddr为存储器基地址,转运目标
  • DMA_MemoryDataSize为存储器数据宽度
  • DMA_MemoryInc为存储器地址自增:
  • DMA_MemoryInc_Enable开启
  • DMA_MemoryInc_Disable关闭
  • DMA_DIR为数据传输方向:
  • DMA_DIR_PeripheralDST存储器到外设
  • DMA_DIR_PeripheralSRC外设到存储器
  • DMA_BufferSize为转运的数据大小(转运次数)
  • DMA_Mode为模式,主要配置自动重装
  • DMA_Mode_Circular循环模式
  • DMA_Mode_Normal单次模式
  • DMA_M2M软硬件触发选择
  • DMA_M2M_Enable开启
  • DMA_M2M_Disable关闭
  • DMA_Priority优先级
DMA_PeripheralDataSize 描述
DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) 1Byte
DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100) 2Byte
DMA_PeripheralDataSize_Word ((uint32_t)0x00000200) 4Byte
DMA_MemoryDataSize 描述
DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) 1Byte
DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400) 2Byte
DMA_MemoryDataSize_Word ((uint32_t)0x00000800) 4Byte
DMA_Priority 描述
DMA_Priority_VeryHigh ((uint32_t)0x00003000) 非常高
DMA_Priority_High ((uint32_t)0x00002000)
DMA_Priority_Medium ((uint32_t)0x00001000)
DMA_Priority_Low ((uint32_t)0x00000000)

DMA + ADC 协同工作

DMA请求

更多DMA请求映像的相关内容:STM32F10xxx参考手册(中文).pdf 页码147/手册10.3.7

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//存储数值的全局变量
uint16_t AD_Value[4];

//时钟配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);

//GPIO配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//ADC通道配置
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);

//ADC配置
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_NbrOfChannel = 4;
ADC_Init(ADC1, &ADC_InitStructure);

//DMA配置
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
MA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);

//DMA和ADC使能
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);

//ADC校准
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);

//ADC触发
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  • DMA_Cmd(DMA1_Channel1, ENABLE);启用DMA通道1
  • ADC_DMACmd(ADC1, ENABLE);启用ADC1触发DMA1信号
  • ADC_Cmd(ADC1, ENABLE);启用ADC1
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计