DMA(Direct Memory Access)直接存储器存取
DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源
12个独立可配置的通道: DMA1(7个通道), DMA2(5个通道)
每个通道都支持软件触发和特定的硬件触发
STM32F103C8T6 DMA资源:DMA1(7个通道)
32单片机中的存储地址:
DMA结构框图:
DMA基本结构 :
当m2m为 1时软件触发,0为硬件触发
同时软件触发和自动重装器不可以同时启用
DMA请求:
数据宽度与对齐方式:
数据转运模式:
AD多通道扫描模式 :
配置流程:
RCC→DMA(初始化)→控制开关(CMD)
相关函数:
DMA_Init 初始化
DMA_Cmd 运行控制
DMA_SetCurrDataCounter 给计数器值
DMA_GetCurrDataCounter 读取计数器值
DMA_GetFlagStatus 获取标志位
DMA_ClearFlag 清楚标志位
ADC_DMA 用于硬件触发产生DMA信号
数据转存例程:
void DMAself_Init(uint32_t num1,uint32_t num2,uint16_t size)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_BufferSize=size;
DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC; //外设作源 方向
DMA_InitStruct.DMA_M2M=DMA_M2M_Enable;
DMA_InitStruct.DMA_Mode=DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority=DMA_Priority_Medium;
DMA_InitStruct.DMA_MemoryBaseAddr=num2;
DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralBaseAddr=num1;
DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Enable;
DMA_Init(DMA1_Channel1,&DMA_InitStruct);
DMA_Cmd(DMA1_Channel1,DISABLE);
}
void Start_Transf(uint16_t size)
{
DMA_Cmd(DMA1_Channel1,DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel1,size);
DMA_Cmd(DMA1_Channel1,ENABLE);
while(DMA_GetFlagStatus(DMA1_FLAG_TC1)==RESET);
DMA_ClearFlag(DMA1_FLAG_TC1);
}
AD多通道:
uint16_t num[4];
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); //外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div8); //ADC分频器
GPIO_InitTypeDef GPIO_InitStruct; //GPIO初始化
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
ADC_InitTypeDef ADC_InitStruct; //ADC初始化
ADC_InitStruct.ADC_ContinuousConvMode=ENABLE;
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None; //软件触发
ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;
ADC_InitStruct.ADC_NbrOfChannel=4;
ADC_InitStruct.ADC_ScanConvMode=ENABLE;
ADC_Init(ADC1,&ADC_InitStruct);
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_28Cycles5); //通道规定
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_28Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_28Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_28Cycles5);
DMA_InitTypeDef DMA_InitStruct; //DMA初始化
DMA_InitStruct.DMA_BufferSize=4;
DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC; //外设基地址作源
DMA_InitStruct.DMA_M2M=DISABLE;
DMA_InitStruct.DMA_Mode=DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority=DMA_Priority_Medium;
DMA_InitStruct.DMA_MemoryBaseAddr=(uint32_t)num;
DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralBaseAddr=(uint32_t)&ADC1->DR;
DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
DMA_Init(DMA1_Channel1,&DMA_InitStruct);
ADC_Cmd(ADC1,ENABLE); //运行控制开关
ADC_DMACmd(ADC1,ENABLE);
DMA_Cmd(DMA1_Channel1,ENABLE);
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
//void AD_Start(void) //不连续模式用
//{
// DMA_Cmd(DMA1_Channel1,DISABLE);
// DMA_SetCurrDataCounter(DMA1_Channel1,4);
// DMA_Cmd(DMA1_Channel1,ENABLE);
// ADC_SoftwareStartConvCmd(ADC1,ENABLE); //ADC软件触发
// while(DMA_GetFlagStatus(DMA1_FLAG_HT1)==RESET); //等待DMA转换完成
// DMA_ClearFlag(DMA1_FLAG_HT1);
//}