OpenEdv-开源电子网

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

用DMA直接驱动GPIO,实现GPIO最高输出速率

  [复制链接]

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
发表于 2015-2-5 16:55:45 | 显示全部楼层 |阅读模式

先上图:STM32F303芯片,72M的主频


可以看到GPIO的达到了14.4M的翻转速率,
      再来上代码:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIOC->MODER |= 0x55555555;
GPIOC->OSPEEDR |= 0xFFFFFFF;
GPIOC->UPDR |= 0x55555555;
u32 Gpio_data[4]= {0x0000FFFF,0xFFFF0000,0x0000FFFF,0xFFFF0000};
DMA_InitTypeDef          DMA_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIMx clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); 
/* DMAx clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 
DMA_DeInit(DMA1_Channel7); 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(GPIOC->BSRR));  
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Gpio_data;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;  
DMA_Init(DMA1_Channel7, &DMA_InitStructure);
DMA1_Channel7->CCR |= DMA_CCR_EN;
        用DMA内存到内存的模式,直接把Gpio_data的数据循环的搬到GPIOC的BSRR寄存器上来控制GPIOC上电平的翻转,这样使得GPIO的速度达到了最快,输出70ns的脉宽,这已经是达到了DMA总线带宽的极限,要想再提高速度的话,就得提高STM32芯片的主频。
      再来看用代码来实现的话,GPIO能达到多快的速度。
    先是用库函数来操作,在Main函数的While循环来翻转电平
while(1)
{
  GPIO_Write(GPIOC,0xffff);
GPIO_Write(GPIOC,0x0000);
}


可以看到最快只能输出320ns的脉宽电平,而且高低电平脉宽还不一样,那是因为处理while(1)占用了CPU的时间导致的。
      再来看用寄存器直接操作GPIO
while(1)
{
   GPIOC->ODR = 0xFFFF;
GPIOC->ODR = 0x0000;
}


可以看到,最小脉宽电平可以达到40ns,直接操作寄存器的速度明显要到库函数操作要快好多,低电平的时间要比高电平的时间长很多,同样也是因为处理while的原因。
      用CPU操作寄存器可以达到最快的电平翻转,但是这样CPU的资源全用在这上面,不能再做其实的操作。如果用DMA的话,完全可以不占用CPU资源来达到更高速率的GPIO翻转速度。假如我们要根据自己的需求来产生我们所需要的时序,那要怎样做。其实也很简单,我们只要用定时器触发DMA搬一次数据到BSRR寄存器,然后再通过调整Gpio_data数组里的数据,就可以来实现我们所要的时序。
下面的代码就是通过这种方式来实现让GPIOC产生1us脉宽的时钟,
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIOC->MODER |= 0x55555555;
GPIOC->OSPEEDR |= 0xFFFFFFF;
GPIOC->UPDR |= 0x55555555;
  u32 Gpio_data[4]= {0x0000FFFF,0xFFFF0000,0x0000FFFF,0xFFFF0000};
   DMA_InitTypeDef          DMA_InitStructure;
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   NVIC_InitTypeDef NVIC_InitStructure;
   /* TIMx clock enable */
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); 
   /* DMAx clock enable */
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 
   DMA_DeInit(DMA1_Channel7); 
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(GPIOC->BSRR));  
   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Gpio_data;
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  
   DMA_InitStructure.DMA_BufferSize = 4;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
   DMA_Init(DMA1_Channel7, &DMA_InitStructure);
 
   TIM_TimeBaseStructure.TIM_Period = 72;          
   TIM_TimeBaseStructure.TIM_Prescaler = 0x0;       
   TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
   TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
 
   TIM_DMACmd(TIM4, TIM_DMA_Update, ENABLE);
   TIM_SelectOutputTrigger(TIM4,TIM_TRGOSource_Update);
   TIM_Cmd(TIM4, ENABLE); 
  DMA1_Channel7->CCR |= DMA_CCR_EN;

已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

