一、器件
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
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 }
四、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
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
五、仿真波形图
六、参考资料
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