STM32与FPGA进行SPI通信

一、器件

32单片机:STM32F407ZG

FPGA     :EP4CE6E22C8N

二、通信方式

STM32作为主机(软件);

FPGA作为从机;

SPI通信方式为0;

三、STM32源代码

 1 #include "delay.h"
 2 #include "stm32f4xx.h"
 3
 4 #ifndef __SPI_H
 5 #define __SPI_H
 6
 7 #define    SPI1_SCK        PBout(2)
 8 #define    SPI1_MOSI        PBout(3)
 9 #define SPI1_MISO   PBin(4)
10 #define    CS                    PBout(5)
11
12 //CPOL=0,CPHA=0
13 u8 SOFT_SPI_RW(u8 byte);
14 //SPI初始化
15 void SPIInit(void);
16
17 #endif

spi.h

 1 #include "spi.h"
 2 #include "delay.h"
 3 #include "stm32f4xx.h"
 4
 5 //CPOL=0,CPHA=0
 6 u8 SOFT_SPI_RW(u8 byte)
 7 {
 8     u8 i;
 9     u8 Temp=0;                                                //接收数据存储
10     SPI1_SCK = 0;
11     delay_init(168);                                    //初始化延时函数
12     for(i=0;i<8;i++)                                // 循环8次
13     {
14         if(byte&0x80) SPI1_MOSI = 1;      //若字节最高位为1,则输出高
15         else SPI1_MOSI = 0;                //若字节最高位为0,则输出低
16         byte <<= 1;                                        //低一位移位到最高位
17         delay_us(1);                                        //延时1us
18         SPI1_SCK = 1;                                    //拉低时钟
19         Temp <<= 1;                                        //数据左移
20         if(SPI1_MISO) Temp++;                        //若从从机接收到高电平,数据自加一
21         delay_us(1);                                        //延时1us
22         SPI1_SCK = 0;                                        //拉低时钟
23     }
24     return (Temp);                                        //返回数据
25 }
26
27 void SPIInit(void)
28 {
29     GPIO_InitTypeDef GPIO_InitStructure;
30     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//使能PORTB时钟
31
32     //PB2,PB3,PB5设置
33   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5;
34   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
35   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
36   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
37   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
38     GPIO_Init(GPIOB,&GPIO_InitStructure);
39     //PB4设置
40     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
41   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
42   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
43   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
44   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
45     GPIO_Init(GPIOB,&GPIO_InitStructure);
46 }

spi.c