64

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
335
金钱
335
注册时间
2014-3-16
在线时间
111 小时
发表于 2016-5-11 21:20:45 | 显示全部楼层
aaronwang 发表于 2016-3-8 12:20
最近和你做了个类似的程序,外设地址设为GPIOE-ODR,DMA1出现数据流传输错误。。不知道有没有解决办法。 ...

f2,f4的DMA1 , 不能访问AHB1/AHB2外设 . DMA1只能做APB1和Memory之间的传输.用DMA2就可以了。
回复 支持 1 反对 0

使用道具 举报

3

主题

197

帖子

0

精华

高级会员

Rank: 4

积分
538
金钱
538
注册时间
2012-7-19
在线时间
63 小时
发表于 2015-7-29 08:43:23 | 显示全部楼层
回复【38楼】mzwhhwj:
---------------------------------
你用的的f3系列,我问f1系列是否可行
回复 支持 0 反对 1

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2015-2-5 22:36:09 | 显示全部楼层
不错,很好的帖子,谢谢分享。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

13

主题

314

帖子

0

精华

高级会员

Rank: 4

积分
713
金钱
713
注册时间
2012-7-20
在线时间
102 小时
发表于 2015-2-5 22:46:18 | 显示全部楼层
感谢分享!!!!!!!!
互联网,智能设备爱好者,欢迎讨论任何有意思的想法。
回复 支持 反对

使用道具 举报

170

主题

917

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1824
金钱
1824
注册时间
2013-4-13
在线时间
63 小时
发表于 2015-2-5 22:58:46 | 显示全部楼层
有图有真相。
手艺人要内外兼修。
回复 支持 反对

使用道具 举报

14

主题

1592

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
2622
金钱
2622
注册时间
2014-7-17
在线时间
350 小时
发表于 2015-2-6 00:19:53 | 显示全部楼层
不错啊!!!!
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-2-6 07:39:07 | 显示全部楼层
不错,谢谢分享!!!
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

81

主题

1002

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1876
金钱
1876
注册时间
2014-9-10
在线时间
208 小时
发表于 2015-2-6 08:50:06 | 显示全部楼层
库函数跟寄存器差这么多啊
小小蜗牛
回复 支持 反对

使用道具 举报

0

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
92
金钱
92
注册时间
2014-11-15
在线时间
9 小时
发表于 2015-2-6 17:29:08 | 显示全部楼层
有意思!想法不错!
回复 支持 反对

使用道具 举报

109

主题

1606

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2222
金钱
2222
注册时间
2011-12-15
在线时间
37 小时
发表于 2015-2-12 16:21:53 | 显示全部楼层
不错,写的很好。
专业制作STM32 物联网通信模块板,模块交流群:369840039。
回复 支持 反对

使用道具 举报

79

主题

534

帖子

0

精华

高级会员

Rank: 4

积分
756
金钱
756
注册时间
2014-9-30
在线时间
128 小时
发表于 2015-3-8 18:58:16 | 显示全部楼层
  不错不错,,学习了。。。
回复 支持 反对

使用道具 举报

54

主题

194

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
430
金钱
430
注册时间
2013-11-2
在线时间
0 小时
发表于 2015-3-12 21:15:41 | 显示全部楼层
回复【6楼】八度空间:
---------------------------------
这里为什么是选用内存到内存的方式呢?不是把数据搬到了寄存器里面去了吗
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-3-13 12:25:13 | 显示全部楼层
回复【11楼】周小样:
---------------------------------
寄存器就映射到了内存
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

15

主题

181

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2014-11-8
在线时间
40 小时
发表于 2015-3-31 12:46:02 | 显示全部楼层
回复【12楼】八度空间:
---------------------------------
那原子哥的程序把数据发送给USART1->DR为什么选用的不是内存到内存的方式?USART1->DR不也是寄存器吗?求解答
Good good study , day day up...
回复 支持 反对

使用道具 举报

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
 楼主| 发表于 2015-3-31 18:29:42 | 显示全部楼层
回复【13楼】Just Beat It:
---------------------------------
DMA的内存到内存模式话,是没有相关的触发和控制的,按照DMA的最快速度跑。其它的从内存到外设或者从外设到内存模式,都是有相关的外设控制,比如外设的DMA的传输请求、外设相关标志位的清除
已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
回复 支持 反对

