关于stm32f030的DMA配置

关于stm32f030的DMA配置

DMA的一般配置

1.设置DMA的工作方式
2.设置通道的优先级
3.设置DMA的动作模式
4.设置外设的增量
5.设置内存是否增量
6.设置外设大小
7.设置内存大小
8.设置数据长度
9.设置外设地址
10.设置内存地址
11.使能DMA

举个栗子:从ADC值到内存的搬运

画了一个小图流程图(个人理解哦o(# ̄▽ ̄)==O)) ̄0 ̄”)o)
在这里插入图片描述
首先呢就是要使能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);//时钟和中断使能以及中断优先级啦
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是STM32F030 DMA初始化的代码示例: ```c /* 选择DMA通道 */ #define DMA_CHANNEL_ADC DMA1_Channel1 /* ADC DMA缓冲区大小 */ #define ADC_DMA_BUF_SIZE 16 uint16_t adc_dma_buf[ADC_DMA_BUF_SIZE]; // ADC DMA缓冲区 void dma_adc_init(void) { /* 使能DMA时钟 */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* DMA配置 */ DMA_InitTypeDef dma_init; DMA_DeInit(DMA_CHANNEL_ADC); dma_init.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; // DMA外设地址为ADC数据寄存器地址 dma_init.DMA_MemoryBaseAddr = (uint32_t)adc_dma_buf; // DMA内存地址为ADC DMA缓冲区首地址 dma_init.DMA_DIR = DMA_DIR_PeripheralSRC; // DMA数据传输方向:外设到内存 dma_init.DMA_BufferSize = ADC_DMA_BUF_SIZE; // DMA缓冲区大小 dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不递增 dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增 dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外设数据大小为半字(两个字节) dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 内存数据大小为半字(两个字节) dma_init.DMA_Mode = DMA_Mode_Circular; // DMA循环模式 dma_init.DMA_Priority = DMA_Priority_High; // DMA优先级高 DMA_Init(DMA_CHANNEL_ADC, &dma_init); /* 使能DMA传输完成中断 */ DMA_ITConfig(DMA_CHANNEL_ADC, DMA_IT_TC, ENABLE); /* 使能DMA通道 */ DMA_Cmd(DMA_CHANNEL_ADC, ENABLE); } /* DMA传输完成中断处理函数 */ void DMA1_Channel1_IRQHandler(void) { if(DMA_GetITStatus(DMA1_FLAG_TC1)) { /* 在这里处理ADCDMA数据 */ DMA_ClearITPendingBit(DMA1_FLAG_TC1); } } ``` 在上面的代码中,先定义了DMA通道和ADC DMA缓冲区大小,并初始化了ADC DMA缓冲区数组。然后在dma_adc_init函数中,首先使能了DMA时钟,之后设置了DMA配置参数,并调用DMA_Init函数进行初始化。此外,还使能了DMA传输完成中断,并打开DMA通道。 最后,在DMA传输完成中断处理函数中,我们可以对ADCDMA数据进行处理。通过上述步骤,DMA已经成功初始化,可以进行数据传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值