OpenEdv-开源电子网

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

很简单的DMA输出,总是调不对,是我脑筋短路了吗?

[复制链接]

1

主题

10

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1436
金钱
1436
注册时间
2016-7-6
在线时间
161 小时
发表于 2020-5-1 16:54:16 | 显示全部楼层 |阅读模式
50金钱
本帖最后由 guiguziqin 于 2020-5-1 17:44 编辑

我在FreeRTOS系统新建了一个任务,每100ms往USART2打印10个字节的数组。数组的第1、第2个元素是个变量,每100ms加1。

// 以下是用for循环输出的源代码:
  1. void datasnd_task(void *pvParameters)
  2. {
  3.         u8 t;
  4.         uint8_t TxData[10] = {0};
  5.         uint16_t tick = 0;
  6.         u32 lastWakeTime = getSysTickCnt();
  7.         while(1)
  8.         {
  9.                 vTaskDelayUntil(&lastWakeTime, 100);                                                //100ms运行频率
  10.                 TxData[0] = BYTE1(tick);                                                                      //把tick的高字节放在第0个元素
  11.                 TxData[1] = BYTE0(tick);                                                                        //把tick的低字节放在第1个元素
  12.                 for(t=0;t<10;t++)
  13.                 {
  14.                         USART_SendData(USART2, TxData[t]);                                         //向串口2发送数据
  15.                         while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);        //等待发送结束
  16.                 }

  17.                 if(tick == 65535) tick = 0;
  18.                 else tick++;
  19.         }
  20. }
复制代码

当使用for循环打印时,输出是正确的,即100ms打印一次。可以看到打印出的变量是每次加1的。

2.jpg

// 以下是用DMA输出的代码:
  1. void datasnd_task(void *pvParameters)
  2. {
  3.         u8 t;
  4.         uint8_t TxData[10] = {0};
  5.         uint16_t tick = 0;
  6.         u32 lastWakeTime = getSysTickCnt();
  7.         MYDMA_Config((u32)TxData,10);                                                                        //初始化DMA1的数据流6,通道4
  8.         USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);                                          //使能串口2的DMA发送
  9.         while(1)
  10.         {
  11.                 vTaskDelayUntil(&lastWakeTime, 100);                                                //100ms运行频率
  12.                 TxData[0] = BYTE1(tick);                                                                      //把tick的高字节放在第0个元素
  13.                 TxData[1] = BYTE0(tick);                                                                        //把tick的低字节放在第1个元素
  14.                 DMA_Cmd(DMA1_Stream6, ENABLE);                                                                //启动一次DMA传输
  15.                 if(DMA_GetFlagStatus(DMA1_Stream6,DMA_FLAG_TCIF6)!=RESET)        //等待DMA1_Stream6传输完成
  16.                 {
  17.                         DMA_ClearFlag(DMA1_Stream6,DMA_FLAG_TCIF6);                                //清除DMA1_Stream6传输完成标志
  18.                 }
  19.                 if(tick == 65535) tick = 0;
  20.                 else tick++;
  21.         }
  22. }
复制代码


但是当使用DMA方式输出的时候,发现是200ms打印一次,每次打印出的变量是加2。请问有大神能解答吗?

1.jpg

以下是DMA初始化代码:
  1. void MYDMA_Config(u32 memory_adr,u16 data_lenth)
  2. {
  3.         DMA_InitTypeDef  DMA_InitStructure;
  4.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);                                                //DMA1时钟使能
  5.         DMA_DeInit(DMA1_Stream6);
  6.         
  7.         while (DMA_GetCmdStatus(DMA1_Stream6) != DISABLE){}                                                //等待DMA可配置
  8.         
  9.         /* 配置 DMA Stream */
  10.         DMA_InitStructure.DMA_Channel = DMA_Channel_4;                                                  //通道选择
  11.         DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;                        //DMA外设地址
  12.         DMA_InitStructure.DMA_Memory0BaseAddr = memory_adr;                                                //DMA 存储器0地址
  13.         DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                        //存储器到外设模式
  14.         DMA_InitStructure.DMA_BufferSize = data_lenth;                                                        //数据传输长度
  15.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                //外设非增量模式
  16.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        //存储器增量模式
  17.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //外设数据长度:8位
  18.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //存储器数据长度:8位
  19.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        //使用普通模式
  20.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                                        //中等优先级
  21.         DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  22.         DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  23.         DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                                //存储器突发单次传输
  24.         DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;                //外设突发单次传输
  25.         DMA_Init(DMA1_Stream6, &DMA_InitStructure);                                                                //初始化DMA Stream
  26. }
复制代码

5.jpg
4.jpg
3.jpg

最佳答案

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

等待DMA1_Stream6传输完成 用while没完成就好了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2020-5-1 16:54:17 | 显示全部楼层
等待DMA1_Stream6传输完成 用while没完成就好了
回复

使用道具 举报

1

主题

10

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1436
金钱
1436
注册时间
2016-7-6
在线时间
161 小时
 楼主| 发表于 2020-5-1 19:11:54 | 显示全部楼层
nashui_sx 发表于 2020-5-1 18:46
等待DMA1_Stream6传输完成 用while没完成就好了

果然问题解决了。感谢解惑!令我茅塞顿开!
回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2020-5-1 19:52:36 | 显示全部楼层
本帖最后由 nashui_sx 于 2020-5-1 19:56 编辑
guiguziqin 发表于 2020-5-1 19:11
果然问题解决了。感谢解惑!令我茅塞顿开!

原因就是ENABLE 后你if  还没传输完成i行就过去了 新的循环了vTaskDelayUntil tick能++两个

你把vTaskDelayUntil减小到10 应该就是间隔20个了,所以要while住等待发完在循环  
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-28 01:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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