当前位置:   article > 正文

STM32使用外部触发DMA并通过FMC总线传输数据_fmc和stm32

fmc和stm32

1.硬件部分

单片机使用STM32F103ZET6,触发源选择信号发生器,该信号发生器产生4us脉冲,触发DMA。本文同时使用信号发生器的信号触发FMC的计数脉冲计数,使用ACTEL 的型号为ProASIC A3P250 VQG100的FPGA产生FMC计数脉冲(FMC传输数据的宽度),本文使用了一个三位计数器产生0-7计数(使用到3位FMC数据线)。


2.软件配置

本文使用高级定时器TIM8,当外部触发该定时器时,该定时器产生连续的16个脉冲,每个脉冲长度位为250ns,16个脉冲的总长为4us。TIM8配置如图所示:选择从模式为触发模式,触发源为外部触发ETR1,该脚硬件连接到信号发生器的输出脚。使用TIM8的单脉冲模式,在CH4通道产生输出捕获比较信号,重复计数器的值为16。

FMC配置如图:选择NE1作为源地址(NE1地址为0X60000000),选择数据位数为16位。将datasetup time设为1,bus turn around time 设为1。

TIM8的DMA中断传输配置如图:源地址不变,目标地址每次+1。

3.程序代码

FPGA产生FMC计数程序为:

  1. module FMC_DMA_Data( sys_clk, sys_rst_n,data_dma,fc_trigger );
  2. input sys_clk, sys_rst_n;
  3. input fc_trigger;//信号发生器的输出作为输入
  4. output [2:0]data_dma;//产生FMC计数,验证DMA传输是否有误
  5. reg [2:0]data_dma1;
  6. //捕获信号发生器信号的下降沿
  7. reg [1:0]delay1_fc_trigger;
  8. always@(posedge sys_clk or negedge sys_rst_n)
  9. begin
  10. if(! sys_rst_n)
  11. delay1_fc_trigger=1'b0;
  12. else
  13. delay1_fc_trigger={delay1_fc_trigger,fc_trigger};
  14. end
  15. wire neg_fc_trigger;
  16. assign neg_fc_trigger=(delay1_fc_trigger[1])&(~delay1_fc_trigger[0]);
  17. //在信号发生器的下降沿计数
  18. always@(posedge sys_clk or negedge sys_rst_n)
  19. begin
  20. if(! sys_rst_n)
  21. begin
  22. data_dma1<=3'd0;
  23. end
  24. else if(data_dma1==3'd7&&neg_fc_trigger)
  25. data_dma1<=3'd0;
  26. else if(data_dma1<3'd7&&neg_fc_trigger)
  27. data_dma1<=data_dma1+1'b1;
  28. end
  29. assign data_dma=data_dma1;
  30. //<statements>
  31. endmodule

main.c函数主要程序为:

  1. uint16_t Read_data[1024];//定义目标地址数据,从源地址中读取数据,数据长度为1024
  2. AD_Address= (uint16_t*)0x60000000;//源地址
  3. //为目标地址数据赋初值,便于观察
  4. for(int i=0;i<1024;i++)
  5. {Read_data2[i]=1023-i;}
  6. HAL_TIM_OC_Start(&htim8,TIM_CHANNEL_4);//开启定时器输出捕获
  7. __HAL_TIM_ENABLE_DMA(&htim8,TIM_DMA_CC4);//使能定时器8DMA,定时器触发DMA源选择输出比较通道4
  8. HAL_DMA_Start_IT(&hdma_tim8_ch4_trig_com,(uint32_t)AD_Address,uint32_t)Read_data, 1024)//开启DMA传输中断,DMA传输长度为1024

it.c文件里的主要代码为:

  1. void DMA2_Channel2_IRQHandler(void)
  2. {
  3. /* USER CODE BEGIN DMA2_Channel2_IRQn 0 */
  4. uint16_t Get_Data[1024];//读取目标地址数据
  5. for(int i=0;i<1024;i++)
  6. {
  7. Get_Data[i]=Read_data2[i]&0007;//因为本文FMC只用到了低3位,所以低三位与1相与
  8. }
  9. /* USER CODE END DMA2_Channel2_IRQn 0 */
  10. HAL_DMA_IRQHandler(&hdma_tim8_ch4_trig_com);//设置断点,进入中断处理程序
  11. /* USER CODE BEGIN DMA2_Channel2_IRQn 1 */
  12. /* USER CODE END DMA2_Channel2_IRQn 1 */
  13. }

注意!!!如果信号发生器上升沿作为计数器计数开始,由捕获输入到FPGA信号的上升沿时间不确定,导致FMC计数和16个DMA信号谁先谁后不确定,计数可能提前或者滞后从而产生数据错误。

所以,采用信号发生器产生的下降沿作为FPGA的输入信号

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/585938
推荐阅读
相关标签
  

闽ICP备14008679号