银杏科技有限公司旗下技术文档发布平台 |
技术支持电话 | 0379-69926675-801 |
技术支持邮件 | Gingko@vip.163.com |
版本 | 日期 | 作者 | 修改内容 |
V1.0 | 2020-03-06 | gingko | 初次建立 |
实验十七:SPI通信实验——基于SPI总线的ARM与FPGA通信
一、 实验目的与意义
掌握SPI通信协议及实现方法。
掌握QuartusII的使用方法。
二、 实验设备及平台
iCore4T 双核心板。
iTool A(或相同功能)仿真器。
USB Type C 线缆。
Keil MDK 开发平台。
Quartus开发平台。
电脑一台。
三、 实验原理
1.SPI简介
2.SPI功能说明
3.SPI通信指令表
指令名称 | 字节1 | 字节2 | 字节3 | 字节4 |
器件ID | 01h | | | |
写数据长度 | 02h | A15~A8 | A7~A0 | |
写数据 | 04h | A15~A8 | A7~A0 | 数据(直至写完所有数据) |
读数据长度 | 05h | A15~A8 | A7~A0 | |
读数据 | 07h | A15~A8 | A7~A0 | 数据(直至读完所有数据) |
读错误信息 | 08h | | | |
ARM与FPGA通信采用的是半双工式通信,FPGA通过识别指令完成与ARM的交互。
器件ID指令为01h,接下来为两字节的伪指令,第四字节仍为伪指令读取ID标志。
写数据长度指令02h,接下来两个字节为写数据的长度,先发高字节,后发低字节,接下来为一个字节的伪指令00h。
写数据指令为04h,接下来为两字节的地址指令,后为要写入的数据,数据写入完毕以伪指令00h结束数据传输。
读数据长度指令05h,接下来两个字节为写数据的长度,先发高字节,后发低字节,接下来为一个字节的伪指令00h。
读数据指令为07h,接下来为两字节的地址指令,其后为伪指令00h开始读取数据进行数据传输,第五字节以后为要读取的数据。
读错误信息指令08h,FPGA接收数据是否出错,先发送两个字节的伪指令,第四字节仍为伪指令读取错误标志信息。
四、 代码讲解
本实验基于ARM+FPGA构架,通过ARM首先发送查询ID指令,然后依次通过指令设置写数据的长度、写数据地址、读数据的长度、读数据的地址,然后对比写入数据和读出数据是否一致判断数据是否写入成功,从而基于SPI总线实现ARM与FPGA之间的通信。
1、更改写数据长度、写数据地址、读数据长度、读数据地址参数时,秩序更改初始化值即可,代码如下:
注意:在设置过程中,地址和长度之和不能大于1024,这是由FPGA内部设置的RAM容量决定的。
//Parameter Value
//注意:地址和长度之和不能大于1024
write_address = 0;
write_length = 1024;
read_address = 0;
read_length = 1024;
//------------------------------------------------//
////////////////按字节接收SPI发送过来的数据//////////////
///////接收模块///////
reg [3:0]receive_state;
reg [7:0]data_in;
reg [7:0]receive_byte_r;
reg spi_rx_en_r;
always@(posedge spi_clk or negedge rst_n or posedge cs_delay)
begin
if((!rst_n)||(cs_delay))
begin
receive_state <= 4'd0;
receive_byte_r <= 8'd0;
data_in <= 8'd0;
spi_rx_en_r <= 1'd0;
end
else //低时钟时可以利用提取沿的方式
begin
case(receive_state) //从高位开始接收数据,每8个spi_clk时钟接收一个Byte
4'd0:begin
receive_state <= receive_state + 1'd1;
data_in <= {data_in[6:0],spi_mosi};
spi_rx_en_r <= 1'd0;
end
4'd1,4'd2:begin
receive_state <= receive_state + 1'd1;
data_in <= {data_in[6:0],spi_mosi};
end
4'd3:begin
receive_state <= receive_state + 1'd1;
data_in <= {data_in[6:0],spi_mosi};
spi_rx_en_r <= 1'd1;
end
4'd4,4'd5:begin
receive_state <= receive_state + 1'd1;
data_in <= {data_in[6:0],spi_mosi};
spi_rx_en_r <= 1'd0;
end
4'd6:begin
receive_state <= receive_state + 1'd1;
data_in <= {data_in[6:0],spi_mosi};
end
4'd7:begin
receive_state <= 4'd0;
data_in <= {data_in[6:0],spi_mosi};
receive_byte_r <= {data_in[6:0],spi_mosi};
end
endcase
end
end
//------------------------------------------------//
///////发送模块///////
reg [3:0]send_state;
reg spi_miso_r;
reg spi_tx_en_r;
reg [7:0]data_out;
always@(negedge spi_clk or negedge rst_n or posedge cs_delay)
if((!rst_n) || (cs_delay))
begin
send_state <= 4'd0;
spi_tx_en_r <= 1'd0;
data_out <= 8'd0;
end
else
begin
case(send_state)
4'd0:begin
spi_miso_r <= data_out[7];
send_state <= send_state + 1'd1;
end
4'd1:begin
spi_miso_r <= data_out[6];
send_state <= send_state + 1'd1;
end
4'd2:begin
spi_miso_r <= data_out[5];
send_state <= send_state + 1'd1;
end
4'd3:begin
spi_miso_r <= data_out[4];
send_state <= send_state + 1'd1;
end
4'd4:begin
spi_miso_r <= data_out[3];
send_state <= send_state + 1'd1;
spi_tx_en_r <= 1'd0;
end
4'd5:begin
spi_miso_r <= data_out[2];
send_state <= send_state+ 1'd1;
spi_tx_en_r <= 1'd1;
end
4'd6:begin
spi_miso_r <= data_out[1];
send_state <= send_state + 1'd1;
spi_tx_en_r <= 1'd0;
end
4'd7:begin
data_out <= send_byte;
spi_miso_r <= data_out[0];
send_state <= 4'd0;
spi_tx_en_r <= 1'd0;
end
endcase
end
五、 实验步骤及实验结果
将硬件正确连接,如图17.2所示。
打开putty串口调试工具,打开设备管理器查看对应的端口信息,在putty中打开对应的端口,用于打印串口信息;
将编写好的FPGA代码进行编译,并下载到开发板中;
将编写好的ARM代码编译,并下载到开发板中,putty工具中会打印相应的SPI通信相关信息;
观察实验现象及putty终端打印信息——FPGA_LED闪烁,putty终端打印如图17.3所示.
六、 拓展实验
通过Signaltap观察SPI通信的时序是否和参考时序一致。
实现错误信息读取指令功能。