四、FPGA源代码

  1 //FPGA作为从设备
  2 module spi_s(I_clk,I_rst_n,I_data_in,O_data_out,O_tx_done,O_rx_done,I_spi_miso,I_spi_sck,I_spi_cs,O_spi_mosi,sck_posedge,sck_negedge,rxd_flag,txd_flag);
  3 input I_clk;                //全局时钟50MHz
  4 input I_rst_n;                //复位信号,低电平有效
  5 //input I_rx_en;                //读(接收)使能信号
  6 //input I_tx_en;                //写(发送)使能信号
  7 input [7:0]I_data_in;    //要发送的数据
  8 output[7:0]O_data_out;    //接收到的数据
  9 output O_tx_done;            //发送一个数据完毕标志位
 10 output O_rx_done;            //接收一个字节完毕标志位
 11
 12 //四线标准SPI信号定义
 13 input I_spi_miso;            //SPI串行输入,用来接收从机的数据
 14 input I_spi_sck;            //SPI时钟
 15 input I_spi_cs;            //SPI片选信号
 16 output O_spi_mosi;        //SPI输出,用来给从机发送数据
 17
 18 output sck_posedge,sck_negedge;
 19 output rxd_flag;//接收标志位
 20 output txd_flag;//发送标志位
 21
 22 reg [7:0] O_data_out;
 23 reg O_tx_done;
 24 reg O_rx_done;
 25 reg O_spi_mosi;
 26
 27 reg [2:0] R_tx_state;
 28 reg [2:0] R_rx_state;
 29
 30 reg sck_r0,sck_r1;//当前SCK态,之前SCK态
 31 wire sck_posedge;    //SCK上升沿
 32 wire sck_negedge;    //SCK下降沿
 33
 34 //获取SCK时钟当前态以及之前态
 35 always @(posedge I_clk,negedge I_rst_n)
 36 begin
 37     if(!I_rst_n)
 38     begin
 39         sck_r0 <= 1‘b0;
 40         sck_r1 <= 1‘b0;//工作方式0,空闲时为低电平
 41     end
 42     else
 43     begin
 44         sck_r0 <= I_spi_sck;    //当前SCK态
 45         sck_r1 <= sck_r0;        //之前SCK态
 46     end
 47 end
 48
 49 //捕获SCK时钟上升沿以及下降沿
 50 assign sck_posedge = (~sck_r0 & sck_r1)? 1‘b1:1‘b0;//上升沿
 51 assign sck_negedge = (~sck_r1 & sck_r0)? 1‘b1:1‘b0;//下降沿
 52
 53 //发送数据触发
 54 always @(posedge I_clk,negedge I_rst_n)
 55 begin
 56     //置位
 57     if(!I_rst_n)
 58     begin
 59             R_tx_state <= 3‘b0;
 60             O_spi_mosi <= 1‘b0;
 61             O_tx_done <= 0;
 62     end
 63     //SCK上跳沿时发送数据(方式0)
 64     else if(sck_posedge && !I_spi_cs)
 65     begin
 66         case(R_tx_state)
 67             3‘d0://发送第七位
 68             begin
 69                 O_spi_mosi <= I_data_in[7];
 70                 R_tx_state <= R_tx_state + 1‘b1;
 71                 O_tx_done <= 1‘b0;
 72             end
 73             3‘d1://发送第六位
 74             begin
 75                 O_spi_mosi <= I_data_in[6];
 76                 R_tx_state <= R_tx_state + 1‘b1;
 77                 O_tx_done <= 1‘b0;
 78             end
 79             3‘d2://发送第五位
 80             begin
 81                 O_spi_mosi <= I_data_in[5];
 82                 R_tx_state <= R_tx_state + 1‘b1;
 83                 O_tx_done <= 1‘b0;
 84             end
 85             3‘d3://发送第四位
 86             begin
 87                 O_spi_mosi <= I_data_in[4];
 88                 R_tx_state <= R_tx_state + 1‘b1;
 89                 O_tx_done <= 1‘b0;
 90             end
 91             3‘d4://发送第三位
 92             begin
 93                 O_spi_mosi <= I_data_in[3];
 94                 R_tx_state <= R_tx_state + 1‘b1;
 95                 O_tx_done <= 1‘b0;
 96             end
 97             3‘d5://发送第二位
 98             begin
 99                 O_spi_mosi <= I_data_in[2];
