关于DMA1和DMA2的问题

2019-07-20 06:38发布

本人是个大三学生,同时也是小白,16年10月份开始接触STM32F4。
想问论坛里的大神,几个DMA的问题。
首先感谢各位大神的回答,同时也恳请各位大神不要喷我,因为我是学机械专业的.......
我想知道DMA1本身之间的关系,数据流和通道,是一个通道只能有一个数据流么?这个视频里没说到,我就有点懵。
还有就是DMA1和DMA2之间会干涉嘛?

我这里有一个DJI官方提供的程序,还有一个我自己仿照着它的写的,单独使用的时候都正常,如果放在一块用,就卡住了,肯定各位指出毛病,小弟感激不谢。


DJI官方:
#include "dbus.h"

volatile unsigned char sbus_rx_buffer[25];
RC_Ctl_t RC_Ctl;
/* ----------------------- Function Implements ---------------------------- */
/******************************************************************************
* @fn RC_Init
*
* @brief configure stm32 usart2 port
* - USART Parameters
* - 100Kbps
* - 8-N-1
* - DMA Mode
*
* @return None.
*
* @note This code is fully tested on STM32F405RGT6 Platform, You can port it
* to the other platform.
*/
void DBUS_Init(void)
{
/* -------------- Enable Module Clock Source ----------------------------*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3, GPIO_AF_USART2);
/* -------------- Configure GPIO ---------------------------------------*/
{
GPIO_InitTypeDef gpio;
USART_InitTypeDef usart2;
gpio.GPIO_Pin = GPIO_Pin_3 ;
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Speed = GPIO_Speed_100MHz;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &gpio);
USART_DeInit(USART2);
usart2.USART_BaudRate = 100000;
usart2.USART_WordLength = USART_WordLength_8b;
usart2.USART_StopBits = USART_StopBits_1;
usart2.USART_Parity = USART_Parity_Even;
usart2.USART_Mode = USART_Mode_Rx;
usart2.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART2,&usart2);
USART_Cmd(USART2,ENABLE);
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
}
/* -------------- Configure NVIC ---------------------------------------*/
{
NVIC_InitTypeDef nvic;
nvic.NVIC_IRQChannel = DMA1_Stream5_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 1;
nvic.NVIC_IRQChannelSubPriority = 2;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
}
/* -------------- Configure DMA -----------------------------------------*/
{
DMA_InitTypeDef dma;
DMA_DeInit(DMA1_Stream5);
dma.DMA_Channel = DMA_Channel_4;
dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
dma.DMA_Memory0BaseAddr = (uint32_t)sbus_rx_buffer;
dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
dma.DMA_BufferSize = 18;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Circular;
dma.DMA_Priority = DMA_Priority_VeryHigh;
dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
dma.DMA_MemoryBurst = DMA_Mode_Normal;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5,&dma);
DMA_ITConfig(DMA1_Stream5,DMA_IT_TC,ENABLE);
DMA_Cmd(DMA1_Stream5,ENABLE);
}
}
/******************************************************************************
* @fn DMA1_Stream5_IRQHandler
*
* @brief USART2 DMA ISR
*
* @return None.
*
* @note This code is fully tested on STM32F405RGT6 Platform, You can port it
* to the other platform.
*/
void DMA1_Stream5_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5))
{
DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5);
DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
RC_Ctl.rc.ch0 = (sbus_rx_buffer[0]| (sbus_rx_buffer[1] << 8)) & 0x07ff; //!< Channel 0
RC_Ctl.rc.ch1 = ((sbus_rx_buffer[1] >> 3) | (sbus_rx_buffer[2] << 5)) & 0x07ff; //!< Channel 1
RC_Ctl.rc.ch2 = ((sbus_rx_buffer[2] >> 6) | (sbus_rx_buffer[3] << 2) | //!< Channel 2
(sbus_rx_buffer[4] << 10)) & 0x07ff;
RC_Ctl.rc.ch3 = ((sbus_rx_buffer[4] >> 1) | (sbus_rx_buffer[5] << 7)) & 0x07ff; //!< Channel 3
RC_Ctl.rc.s1 = ((sbus_rx_buffer[5] >> 4)& 0x000C) >> 2; //!< Switch left
RC_Ctl.rc.s2 = ((sbus_rx_buffer[5] >> 4)& 0x0003); //!< Switch right
RC_Ctl.mouse.x = sbus_rx_buffer[6] | (sbus_rx_buffer[7] << 8); //!< Mouse X axis
RC_Ctl.mouse.y = sbus_rx_buffer[8] | (sbus_rx_buffer[9] << 8); //!< Mouse Y axis
RC_Ctl.mouse.z = sbus_rx_buffer[10] | (sbus_rx_buffer[11] << 8); //!< Mouse Z axis
RC_Ctl.mouse.press_l = sbus_rx_buffer[12]; //!< Mouse Left Is Press ?
RC_Ctl.mouse.press_r = sbus_rx_buffer[13]; //!< Mouse Right Is Press ?
RC_Ctl.key.v = sbus_rx_buffer[14] | (sbus_rx_buffer[15] << 8); //!< KeyBoard value
}
}



