一.SPI协议简要介绍

SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
  SPI总线是Motorola公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟线SCK,一条数据输入线MOSI,一条数据输出线MISO;用于 CPU与各种外围器件进行全双工、同步串行通讯。SPI主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。

SPI总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是SPI0和SPI3方式。SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果 CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。

SPI主模块和与之通信的外设时钟相位和极性应该一致。

以下是SPI时序图:

主要讲解一下广泛使用的两种方式设置:

SPI0方式:CPOL=0,CPHA=0;SCK空闲状态为低电平,第一个跳变沿(上升沿)采样数据,无论对Master还是Slaver都是如此。

SPI3方式:CPOL=1,CPHA=1;SCK空闲状态为高电平,第二个跳变沿(上升沿采样数据,无论对Master还是Slaver都是如此。

其实对于SPI0和SPI1发送与接收数据,可以总结为一句话:上升沿采样数据,下降沿发送数据。全双工同时进行,当然,必须在CS拉低使能情况下。

二.FPGA作为Slaver实现SPI3方式与STM32通信

1.STM32方面:用库函数配置SPI1,设置CPOL=1,CPHA=1.

2.FPGA方面:

(1)通过边沿检测技术得出SCK上升沿与下降沿标志,用于下面状态机中的数据采样及发送。

(2)根据时序图,采用2个状态机分别在SCK上升沿实现数据采样,下降沿实现数据发送。无论是采样还是发送,都是高位在前,从Bit[7]到Bit[0],共8位数据。

(3)最后通过边沿检测技术得出数据采样完成标志,用于用户操作。

以下是SPI3的时序图:

三.Verilog代码部分

测试工程代码:实现了STM32每隔200ms发送流水灯数据给FPGA,使FPGA系统板上的4个LED灯实现流水操作;同时,FPGA每隔1s发送计数数据给STM32,并在STM32系统板上的LCD屏出来,即:显示0-9循环计数。

但下面的代码只是SPI作为从机的驱动部分,包括SPI发送数据与接收数据。

  1 /***********************************************************************
  2      ****************** name:SPI_Slaver_Driver **************
  3             ********** author:made by zzuxzt **********
  4      ****************** time:2014.4.29 **********************
  5 ***********************************************************************/
  6 //use SPI 3 mode,CHOL = 1,CHAL = 1
  7 module spi(input clk,
  8               input rst_n,
  9               input CS_N,
 10               input SCK,
 11               input MOSI,
 12               input [7:0] txd_data,
 13               output reg MISO,
 14               output reg [7:0] rxd_data,
 15               output rxd_flag);   //recieve done,please transmit data
 16
 17 //-------------------------capture the sck-----------------------------
 18 reg sck_r0,sck_r1;
 19 wire sck_n,sck_p;
 20 always@(posedge clk or negedge rst_n)
 21 begin
 22     if(!rst_n)
 23         begin
 24             sck_r0 <= 1'b1;   //sck of the idle state is high
 25             sck_r1 <= 1'b1;
 26         end
 27     else
 28         begin
 29             sck_r0 <= SCK;
 30             sck_r1 <= sck_r0;
 31         end
 32 end
 33
 34 assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
 35 assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
 36
 37 //-----------------------spi_slaver read data-------------------------------
 38 reg rxd_flag_r;
 39 reg [2:0] rxd_state;
 40 always@(posedge clk or negedge rst_n)
 41 begin
 42     if(!rst_n)
 43         begin
 44             rxd_data <= 1'b0;
 45             rxd_flag_r <= 1'b0;
 46             rxd_state <= 1'b0;
 47         end
 48     else if(sck_p && !CS_N)
 49         begin
 50             case(rxd_state)
 51                 3'd0:begin
 52                         rxd_data[7] <= MOSI;
 53                         rxd_flag_r <= 1'b0;   //reset rxd_flag
 54                         rxd_state <= 3'd1;
 55                       end
 56                 3'd1:begin
 57                         rxd_data[6] <= MOSI;
 58                         rxd_state <= 3'd2;
 59                       end
 60                 3'd2:begin
 61                         rxd_data[5] <= MOSI;
 62                         rxd_state <= 3'd3;
 63                       end
 64                 3'd3:begin
 65                         rxd_data[4] <= MOSI;
 66                         rxd_state <= 3'd4;
 67                       end
 68                 3'd4:begin
 69                         rxd_data[3] <= MOSI;
 70                         rxd_state <= 3'd5;
 71                       end
 72                 3'd5:begin
 73                         rxd_data[2] <= MOSI;
 74                         rxd_state <= 3'd6;
 75                       end
 76                 3'd6:begin
 77                         rxd_data[1] <= MOSI;
 78                         rxd_state <= 3'd7;
 79                       end
 80                 3'd7:begin
 81                         rxd_data[0] <= MOSI;
 82                         rxd_flag_r <= 1'b1;  //set rxd_flag
 83                         rxd_state <= 3'd0;
 84                       end
 85                 default: ;
 86             endcase
 87         end
 88 end
 89
 90
 91 //--------------------capture spi_flag posedge--------------------------------
 92 reg rxd_flag_r0,rxd_flag_r1;
 93 always@(posedge clk or negedge rst_n)
 94 begin
 95     if(!rst_n)
 96         begin
 97             rxd_flag_r0 <= 1'b0;
 98             rxd_flag_r1 <= 1'b0;
 99         end
100     else
101         begin
102             rxd_flag_r0 <= rxd_flag_r;
103             rxd_flag_r1 <= rxd_flag_r0;
104         end
105 end
106
107 assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
108
109 //---------------------spi_slaver send data---------------------------
110 reg [2:0] txd_state;
111 always@(posedge clk or negedge rst_n)
112 begin
113     if(!rst_n)
114         begin
115             txd_state <= 1'b0;
116         end
117     else if(sck_n && !CS_N)
118         begin
119             case(txd_state)
120                 3'd0:begin
121                         MISO <= txd_data[7];
122                         txd_state <= 3'd1;
123                       end
124                 3'd1:begin
125                         MISO <= txd_data[6];
126                         txd_state <= 3'd2;
127                       end
128                 3'd2:begin
129                         MISO <= txd_data[5];
130                         txd_state <= 3'd3;
131                       end
132                 3'd3:begin
133                         MISO <= txd_data[4];
134                         txd_state <= 3'd4;
135                       end
136                 3'd4:begin
137                         MISO <= txd_data[3];
138                         txd_state <= 3'd5;
139                       end
140                 3'd5:begin
141                         MISO <= txd_data[2];
142                         txd_state <= 3'd6;
143                       end
144                 3'd6:begin
145                         MISO <= txd_data[1];
146                         txd_state <= 3'd7;
147                       end
148                 3'd7:begin
149                         MISO <= txd_data[0];
150                         txd_state <= 3'd0;
151                       end
152                 default: ;
153             endcase
154         end
155 end
156
157 endmodule

六.Modelsim仿真图

FPGA作为从机与STM32进行SPI协议通信---Verilog实现相关推荐

  1. FPGA作为从机与STM32进行SPI协议通信

    1.SPI协议简要介绍 (1)SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上 ...

  2. 【STM32】SPI协议通信详解

    目录 一.SPI协议简介 二.SPI物理层 三.SPI协议层 1.通讯的起始和停止信号 2.数据有效性 3.时钟信号的相位和极性(重点) 四.SPI 特性及架构(重点) 1.通信引脚 2.时钟控制逻辑 ...

  3. 【嵌入式】STM32实现SPI双机通信的一些细节(2)片选总结

    [嵌入式]STM32实现SPI双机通信的一些细节(2)SPI软硬件片选总结 SPI片选总结 坑爹的手册示意图 理想中的硬件片选 主机软件片选就对了 从机硬件片选 从机软件片选 代码 主机软件片选SPI ...

  4. 两块STM32之间 SPI DMA通信

    @[两块STM32之间 SPI DMA通信] 这里讲的是两块STM32F407板子的互相通讯,折腾了3天,终于比较清楚了,特此记录. 两块板子互相通讯,除了SPI的接线,肯定还有其他信号线,必须注意这 ...

  5. 基于stm32、spi协议的Fatfs文件系统移植(附完整代码下载)

    开发环境:Window 7 32bit 开发工具:Keil uVision4 硬件:stm32f103vct6 目录 1.硬件设计: 2.软件设计 1.SPI收发数据 2.向SD卡发送的命令格式: 3 ...

  6. STM32通过SPI协议驱动OLED屏

    坚持就是胜利 一.SPI协议介绍 01 简介 02 SPI物理层 03 SPI基本通讯过程 二.OLED显示器介绍 01 简介 02 接口定义 03 与STM32接线图 三.汉字取模软件介绍 01 下 ...

  7. STM32双机SPI全双工通信

    (基于STM32F407的SPI全双工通信时序不同步问题!!) 首先吐槽一波,调一个星期的SPI,始终没有很好的效果. 网上有很多SPI主从通信的例子,但是两片STM32单片机进行通信,基本很少,就算 ...

  8. STM32模拟SPI协议驱动AD7908芯片

    最近时间,由于项目需求用到了AD7908的AD采集芯片,通过查阅其相关的技术手册之后,成功的实现了其AD采集的功能,下面分享一下我的一些经验. AD7908是一个8位高速.低功耗.8通道的ADC芯片, ...

  9. SPI协议主机verilog

    对SPI协议的理解 spi协议 verilog 最近刚做了一个项目,现在还没做完,但是我发现官方的ip写得很全面,但是很复杂,许多东西对于速度要求不是很高的就用不着,比如一个crc,crc本身计算并不 ...

最新文章

  1. 多线程-synchronized锁
  2. 网络推广费用浅析网站具备哪些特点能更受蜘蛛的青睐?
  3. BZOJ 1815: [Shoi2006]color 有色图 [Polya DFS 重复合并]
  4. Android JNI programming demo with Eclipse
  5. Guava学习笔记(六):Immutable(不可变)集合
  6. TCP 粘包/拆包说明 及 异常案例
  7. 通过SAXReader解析XML
  8. 用python如何制作表格_Python中用xlwt制作表格实例讲解
  9. win10小课堂:如何彻底关闭windows defender
  10. 安装RAC小记(Oracle11gR2)
  11. 个人深度学习工作站配置指南
  12. 轮播图、焦点图代码案例
  13. 如何快速定位自己热爱的工作
  14. 试简述smtp通信的三个阶段的过程_通信原理简答题汇总
  15. 华为linux磁盘空间,华为推出EROFS文件系统,磁盘性能大提速
  16. VIA图像标注系统汉化版
  17. C语言:计算同一年内两个日期的相隔天数
  18. 清华大学的计算机新世界排名,清华蝉联计算机科学AI专业全球冠军 交大排名第6...
  19. 2022华数杯B题论文思路分析+完整代码(水下机器人组装计划)
  20. 计算机通信技术知识大全网络,计算机通信技术

热门文章

  1. 2021年春季学期-信号与系统-第二次作业参考答案-第九小题
  2. 第十六届全国大学生智能车竞赛赛题规划
  3. 为什么使用RLC表测量电感在不同的频率测量值不同呢?
  4. html中::before 爬虫_反反爬虫系列(四)
  5. c python.h_C++/C语言Python H
  6. 20分钟学会mysql_5分钟学会mysql基本操作
  7. linux io函数,Linux下普通IO文件操作函数---C语言
  8. android actionbaractivity 错误,Android studio无法解析ActionBarActivity
  9. 计算机行业可以开安装服务费,安装服务费税率是多少
  10. python怎么做界面自动化_mac+python3+selenium做pc的界面自动化测试