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 always@(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 always@(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

猜你喜欢

转载自www.cnblogs.com/cnlntr/p/12207721.html