小弟自己仿照着改写的:
#include "main.h"

volatile unsigned char gyro_rx_buffer[25];
MPU6050_t MPU6050;
/* ----------------------- Function Implements ---------------------------- */
/******************************************************************************
* @fn MPU6050_Init
*
* @brief configure stm32 usart2 port
* - USART Parameters
* - 100Kbps
* - 8-N-1
* - DMA Mode
*
* @return None.
*
* @note This code is fully tested on STM32F405RGT6 Platform, You can port it
* to the other platform.
*/

void MPU6050_Init(void)
{
/* -------------- Enable Module Clock Source ----------------------------*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10, GPIO_AF_USART1);
/* -------------- Configure GPIO ---------------------------------------*/
{
GPIO_InitTypeDef gpio;
USART_InitTypeDef usart1;
gpio.GPIO_Pin = GPIO_Pin_10 ;
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Speed = GPIO_Speed_100MHz;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &gpio);
USART_DeInit(USART2);
usart1.USART_BaudRate = 115200;
usart1.USART_WordLength = USART_WordLength_8b;
usart1.USART_StopBits = USART_StopBits_1;
usart1.USART_Parity = USART_Parity_No;
usart1.USART_Mode = USART_Mode_Rx;
usart1.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1,&usart1);
USART_Cmd(USART1,ENABLE);
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
}
/* -------------- Configure NVIC ---------------------------------------*/
{
NVIC_InitTypeDef nvic;
nvic.NVIC_IRQChannel = DMA2_Stream5_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 1;
nvic.NVIC_IRQChannelSubPriority = 1;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
}
/* -------------- Configure DMA -----------------------------------------*/
{
DMA_InitTypeDef dma;
DMA_DeInit(DMA2_Stream5);
dma.DMA_Channel = DMA_Channel_4;
dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
dma.DMA_Memory0BaseAddr = (uint32_t)sbus_rx_buffer;
dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
dma.DMA_BufferSize = 13;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Circular;
dma.DMA_Priority = DMA_Priority_VeryHigh;
dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
dma.DMA_MemoryBurst = DMA_Mode_Normal;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream5,&dma);
DMA_ITConfig(DMA2_Stream5,DMA_IT_TC,ENABLE);
DMA_Cmd(DMA2_Stream5,ENABLE);
}
}
/******************************************************************************
* @fn DMA2_Stream5_IRQHandler
*
* @brief USART1 DMA ISR
*
* @return None.
*
* @note This code is fully tested on STM32F405RGT6 Platform, You can port it
* to the other platform.
*/
void DMA2_Stream5_IRQHandler(void)
{
if(DMA_GetITStatus(DMA2_Stream5, DMA_IT_TCIF5))
{
DMA_ClearFlag(DMA2_Stream5, DMA_FLAG_TCIF5);
DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5);
MPU6050.check = ((gyro_rx_buffer[0]<< 24) | (gyro_rx_buffer[1]) << 16| (gyro_rx_buffer[2])<< 8 | (gyro_rx_buffer[3]));
MPU6050.pitch = ((gyro_rx_buffer[7]) | (gyro_rx_buffer[8]<<8));
MPU6050.roll  = ((gyro_rx_buffer[9]) | (gyro_rx_buffer[10]<<8));
MPU6050.yaw   = ((gyro_rx_buffer[11])| (gyro_rx_buffer[12]<<8));
}
}



感谢您看到最后,还有一个问题就是,您觉得串口MPU6050用DMA接收数据合适嘛0.0
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
12条回答
正点原子
1楼-- · 2019-07-20 07:48
每个DMA有多个数据流通道,但是同一时刻,只能执行一个数据流的数据传输。
不同DMA之间,是可以同时传输的,不过DMA外设不要有冲突才行。
为我的心
2楼-- · 2019-07-20 10:26
 精彩回答 2  元偷偷看……
qq409157995
3楼-- · 2019-07-20 16:16
 精彩回答 2  元偷偷看……
barryxiao
4楼-- · 2019-07-20 20:42
同时使用DMA影响不大,可以任意多个设备使用DMA。只是在同一个DMA上,不同的通道会存在优先级的问题,在一个通道响应传输的时候,另一个通道会暂停等待其响应完。

就是说,DMA的所有通道可以同时都开启,但是某一确定的时钟周期上,只会有最多一个通道在传输数据,传输完了就让给别人
qq409157995
5楼-- · 2019-07-20 22:07
 精彩回答 2  元偷偷看……
civic7366
6楼-- · 2019-07-21 01:57
丟資料應該不至於吧...

外設至少都有一個BUFFER ,要延遲到BUFFER被複寫了 DMA都還沒去收才會丟


一周热门 更多>