天天看點

關于stm32f030的DMA配置關于stm32f030的DMA配置

關于stm32f030的DMA配置

DMA的一般配置

1.設定DMA的工作方式

2.設定通道的優先級

3.設定DMA的動作模式

4.設定外設的增量

5.設定記憶體是否增量

6.設定外設大小

7.設定記憶體大小

8.設定資料長度

9.設定外設位址

10.設定記憶體位址

11.使能DMA

舉個栗子:從ADC值到記憶體的搬運

畫了一個小圖流程圖(個人了解哦o(# ̄▽ ̄)==O)) ̄0 ̄”)o)

關于stm32f030的DMA配置關于stm32f030的DMA配置

首先呢就是要使能ADC讓它轉換咯,我使用的是STM32的LL庫,關于ADC的配置代碼如下(以下代碼可以用STM32Cube自動生成啦)

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1); //首當其沖的當然是時鐘的使能啦

LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_2;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//就是IO的模式配置啦

LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_0);
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_1);
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_2); //這是通道選擇啊

ADC_InitStruct.Clock = LL_ADC_CLOCK_ASYNC;
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
LL_ADC_Init(ADC1, &ADC_InitStruct);
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
LL_ADC_REG_SetSequencerScanDirection(ADC1, LL_ADC_REG_SEQ_SCAN_DIR_FORWARD);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_239CYCLES_5);
LL_ADC_DisableIT_EOC(ADC1);
LL_ADC_DisableIT_EOS(ADC1);

/*ADC要自動添加代碼使能哦*/
LL_ADC_Enable(ADC1);
LL_ADC_REG_SetDMATransfer(ADC1,LL_ADC_REG_DMA_TRANSFER_LIMITED); 
LL_ADC_REG_StartConversion(ADC1);//這就是ADC相關的參數配置啊。注意DMA的采集一定要多,才有意義哦
           

接下來就是DMA的設定咯

LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_MEDIUM);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1,LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_HALFWORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_HALFWORD);//這是DMA的一些配值啊

LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,300);
LL_DMA_SetPeriphAddress(DMA1,LL_DMA_CHANNEL_1,LL_ADC_DMA_GetRegAddr(ADC1,LL_ADC_DMA_REG_REGULAR_DATA));
LL_DMA_SetMemoryAddress(DMA1,LL_DMA_CHANNEL_1,(uint32_t)&adc_value);//這就是告訴DMA位址和資料長度,它好知道我要搬的地方在哪,搬多少啦

LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);//最後一句使能就OK啦

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
NVIC_EnableIRQ(DMA1_Channel1_IRQn);//時鐘和中斷使能以及中斷優先級啦
           

繼續閱讀