stm32F4 DMA
外设使用的DMA
DMA1
DMA2
外设地址
ADC地址
ADC1
:0x40012000+0x4C
DMA初始化
void Dma_Init(DMA_Stream_TypeDef* DMAy_Streamx, u32 DMA_Channel_x, u32 phaddr, u32 meaddr, u32 BufferSize)
{
DMA_InitTypeDef DmaIniture;
NVIC_InitTypeDef Dma_It_Initure;
if((u32)DMAy_Streamx >= (u32)DMA2)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
else
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
DMA_DeInit(DMAy_Streamx);
DmaIniture.DMA_Channel = DMA_Channel_x; //指定通道
DmaIniture.DMA_BufferSize = BufferSize; //传输的数据数目
DmaIniture.DMA_FIFOMode = DMA_FIFOMode_Disable; //失能FIFO
DmaIniture.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; //FIFO阈值(随便给一个值)
DmaIniture.DMA_DIR = DMA_DIR_PeripheralToMemory; //外设到内存
DmaIniture.DMA_Mode = DMA_Mode_Circular; //循环模式
DmaIniture.DMA_Priority = DMA_Priority_VeryHigh; //优先级为非常高
DmaIniture.DMA_Memory0BaseAddr = meaddr; //指定内存地址
DmaIniture.DMA_PeripheralBaseAddr = phaddr; //指定外设地址
DmaIniture.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存半字(16位)传输
DmaIniture.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设半字传输
DmaIniture.DMA_MemoryBurst = DMA_MemoryBurst_Single; //内存突发单次传输
DmaIniture.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发单次传输
DmaIniture.DMA_MemoryInc = DMA_MemoryInc_Enable; //使能内存地址递增
DmaIniture.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //失能外设地址递增
DMA_Init(DMAy_Streamx, &DmaIniture);
while(DMA_GetCmdStatus(DMAy_Streamx) == ENABLE);//等待DMA配置成功(若参数配置错误,即使使能对应的数据流,仍然处于失能状态)
//开启中断
DMA_ITConfig(DMAy_Streamx, DMA_IT_TC, ENABLE);
Dma_It_Initure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
Dma_It_Initure.NVIC_IRQChannelCmd = ENABLE;
Dma_It_Initure.NVIC_IRQChannelPreemptionPriority = 0;
Dma_It_Initure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&Dma_It_Initure);
DMA_Cmd(DMAy_Streamx, ENABLE);
}
注:内存地址为自定义数组
ADC初始化
void ADC1_CH1_Init()
{
GPIO_InitTypeDef GpioIniture;
ADC_CommonInitTypeDef AdcIniture;
ADC_InitTypeDef Adc1Initure;
// NVIC_InitTypeDef AdcItIniture;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); //ADC配置复位
GpioIniture.GPIO_Mode = GPIO_Mode_AN;
GpioIniture.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GpioIniture.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GpioIniture);
AdcIniture.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
AdcIniture.ADC_Mode = ADC_Mode_Independent; //独立模式(只用一个adc)
AdcIniture.ADC_Prescaler = ADC_Prescaler_Div4; //adc的时钟频率不得大于36M,此处设为84M / 4
AdcIniture.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; //延时周期数 = 采样周期数 + 12(越大越准确)
ADC_CommonInit(&AdcIniture);
Adc1Initure.ADC_ContinuousConvMode = ENABLE; //使能连续转换
Adc1Initure.ADC_DataAlign = ADC_DataAlign_Right; //右对齐
Adc1Initure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //随便给一个
Adc1Initure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //外部触发方式(无)
Adc1Initure.ADC_NbrOfConversion = 2; //规则序列长度
Adc1Initure.ADC_Resolution = ADC_Resolution_12b; //分辨率
Adc1Initure.ADC_ScanConvMode = ENABLE; //使能扫描模式
ADC_Init(ADC1, &Adc1Initure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_56Cycles); //转换周期数 = 采样周期数 + 12(越大越准确)
ADC_Cmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);//使能后,只要发生数据转换,就可以发出DMA请求(对于独立模式)
// ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);//规则组转换完成中断
//
// AdcItIniture.NVIC_IRQChannel = ADC_IRQn;
// AdcItIniture.NVIC_IRQChannelCmd = ENABLE;
// AdcItIniture.NVIC_IRQChannelPreemptionPriority = 1;
// AdcItIniture.NVIC_IRQChannelSubPriority = 1;
// NVIC_Init(&AdcItIniture);
}
DMA中断
void DMA2_Stream0_IRQHandler()
{
if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)//判断DMA中断是否发生
{
}
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC);//清除中断标志位
}