SPI全双工通信

SPI全双工通信 while(1){if(usart4.receive_ok_flag){usart4.receive_ok_flag 0;// 1. 将串口底层的接收数据拷贝到我们的 buffer 中memset(buffer, 0, sizeof(buffer));//数据清零操作for(i 0; i 20; i){buffer[i] usart4.receive_buffer[i]; // 原样拷贝不用转小写}// buffer[]123456789;// 第一步发送给 FPGA 并让其锁存 SPI_CS_OFF;for(k 0; k 6; k){spi.write_byte(buffer[k]); // 固定发 5 个字节对应 FPGA 40位}SPI_CS_ON; // CS 瞬间拉高此时 FPGA 执行 latched_data shift_reg// 给硬件一点点反应时间for (n 0; n 1000; n);// 第二步立刻发起空读取把数据要回来 memset(spibuffer, 0, sizeof(spibuffer));SPI_CS_OFF;for(k 0; k 6; k){// 此时发 0x00 纯粹是为了产生时钟重点在于等号右边读回来的数据spibuffer[k] spi.write_byte(0x00);}SPI_CS_ON;// 3. 将从 FPGA 读回来的数据打印到串口终端usart4.printf(FPGA Return: );usart4.printf(spibuffer);usart4.printf(\r\n);}}FPGAtimescale 1 ns / 1 psmodule SPI(input CLK_25M,input spi_clk,input spi_mosi,input spi_cs,output spi_miso, // 注意去掉了 reg因为直接用线连output FPGA_LEDR,output FPGA_LEDG,output FPGA_LEDB);//-------------------------rst_n---------------------------///*延时复位信号生成*/reg [5:0]rst_cnt 6d0;reg rst_n 1d0;always (posedge CLK_25M)if(rst_cnt 6d50) beginrst_n 1d1;rst_cnt rst_cnt;end else beginrst_cnt rst_cnt 1d1;end//--------------------------SPI 核心移位管道---------------------------//reg [47:0] shift_reg;// 唯一的动态逻辑只有在被选中(CS为低)且时钟上升沿时把数据往左挤always (posedge spi_clk or negedge rst_n) beginif (!rst_n) beginshift_reg 48d0;end else if (!spi_cs) beginshift_reg {shift_reg[46:0], spi_mosi};endend// MISO 永远无脑输出管子最左边最高位的数据assign spi_miso shift_reg[47];//--------------------------LED 默认关闭---------------------------//// 因为现在做纯数据回环就不亮灯了保持高电平全灭assign {FPGA_LEDR, FPGA_LEDG, FPGA_LEDB} 3b111;endmodule///*// * --------------------// * Company : LUOYANG GINGKO TECHNOLOGY CO.,LTD.// * BBS : http://www.eeschool.org// * --------------------// * Project Name : SPI// * Module Name : SPI// * Description : The codes of SPI// * --------------------// * Tool Versions : Quartus II 13.1// * Target Device : Cyclone IV E EP4CE10F17C8// * --------------------// * Engineer : Xiaorenwu// * Revision : V0.0// * Created Date : 2016-01-04// * --------------------// * Engineer :// * Revision :// * Modified Date :// * --------------------// *// * --------------------// *///////--------------------Timescale------------------------------////timescale 1 ns / 1 ps////------------------------Module_SPI-------------------------//// /*定义端口*/// module SPI(// input CLK_25M,// input spi_clk,// input spi_mosi,// input spi_cs,// output reg spi_miso,//// output FPGA_LEDR,// output FPGA_LEDG,// output FPGA_LEDB// );//////-------------------------rst_n---------------------------//// /*复位信号*/// reg [5:0]rst_cnt 6d0;// reg rst_n 1d0;// always (posedge CLK_25M)// if(rst_cnt 6d50)// begin// rst_n 1d1;// rst_cnt rst_cnt;// end// else rst_cnt rst_cnt 1d1;//////-------------------------parameter---------------------//// parameter ledr {8d108,8d101,8d100,8d114},// ledg {8d108,8d101,8d100,8d103},// ledb {8d108,8d101,8d100,8d98},// hello {8d104,8d101,8d108,8d108,8d111};//////////--------------------------spi_mosi---------------------------//// /* 40位数据接收与锁存模块 */// reg [39:0] shift_reg;// reg [39:0] latched_data;//// wire spi_rx_rst_n rst_n (~spi_cs);//// // 1. 来一个时钟数据往左挤一位// always(posedge spi_clk or negedge spi_rx_rst_n) begin// if(!spi_rx_rst_n) begin// shift_reg 40d0;// end else begin// shift_reg {shift_reg[38:0], spi_mosi};// end// end//// // 2. 当 CS 拉高一帧结束时把接收到的 40 位数据安全锁存// always(posedge spi_cs or negedge rst_n) begin// if(!rst_n) begin// latched_data 40d0;// end else begin// latched_data shift_reg;// end// end//////--------------------------delay----------------------------//// reg spi_clk_r;// always(posedge CLK_25M or negedge rst_n) begin// if(!rst_n)// spi_clk_r 1d1;// else// spi_clk_r spi_clk;// end//////--------------------------spi_miso----------------------------//// /* 40位数据原样回传模块 */// reg [39:0] data_out;// wire spi_tx_rst_n rst_n (~spi_cs);//// always(negedge spi_clk_r or negedge spi_tx_rst_n) begin// if(!spi_tx_rst_n) begin// data_out latched_data; // 通信还没开始时装载刚才锁存的数据// spi_miso latched_data[39]; // 提前把最高位挂到 MISO 引脚上准备好// end else begin// spi_miso data_out[38]; // 时钟下降沿时推送下一位数据// data_out {data_out[38:0], 1b0}; // 寄存器整体左移// end// end// endmodule