1、SPI简介
一种高速、全双工的串行,即发送数据的时候同时也可以接收数据,传输时高位在前,低位在后;
同步的,即主机发送SCK时钟信号给从机,共用时钟,主从机收发数据也是按照此时钟。每个SCK周期内,主从机都会发送并接收1 bit;
一般是4根线:
SCK即主机发送的时钟信号;
MOSI即主机的输出口;
MISO即主机的输入口;
CS即主机选择哪个从机对接通讯,一般低电平,表示被主机选中;
采用主从模式,即主机控制着SCK和CS;
传输方式有四种,由时钟极性(CPOL)和时钟相位(CPHA)决定,两者控制着主从机何时交换数据以及何时对接收数据进行采样,最常用的是两种:
工作模式0:CPOL=0且CPHA=0,即SCK=0是空闲的,数据在SCK的上升沿被采样,数据在SCK的下降沿被改变;
工作模式3:CPOL=1且CPHA=1,即SCK=1是空闲的,数据在SCK的上升沿被采样,数据在SCK的下降沿被改变;
2、STM32发送的SCK信号
发送的信号如下所示
此处没有放大,每个竖条其实是如下所示
3、边沿检测
实现FPGA对SCK信号的捕捉,经典的边沿检测代码,网上一搜一大把,借用一下正点原子的学习代码做个试验。
module touch_led (input sys_clk,input sys_rst_n,input touch_key,output reg led);
reg touch_key_d0;
reg touch_key_d1;
wire touch_en;
assign touch_en = (~touch_key_d1) & touch_key_d0;
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0) begin
touch_key_d0 <= 1'b0;
touch_key_d1 <= 1'b0;
end
else begin
touch_key_d0 <= touch_key;
touch_key_d1 <= touch_key_d0;
end
end//对触摸按键端口接收的数据延迟两个周期
//根据上升沿使能信号切换led状态
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0)
led <= 1'b1;
else if (touch_en)
led <= ~led;
end
endmodule
捕捉到上升沿后,fpga在测试时对应发出低电平
4、双机通讯
工作模式0的时候,观察时序图如下
SCK是主机发送给从机的,CS也是由主机控制的
数据在上升沿时被采样,下降沿时被切换
MOSI 和 MISO 数据在 SCK 的奇数边沿保持不变,数据在 SCK 奇数边沿时被采样,在非采样时刻, MOSI 和 MISO 的信号才发生切换。
主机的MOSI的有效数据是在第一个上升沿之前就已经输出
主机的MISO的有效数据是在第一个上升沿时,从机发送过来的有效数据