FPGA(主机)STM32(从机)SPI通信(HAL库实现)

本文记录了一次使用FPGA作为主机,通过ADC模块采集信号,存储到RAM中,然后通过SPI与STM32单片机进行数据传输的过程。在STM32端,数据被打印到串口并最终由Excel显示。作者遇到并解决了数据丢失的问题,包括SPI通信的优化和STM32电源问题。此外,还提到了在FFT应用中RAM大小的调整和数据接收点的选择策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FPGA 作主机,
传输ADC的数据
STM32F4 作从机。

1、FPGA通过ADC模块采集信号(AD9220 10M采样率的模块)

我这是12位的就接了12根引脚,和一根10M时钟线

2、存储到RAM中

设置12位 258字的RAM (设置>=258)
勾选读使能

ram u_ram(
	.address	(address),
	.clock	(clk10M), 
	.data		(Data),
	.rden		(rden),
	.wren		(wren),
	.q			(q)
);

读写的过程(暂时没优化)

always@(posedge clk10M, negedge rst_n)
	if(!rst_n)
		begin 
		address<=0;
		wren<=1;
		flag<=0;
		tend<=0;
		start<=0;
		end
	else if(address<=260&&wren==1&&flag==0)
		begin
				if(address==260) 			//写完了开始读
				begin 
					flag<=1; 
					wren<=0;
					address<=0;
					rden<=1;				
					start<=1;			
				end
			else
				address<=address+1;	//地址+1
		end
	else if(flag==1&&rden==1&&address<=260&&nc==1&&tend==0)
		begin
			if(Start==0)begin
				address<=0;
				add0<=0; end				
			else if(add0==0)begin//延时一个周期,读取地址0的数据  这个没用了
				address<=0;
				add0<=1;
			end
				
			else	if(address==260)
				begin
					flag<=0;
					wren<=1;
					address<=0;
					rden<=0;						//读完重写
					tend<=1;
					start<=0;
				end
			else
				
				address<=address+1;
				tend<=1;							//SPI传输完才进行地址增加
				
		end
	else if(address>260)
		address<=0;
	else 
	begin
		if(nc==0)tend<=0;
		address<=address;						//地址不变
	end

(可能fifo更简便些,只是想试一试RAM)

因为要做FFT,所以需要256个点,但是为什么RAM设置>256的深度,经过反复的测试,在FPGA发送第一数据时,单片机可能跳过了,所以我选择往后移几个点接收。

3、通过SPI与单片机进行数据传输(POL=1,PHA=1)

SPI 我的结构
顶层模块,例化了,计数,sck,数据移位三个模块
这个比较复杂,可以直接套网上的代码

Start为单片机发送的开始传输的标志

在这里插入图片描述

4、单片机SPI采集到信号打印到串口上

这里有一点 MOSI 接 MOSI 而不像串口反接
在这里插入图片描述

在这里插入图片描述

  while (1)
  {
    HAL_GPIO_WritePin(Start_GPIO_Port,Start_Pin,GPIO_PIN_RESET);
	HAL_Delay(100);
	HAL_GPIO_WritePin(Start_GPIO_Port,Start_Pin,GPIO_PIN_SET);
	HAL_SPI_Receive(&hspi1,(uint8_t *)data2,259,0xff);
	for(int i=2;i<258;i++)
		printf("%d\r\n",data2[i]);	//不管黑白猫,能得到正确的数据,就行		
		HAL_Delay(2000);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

5、由EXCEL显示出来

最终展示一下采集到的信号 500kHz
在这里插入图片描述

6、Github

FPGA和STM32工程文件

7、踩坑记录

完成这个花费了4天时间,踩了许多坑
因为STM32没接电源导致数据丢失就成了下面这图,还花费了一天去检查
在这里插入图片描述


2021.9.26 日复测,距离上次完成过了20天左右
这一次失败了,莫名出现了如上图的丢包现象


9.28
换了stm32的spi1(之前为spi2) 成功采集500kHz的三角波
原因推测,可能是硬件NSS口出问题

但是出现了第一个数据丢失的情况,所以我就不再循规蹈矩,谁说了一定要从ram的第一个发送,我第3个不行吗?
在这里插入图片描述


23/4/26
代码已经上传到github上了,有需要的自取。
曾经写的代码,虽然能用,但是感觉很垃圾(>_<) ,各位可以修改一番。

### FPGA实现SPI #### 硬件连接 当FPGA作为SPI时,硬件连接相对简单。通常只需要四条线即可完成基本的通信功能:SCK(串行时钟)、MOSI(主输出从输入)、MISO(主输入从输出)和SS/CS(片选)。这些信号线负责协调主机与从之间的数据交换过程[^4]。 对于具体的应用场景而言,在实际搭建电路过程中还需要考虑其他因素,比如电源供电、地线连接等辅助线路的设计以确保整个系统的稳定运行。此外,某些情况下可能还会涉及到额外的状态指示灯或者调试接口的设置以便更好地监控工作状态。 #### 开发教程概述 针对希望利用FPGA构建高效可靠的SPI解决方案的需求方来说,《SPI-FPGA》开源项目提供了详尽指导和支持材料。此资源不仅涵盖了理论知识介绍还包含了实践操作指南,帮助使用者快速入门并深入理解相关技术要点[^1]。 该文档会引导读者逐步建立起自己的SPI模块,并详细介绍每一个环节背后的工作原理;同时也会分享一些常见错误排查技巧以及优化建议等内容,使得即便是初学者也能顺利完成任务目标。 #### 示例代码片段 下面给出一段基于Verilog编写的简易版SPI逻辑框架供参考: ```verilog module spi_slave ( input wire clk, // 主时钟 input wire rst_n, // 复位信号(低电平有效) input wire sclk, // SPI时钟 input wire mosi, // 来自主机的数据流 output reg miso, // 发送给主机的数据流 input wire ss_n // 片选信号(低电平激活) ); // 定义内部寄存器变量... always @(posedge clk or negedge rst_n) begin if (!rst_n) begin // 初始化处理... end else if (!ss_n && sclk) begin // 数据接收及发送流程控制... end end endmodule ``` 上述代码仅为示意性质,实际应用中需根据特定需求调整参数配置并完善细节部分的功能实现
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花椒且喵酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值