使用道具 举报

15

主题

181

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2014-11-8
在线时间
40 小时
发表于 2015-3-31 21:22:23 | 显示全部楼层
回复【14楼】mzwhhwj:
---------------------------------
谢谢
Good good study , day day up...
回复 支持 反对

使用道具 举报

15

主题

181

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2014-11-8
在线时间
40 小时
发表于 2015-3-31 21:33:54 | 显示全部楼层
回复【14楼】mzwhhwj:
---------------------------------
请问楼主为什么要使能TIM4(通道7),tim4是怎么和io口联系起来的?我比较弱,楼主莫怪
Good good study , day day up...
回复 支持 反对

使用道具 举报

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
 楼主| 发表于 2015-3-31 22:42:40 | 显示全部楼层
使能通道7是为了用TIM4定时来触发一次DMA把数据搬到GPIO的寄存器上,这样就可以控制电平的脉宽了
已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
回复 支持 反对

使用道具 举报

15

主题

181

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2014-11-8
在线时间
40 小时
发表于 2015-4-1 11:48:56 | 显示全部楼层
回复【17楼】mzwhhwj:
---------------------------------
奥奥,谢谢楼主,明白了,十分感谢。。。

 
Good good study , day day up...
回复 支持 反对

使用道具 举报

15

主题

181

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2014-11-8
在线时间
40 小时
发表于 2015-4-3 08:19:58 | 显示全部楼层
回复【14楼】mzwhhwj:
---------------------------------
再问一下,就是为什么原子哥的程序是存储器到外设。TEXT_TO_SEND[]到USART1->DR(存储器到外设) DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 
 你的程序是Gpio_data[4]      到GPIOC->BSRR (存储器到存储器)   DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; 
为什么是存储器到存储器(内存到内存)呢?
这是您的解答:DMA的内存到内存模式话,是没有相关的触发和控制的,按照DMA的最快速度跑。其它的从内存到外设或者从外设到内存模式,都是有相关的外设控制,比如外设的DMA的传输请求、外设相关标志位的清除。
那是不是所有的传输无论源和目标是什么,都可以任意选择这两种模式?
Good good study , day day up...
回复 支持 反对

使用道具 举报

7

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
126
金钱
126
注册时间
2015-2-10
在线时间
10 小时
发表于 2015-6-9 09:34:08 | 显示全部楼层
感谢楼主,正在为这两个问题纠结,一个是DMA实现内存到内存,一个是TIMER触发DMA,正好原子哥的例程上没有提到这两个函数,再次感谢!
STM32还是有搞头的..
回复 支持 反对

使用道具 举报

0

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2015-6-15
在线时间
9 小时
发表于 2015-6-15 17:44:56 | 显示全部楼层
感谢楼主共享,学习了。
回复 支持 反对

使用道具 举报

0

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2015-6-15
在线时间
9 小时
发表于 2015-6-16 10:13:45 | 显示全部楼层


我用楼主提供的方式来操作spi,结果spi不能主动提供时钟。看来这东西只对部分外设有用。
回复 支持 反对

使用道具 举报

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
 楼主| 发表于 2015-6-16 10:37:44 | 显示全部楼层
回复【22楼】今时今日:
---------------------------------
你的配置有没问题吧,我也有这么做,没有问题的,SPI的主模式,只要往DR寄存器填值,SPI就会产生时钟把数据发出去
已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
回复 支持 反对

使用道具 举报

0

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2015-6-15
在线时间
9 小时
发表于 2015-6-16 11:52:50 | 显示全部楼层
回复【23楼】mzwhhwj:
---------------------------------
我的定时器复杂了点,可能是我配置出问题了,我再试试。
回复 支持 反对

使用道具 举报

