OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5568|回复: 12

关于DMA1和DMA2的问题

[复制链接]

3

主题

12

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2017-1-20
在线时间
8 小时
发表于 2017-1-20 22:43:46 | 显示全部楼层 |阅读模式
1金钱
本人是个大三学生,同时也是小白,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

最佳答案

查看完整内容[请看2#楼]

每个DMA有多个数据流通道,但是同一时刻,只能执行一个数据流的数据传输。 不同DMA之间,是可以同时传输的,不过DMA外设不要有冲突才行。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-1-20 22:43:47 | 显示全部楼层
每个DMA有多个数据流通道,但是同一时刻,只能执行一个数据流的数据传输。
不同DMA之间,是可以同时传输的,不过DMA外设不要有冲突才行。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

23

主题

69

帖子

0

精华

新手上路

积分
26
金钱
26
注册时间
2017-1-5
在线时间
50 小时
发表于 2017-1-21 09:23:01 | 显示全部楼层
一个数据流有8个通道,看手册有个表格的,比如stream1 通道5 是UART ,我是用cube直接产生的代码,比较方便。MPU6050不知道,我也是新手,在弄串口空闲中断+DMA
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2017-1-20
在线时间
8 小时
 楼主| 发表于 2017-1-21 11:19:30 来自手机 | 显示全部楼层
我想问的是能几个设备同时用DMA
回复

使用道具 举报

0

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2015-5-9
在线时间
17 小时
发表于 2017-1-22 21:51:55 | 显示全部楼层
同时使用DMA影响不大,可以任意多个设备使用DMA。只是在同一个DMA上,不同的通道会存在优先级的问题,在一个通道响应传输的时候,另一个通道会暂停等待其响应完。

就是说,DMA的所有通道可以同时都开启,但是某一确定的时钟周期上,只会有最多一个通道在传输数据,传输完了就让给别人
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2017-1-20
在线时间
8 小时
 楼主| 发表于 2017-1-24 11:46:06 来自手机 | 显示全部楼层
barryxiao 发表于 2017-1-22 21:51
同时使用DMA影响不大,可以任意多个设备使用DMA。只是在同一个DMA上,不同的通道会存在优先级的问题,在一 ...

如果两个都在不停的接受数据呢,如果区分优先级,会不会有一个丢失数据。。。
回复

使用道具 举报

60

主题

409

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2814
金钱
2814
注册时间
2012-10-17
在线时间
653 小时
发表于 2017-1-24 11:55:41 | 显示全部楼层
丟資料應該不至於吧...

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


回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2017-1-20
在线时间
8 小时
 楼主| 发表于 2017-1-24 15:49:05 | 显示全部楼层
一个数据流可以使用多个通道,还是一个通道可以使用多个数据流。应该是一个数据流可以使用多个通道吧,跪求大神指点
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2017-1-20
在线时间
8 小时
 楼主| 发表于 2017-1-24 16:08:09 | 显示全部楼层
我发现我先初始化DMA2,再初始化DMA1就没问题了.........这是为什么啊...........
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2017-1-20
在线时间
8 小时
 楼主| 发表于 2017-1-25 09:42:27 来自手机 | 显示全部楼层
等大神
回复

使用道具 举报

0

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2015-5-9
在线时间
17 小时
发表于 2017-3-10 10:18:34 | 显示全部楼层
qq409157995 发表于 2017-1-24 11:46
如果两个都在不停的接受数据呢,如果区分优先级,会不会有一个丢失数据。。。

你可以这样想。其实就跟中断接收是一个道理,只是DMA没有执行具体的中断接收代码,也没用中断那样灵活的控制方案。
例如:DMA1的channel1和channel2设置为相同优先级(但是其实1的优先级比2高。因为硬件里默认是,两个通道设置为相同优先级的时候,编号号小的优先)。都在同一个时间(即同一个时钟周期)接收到传输数据请求。
这个请求有可能是来自CPU core,也有可能是来自外设usart等。
这时候DMA1会进行优先级判断,低优先的channel2会被挂起,DMA1先安排channnel1的任务,传输完channel1的数据后,再安排channnel2的动作。数据都不会丢,只是谁先完成谁后完成。
完成的时间,跟传输的速度和数据量有关。例如channnel1从串口2(只是假设,实际看处理器型号)接收速度115200bps的数据,channnel1在接收完1个byte后,第2个byte的请求要很久之后(10*1/115200=86.8us)才会到来,这段空余时间里DMA并不知道channnel1还有数据要接收,他会自动安排所有其他的传输请求,如果这时候channnel2是被挂起的,就会去传输channnel2的数据
如果channnel1是用的M2M模式,这种情况下,数据请求是一个接着一个的,直到传输CNDTR数量为0,DMA就会一直忙于执行channnel1的请求,直到channnel1完成后,转为执行channnel2的请求。这个执行时间跟数据量和总线的竞争仲裁有关。
这些东西建议详细看一下NVIC和总线仲裁的知识,其中逻辑是相通的
回复

使用道具 举报

0

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2015-5-9
在线时间
17 小时
发表于 2017-3-10 10:21:46 | 显示全部楼层
qq409157995 发表于 2017-1-24 11:46
如果两个都在不停的接受数据呢,如果区分优先级,会不会有一个丢失数据。。。

另外就是,一个channel在同一个确定的clock中,只能有一个数据源的传输请求,说简单点就是只能配置到一个外设。如果两个外设同时配置为使用同一个channel……这种死我也没作过,还请经验人士告知
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2018-8-17
在线时间
1 小时
发表于 2018-8-17 17:02:52 | 显示全部楼层
我也遇到同样的问题,同时使用DMA1和DMA2时,程序跑一会就发生总线故障,只使用DMA1时,就没有问题,楼主现在有没有什么思路了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-12 03:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表