100                 R_tx_state <= R_tx_state + 1‘b1;
101                 O_tx_done <= 1‘b0;
102             end
103             3‘d6://发送第一位
104             begin
105                 O_spi_mosi <= I_data_in[1];
106                 R_tx_state <= R_tx_state + 1‘b1;
107                 O_tx_done <= 1‘b0;
108             end
109             3‘d7://发送第零位
110             begin
111                 O_spi_mosi <= I_data_in[0];
112                 R_tx_state <= R_tx_state + 1‘b1;
113                 O_tx_done <= 1‘b1;//发送完毕
114             end
115             default:R_tx_state <= 3‘d0;
116         endcase
117     end
118 end
119
120
121
122 //接收数据触发
123 always @(posedge I_clk,negedge I_rst_n)
124 begin
125     if(!I_rst_n)
126     begin
127         O_data_out <= 8‘b0;
128         R_rx_state <= 3‘b0;
129         O_rx_done <= 1‘b0;
130     end
131     else if(sck_negedge && !I_spi_cs)
132         case(R_rx_state)
133             3‘d0://接收第七位
134             begin
135                 R_rx_state <= R_rx_state + 1‘b1;
136                 O_rx_done <= 1‘b0;
137                 O_data_out[7] <= I_spi_miso;
138             end
139             3‘d1://接收第六位
140             begin
141                 R_rx_state <= R_rx_state + 1‘b1;
142                 O_rx_done <= 1‘b0;
143                 O_data_out[6] <= I_spi_miso;
144             end
145             3‘d2://接收第五位
146             begin
147                 R_rx_state <= R_rx_state + 1‘b1;
148                 O_rx_done <= 1‘b0;
149                 O_data_out[5] <= I_spi_miso;
150             end
151             3‘d3://接收第四位
152             begin
153                 R_rx_state <= R_rx_state + 1‘b1;
154                 O_rx_done <= 1‘b0;
155                 O_data_out[4] <= I_spi_miso;
156             end
157             3‘d4://接收第三位
158             begin
159                 R_rx_state <= R_rx_state + 1‘b1;
160                 O_rx_done <= 1‘b0;
161                 O_data_out[3] <= I_spi_miso;
162             end
163             3‘d5://接收第二位
164             begin
165                 R_rx_state <= R_rx_state + 1‘b1;
166                 O_rx_done <= 1‘b0;
167                 O_data_out[2] <= I_spi_miso;
168             end
169             3‘d6://接收第一位
170             begin
171                 R_rx_state <= R_rx_state + 1‘b1;
172                 O_rx_done <= 1‘b0;
173                 O_data_out[1] <= I_spi_miso;
174             end
175             3‘d7://接收第零位
176             begin
177                 R_rx_state <= R_rx_state + 1‘b1;
178                 O_rx_done <= 1‘b1;//接收完毕
179                 O_data_out[0] <= I_spi_miso;
180             end
181             default:R_rx_state <= 3‘d0;
182         endcase
183 end
184
185 reg rxd_flag_r0,rxd_flag_r1;//接收标志位(当前态),接收标志位(之前态)
186 [email protected](posedge I_clk or negedge I_rst_n)
187 begin
188     if(!I_rst_n)
189         begin
190             rxd_flag_r0 <= 1‘b0;
191             rxd_flag_r1 <= 1‘b0;
192         end
193     else
194         begin
195             rxd_flag_r0 <= O_rx_done;
196             rxd_flag_r1 <= rxd_flag_r0;
197         end
198 end
199 //接收标志位
200 assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1‘b1:1‘b0;
201
202 reg txd_flag_r0,txd_flag_r1;//发送标志位(当前态),发送标志位(之前态)
203 [email protected](posedge I_clk or negedge I_rst_n)
204 begin
205     if(!I_rst_n)
206         begin
207             txd_flag_r0 <= 1‘b0;
208             txd_flag_r1 <= 1‘b0;
209         end
210     else
211         begin
212             txd_flag_r0 <= O_tx_done;
213             txd_flag_r1 <= txd_flag_r0;
214         end
215 end
216 //发送标志位
217 assign txd_flag = (~txd_flag_r1 & txd_flag_r0)? 1‘b1:1‘b0;
218
219
220 endmodule