0

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2015-6-15
在线时间
9 小时
发表于 2015-6-16 11:54:38 | 显示全部楼层
回复【23楼】mzwhhwj:
---------------------------------
回复【23楼】mzwhhwj:
---------------------------------
我确认我的dma触发了,因为我设置了dma满中断,这个中断服务函数进去了
回复 支持 反对

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2015-7-17
在线时间
1 小时
发表于 2015-7-17 09:24:32 | 显示全部楼层
GPIOC->MODER |= 0x55555555;
GPIOC->OSPEEDR |= 0xFFFFFFF;
GPIOC->UPDR |= 0x55555555; 
DMA1_Channel7->CCR |= DMA_CCR_EN;

会报错User\DMA_GPIO.h(13): error:  #136: struct "<unnamed>" has no field "MODER"

也是刚学!!
不断努力
回复 支持 反对

使用道具 举报

11

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2014-11-12
在线时间
0 小时
发表于 2015-7-18 20:56:43 | 显示全部楼层
mark 学习了,另外教楼主一个知识点,while(1)有的编译器要占用机器周期,但是for(;;)这个循环是不会占用的,楼主日后可以用这个循环来测试
回复 支持 反对

使用道具 举报

54

主题

194

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
430
金钱
430
注册时间
2013-11-2
在线时间
0 小时
发表于 2015-7-20 17:54:14 | 显示全部楼层
回复【12楼】八度空间:
---------------------------------
亲,我还是不懂,STM32外设和内存sram都是两块不同的区域,怎么会使寄存器映射到内存呢?
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-7-20 22:21:54 | 显示全部楼层
回复【28楼】周小样:
---------------------------------
数据搬运
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2015-7-23
在线时间
1 小时
发表于 2015-7-23 10:32:25 | 显示全部楼层
学习了,谢谢
你问我要去向何方,我指着大海的方向!
回复 支持 反对

使用道具 举报

3

主题

197

帖子

0

精华

高级会员

Rank: 4

积分
538
金钱
538
注册时间
2012-7-19
在线时间
63 小时
发表于 2015-7-23 14:46:05 | 显示全部楼层
有个疑问,是不是只有ahb设备上的gpio可以使用dma啊,f1的gpio是挂在apb总线上的,能不能用dma呢
回复 支持 反对

使用道具 举报

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
 楼主| 发表于 2015-7-23 15:24:12 | 显示全部楼层
回复【31楼】myxiaoniao:
---------------------------------
所有挂在总线上的外设都可以用DMA
已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
回复 支持 反对

使用道具 举报

3

主题

197

帖子

0

精华

高级会员

Rank: 4

积分
538
金钱
538
注册时间
2012-7-19
在线时间
63 小时
发表于 2015-7-24 09:54:29 | 显示全部楼层
回复【32楼】mzwhhwj:
---------------------------------
f1可不是所有外设都有dma支持的,一般ahb外设是用m2m模式进行,apb上不支持dma的外设也能用m2m模式支持吗
回复 支持 反对

使用道具 举报

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
 楼主| 发表于 2015-7-24 15:26:29 | 显示全部楼层
回复【33楼】myxiaoniao:
---------------------------------
可以的,外设的所有寄存器都是映射在总线上的,都可以用DMA,但是如果外设没有对应的DMA通道的话,就没有相应的一些硬件操作,比如DMA的触发,标志的清除或者置位,这样用起来就会有问题,所以最好是借助其它的通道来实现,我帖子里的做法就是借助Timer通道来实现,
已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
回复 支持 反对

使用道具 举报

3

主题

197

帖子

0

精华

高级会员

Rank: 4

积分
538
金钱
538
注册时间
2012-7-19
在线时间
63 小时
发表于 2015-7-25 09:26:54 | 显示全部楼层
回复【34楼】mzwhhwj:
---------------------------------
你是用tim产生的dma请求吗?溢出中断?可是你代码中没有具体配置这个tim

事实上  ahb外设都是可以用dma的m2m模式传递的,但是我看有人想在apb外设上这么做最后都失败了,只能借助其他外设间接做到
回复 支持 反对

使用道具 举报

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
 楼主| 发表于 2015-7-27 08:54:33 | 显示全部楼层