spi_s.v

  1 `timescale 1 ns/ 1 ps
  2 module spi_s_vlg_tst();
  3 // constants
  4 // general purpose registers
  5 reg eachvec;
  6 // test vector input registers
  7 reg I_clk;
  8 reg [7:0] I_data_in;
  9 reg I_rst_n;
 10 reg I_spi_cs;
 11 reg I_spi_miso;
 12 reg I_spi_sck;
 13 // wires
 14 wire [7:0]  O_data_out;
 15 wire O_rx_done;
 16 wire O_spi_mosi;
 17 wire O_tx_done;
 18 wire rxd_flag;
 19 wire sck_negedge;
 20 wire sck_posedge;
 21 wire txd_flag;
 22
 23 // assign statements (if any)
 24 spi_s i1 (
 25 // port map - connection between master ports and signals/registers
 26     .I_clk(I_clk),
 27     .I_data_in(I_data_in),
 28     .I_rst_n(I_rst_n),
 29     .I_spi_cs(I_spi_cs),
 30     .I_spi_miso(I_spi_miso),
 31     .I_spi_sck(I_spi_sck),
 32     .O_data_out(O_data_out),
 33     .O_rx_done(O_rx_done),
 34     .O_spi_mosi(O_spi_mosi),
 35     .O_tx_done(O_tx_done),
 36     .rxd_flag(rxd_flag),
 37     .sck_negedge(sck_negedge),
 38     .sck_posedge(sck_posedge),
 39     .txd_flag(txd_flag)
 40 );
 41 reg [2:0]state;
 42 initial
 43 begin
 44     I_clk = 0;
 45     I_rst_n = 0;
 46     I_data_in = 8‘h00;
 47     I_spi_miso = 0;
 48     I_spi_cs = 1;
 49     I_spi_sck = 0;
 50     #100
 51     I_rst_n = 1;
 52     I_spi_cs = 0;
 53 end
 54 always
 55 begin
 56     #10 I_clk = ~I_clk;
 57 end
 58
 59 always
 60 begin
 61     #20 I_spi_sck = ~I_spi_sck;
 62 end
 63
 64 always @(posedge I_spi_sck,negedge I_rst_n)
 65 begin
 66     if(!I_rst_n)
 67         I_data_in <= 8‘h00;
 68     else if(I_data_in == 8‘hff)
 69     begin
 70         I_data_in <= 8‘h00;
 71     end
 72     else if(txd_flag)
 73         I_data_in <= I_data_in + 1‘b1;
 74 end
 75 //11101010
 76 always @(negedge I_spi_sck,negedge I_rst_n)
 77 begin
 78     if(!I_rst_n)
 79         state <= 3‘b000;
 80     else
 81     case(state)
 82         3‘d0:
 83         begin
 84             state <= state + 1;
 85             I_spi_miso <= 1‘b1;
 86         end
 87         3‘d1:
 88         begin
 89             state <= state + 1;
 90             I_spi_miso <= 1‘b1;
 91         end
 92         3‘d2:
 93         begin
 94             state <= state + 1;
 95             I_spi_miso <= 1‘b1;
 96         end
 97         3‘d3:
 98         begin
 99             state <= state + 1;
100             I_spi_miso <= 1‘b0;
101         end
102         3‘d4:
103         begin
104             state <= state + 1;
105             I_spi_miso <= 1‘b1;
106         end
107         3‘d5:
108         begin
109             state <= state + 1;
110             I_spi_miso <= 1‘b0;
111         end
112         3‘d6:
113         begin
114             state <= state + 1;
115             I_spi_miso <= 1‘b1;
116         end
117         3‘d7:
118         begin
119             state <= state + 1;
120             I_spi_miso <= 1‘b0;
121         end
122         default:state <= 3‘b000;
123     endcase
124 end
125 endmodule

spi_s.vt(测试代码)

五、仿真波形图

 六、参考资料

https://www.cnblogs.com/wanghuaijun/p/7627065.html

https://blog.csdn.net/weixin_42509369/article/details/83096349

https://blog.csdn.net/qq_22168673/article/details/101546898

https://www.cnblogs.com/liujinggang/p/9609739.html

原文地址:https://www.cnblogs.com/cnlntr/p/12207721.html

时间: 2024-10-04 03:15:40

STM32与FPGA进行SPI通信的相关文章

ARM与FPGA通过spi通信设计1.spi基础知识

SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息.SPI总线可直接与各个厂家生产的多种标准外围器件相连,包括FLASHRAM.网络控制器.LCD显示驱动器.A/D转换器和MCU等. SPI接口是在CPU和外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输,高位在前,低位在后,为全双工通信,数据传输速度总体来说比I2C总线要快,速度可达到几Mbps. 1.接

SPI通信实验---verilog(FPGA作为从机,使用可读可写)

本实验讲究实用性,故设计思想为:主机先向从机发送地址,若是向从机写入数据,则向从机发送数据,若是读取从机数据,则向从机发送时钟,然后在时钟下降沿读取数据即可.cs信号上升沿作为SPI通信的结束信号.rom程序只是做测试使用. 每次发送16个时钟信号,前八个是地址和命令,后八个是数据.其中:前8个时钟接受的数据的最高位决定着这次通信是读取数据还是写入数据,最高位为1,则是读取数据,为0则是写入数据. 程序: /********************************Copyright***

STM32 SPI 通信

SPI  是英语 Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口.是 Motorola首先在其 MC68HCXX 系列处理器上定义的. SPI 接口主要应用在  EEPROM, FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信

SPI通信

SPI是由Motorola公司提出的一种同步串行外围接口:它在速度要求不高,低功耗,需要保存少量参数的智能化传感系统中得到了广泛应用: SPI是一个全双工的同步串行接口,在数据传输过程中,总线上只能是一个主机和一个从机进行通信: 通信四种模式: 1.MISO(Master In Slave Out) 主机输入,从机输出: 2.MOSI(Master  Out  Slave In) 主机输出,从机输入: 3.SCK(Serial  Clock) 串行时钟信号 4.SS(Slave  Select)

ANT无线通信技术(5) ANT与MCU的SPI通信时序分析及相关程序设计

ANT与MCU可以使用异步UART或同步SPI两种方式连接.异步通信与同步通信的各自特点这里不赘述,总之我们选择使用同步方式进行连接. 一.SPI简介 SPI(Serial Peripheral Interface),串行外设接口.是摩托罗拉公司开发的一种同步全双工通信协议.依靠收发两端的移位寄存器,以及主机master提供的时钟信号,双方可以实现较高速率的同步全双工传输. 标准的SPI是3/4根线,分别用于一主一从/多主从的情况.4根线分别是: MOSI 主机发,从机收 master out

SPI 通信

信号组成 链接线 SPI通信过程 主从模式设置 相位和级性 传输格式 设置步骤 发送和接收过程 SPI 通信,布布扣,bubuko.com

[转]SPI通信原理简介

[转自]http://www.cnblogs.com/deng-tao/p/6004280.html 1.前言 SPI是串行外设接口(Serial Peripheral Interface)的缩写.是 Motorola 公司推出的一 种同步串行接口技术,是一种高速的,全双工,同步的通信总线. 2. SPI特点 高速.同步.非差分.总线式.支持全双工通信 主从式通信 通信协议简单 可靠性有缺陷.没有指定的流控制,没有应答机制确认是否接收到数据,所以跟IIC总线协议比较在数据,可靠性上有一定的缺陷.

nrf51822 --- spi 通信

1.目的 nrf51822 spi通信 2.分析 在实际应用中经常要用到spi通信,比如度flash 3.平台: 协议栈版本:SDK10.0.0 编译软件:keil 5.12 硬件平台:微雪开发板nrf51822 例子:SDK 10.0.0\examples\ble_peripheral\ble_app_hrs\pca10028\s110\arm4 4.步骤 1.打开\SDK10.0\components\drivers_nrf\twi_master\deprecated目录 2.把nrf_dr

FPGA设计——SPI Flash启动之MC8051设计

1. 概述 本设计采用FPGA技术,在FPGA中实现8051单片机的软核,将外部SPI Flash中的代码数据加载到FPGA内部ram,然后复位MC8051,实现外部flash启动MC8051. 2. 系统框图 8051采用Oregano Systems公司开源的MC8051软核.SPI Flash采用W25Q16芯片存储8051的代码程序.系统框图如下: 3. MC8051简介 Oregano Systems的8051单片机采用VHDL语言开发,具有如下特点: 采用完全同步设计 指令集和标准