回复【35楼】myxiaoniao:
---------------------------------
看我帖子写在最后面的那段代码就是用Timer的Updata来做DMA的请求,外设是可以用M2M的模式来传递,但是很多的外设的速度远比DMA总线的速度慢,而M2M模式是没有DMA是请求的,只要开启DMA,DMA就会按总线的速度在搬运数据,像串口如果用M2M模式话,估计DMA搬了几百上千个数据到DR上,但串口连一个数据都还没有发送完,这样有啥意义啊,
已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
回复 支持 反对

使用道具 举报

3

主题

197

帖子

0

精华

高级会员

Rank: 4

积分
538
金钱
538
注册时间
2012-7-19
在线时间
63 小时
发表于 2015-7-28 09:53:00 | 显示全部楼层
回复【36楼】mzwhhwj:
---------------------------------
下一段是更新没错,但是这完全可以用tim的更新dma触发,我看你代码也没有使用m2m模式 

我的意思  就是纯粹的dma用m2m模式,挂在ahb总线的外设都可以和内存用m2m搬运这个没问题  我用crc实践过  我在amo上还有发贴过
但是f1的gpio并不是挂在ahb而是apb上的,我就想请教下这个是否也行,看样子你没有尝试过f1的gpio直接用dma传输,这个问题还是不清楚了
回复 支持 反对

使用道具 举报

58

主题

499

帖子

4

精华

金牌会员

Rank: 6Rank: 6

积分
1920
金钱
1920
注册时间
2013-11-18
在线时间
268 小时
 楼主| 发表于 2015-7-28 11:37:49 | 显示全部楼层
回复【37楼】myxiaoniao:
---------------------------------
第一段代码就是用M2M模式把数据搬到GPIO上
已经放下多年的FPGA,要重新再拾起来,却是如此的陌生
回复 支持 反对

使用道具 举报

13

主题

276

帖子

0

精华

高级会员

Rank: 4

积分
697
金钱
697
注册时间
2014-6-20
在线时间
146 小时
发表于 2016-1-4 21:05:15 | 显示全部楼层
确实是好东西,
回复 支持 反对

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2016-1-4 21:49:13 | 显示全部楼层
谢谢楼主分享,学习了!很不错的想法
回复 支持 反对

使用道具 举报

0

主题

15

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
274
金钱
274
注册时间
2014-12-9
在线时间
60 小时
发表于 2016-1-5 12:12:59 | 显示全部楼层
谢谢,分享,之前也纠结过这个问题。
回复 支持 反对

使用道具 举报

1

主题

80

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2996
金钱
2996
注册时间
2015-3-29
在线时间
292 小时
发表于 2016-1-26 12:39:41 | 显示全部楼层
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2016-3-1
在线时间
11 小时
发表于 2016-3-1 09:27:30 | 显示全部楼层
求教大家,我也是用了类似的方法:TIM4 定时通过DMA来修改GPIOE的值,却修改不了;调试中发现DMA也启动了,因通过寄存器发现为修改TIM4 CCR1的值是能修改了,
但GPIOE->ODR或GPIOE->BSRR却不行,用的STM32F407,下面是我的代码:


#define TIM4_CCR1_ADDRESS  ((uint32)0x40000834) /* TIM4 CCR1 address */
#define GPIOE_ODR_ADDRESS  ((uint32)0x40021014) /*  address */

uint16 a_SRC_Buffer[4] = {0x0023, 0x0045, 0x00d3, 0x004a};
/*
**********************************************************************************************
函 数 名: TIM_GPIO_Init     TIM4  
功    能:定时器输出通道GPIO初始化  
参    数: 无
返    回: 无
**********************************************************************************************
*/
void TIM_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  DMA_InitTypeDef          DMA_InitStructure;

  /* TIM4 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_TIM4, ENABLE);

  /* GPIOA clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1PERIPH_GPIOD | RCC_AHB1PERIPH_GPIOE, ENABLE);

  /* DMA1 clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1PERIPH_DMA1, ENABLE);
  
  /* GPIOA Configuration: PD12(TIM4 CH1) as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_12;
  GPIO_InitStructure.e_GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.e_GPIO_Speed = GPIO_SPEED_100MHZ;
  GPIO_InitStructure.e_GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.e_GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  /* Connect TIM pins to AF1 */
  GPIO_PinAFConfig(GPIOD, GPIO_PIN_SOURCE12, GPIO_AF_TIM4);
  
  /* DeInitialize the DMA1 Stream6 */
  DMA_DeInit(DMA1_Stream6);

  DMA_InitStructure.DMA_Channel = DMA_Channel_2;
//  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)(&(GPIOE->ODR)); //&(GPIOE->BSRRL)  值没有变化
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)(TIM4_CCR1_ADDRESS);  /* 可以正常修改它的值 */
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32)a_SRC_Buffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = 4;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA1_Stream6, &DMA_InitStructure);
}

/*
**********************************************************************************************
函 数 名: TIM_DMA_Output_Init
功    能:定时器DMA方式输出通道初始化  
参    数: 无
返    回: 无
**********************************************************************************************
*/
void TIM_DMA_Output_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;

  TIM_TimeBaseStructure.TIM_Period = 1000;         
  TIM_TimeBaseStructure.TIM_Prescaler = 42 - 1;      
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;   
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_COUNTERMODE_UP;   
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

  /* TIM Configuration in PWM Mode */
  TIM_OCInitStructure.TIM_OCMode =  TIM_OCMode_Toggle;   
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;         
  TIM_OCInitStructure.TIM_Pulse = a_SRC_Buffer[0];//0xFFF;  
  TIM_OC1Init(TIM4, &TIM_OCInitStructure);

  /* TIM4 DMA Update enable */
  TIM_DMACmd(TIM4, TIM_DMA_Update, ENABLE);
       
        TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update);

  /* TIM4 enable */
  TIM_Cmd(TIM4, ENABLE);
  
  /* TIM4 PWM Outputs Enable */
//  TIM_CtrlPWMOutputs(TIM4, ENABLE);

  /* Enable DMA2 Stream5  */
  DMA_Cmd(DMA1_Stream6, ENABLE);

//  /* Wait until DMA1 Stream6 end of Transfer */
//  while (!DMA_GetFlagStatus(DMA1_Stream6, DMA_FLAG_TCIF6))
//  {
//  }
}

void TLC7524_GPIO_Init(void)
{
  GPIO_InitTypeDef  s_GPIO_InitStructure;

  /* Enable GPIOs clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1PERIPH_GPIOD | RCC_AHB1PERIPH_GPIOE, ENABLE);
  
  /* GPIOI configuration */
  s_GPIO_InitStructure.GPIO_Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
  s_GPIO_InitStructure.e_GPIO_Mode = GPIO_Mode_OUT;
  s_GPIO_InitStructure.e_GPIO_OType = GPIO_OType_PP;
  s_GPIO_InitStructure.e_GPIO_Speed = GPIO_SPEED_100MHZ;
  s_GPIO_InitStructure.e_GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOE, &s_GPIO_InitStructure);
}
回复 支持 反对

使用道具 举报

6

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
111
金钱
111
注册时间
2016-1-16
在线时间
23 小时
发表于 2016-3-1 12:14:51 | 显示全部楼层
有没有寄存器版本的呢
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2016-3-5
在线时间
4 小时
发表于 2016-3-8 12:20:51 | 显示全部楼层
steel_2006 发表于 2016-3-1 09:27
求教大家,我也是用了类似的方法:TIM4 定时通过DMA来修改GPIOE的值,却修改不了;调试中发现DMA也启动了, ...

最近和你做了个类似的程序,外设地址设为GPIOE-ODR,DMA1出现数据流传输错误。。不知道有没有解决办法。。
回复 支持 反对

使用道具 举报

8

主题

39

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2015-6-9
在线时间
41 小时
发表于 2016-4-18 10:02:13 | 显示全部楼层
你好,请问这种方法IO输入检测可以做到这么快的速度吗?谢谢!
回复 支持 反对

使用道具 举报

特立独行的猪 该用户已被删除
发表于 2016-7-20 20:17:20 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2016-9-18
在线时间
13 小时
发表于 2016-10-26 10:15:17 | 显示全部楼层
不知道有人用F4系列做过类似的实验没有?
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-25 15:29

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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