软件模拟SPI接口程序代码(4种模式)

SPI协议简介

SPI的通信原理很简单,一般主从方式工作,这种模式通常有一个主设备和一个或多个从设备,通常采用的是4根线,它们是MISO(数据输入,针对主机来说)、MOSI(数据输出,针对主机来说)、SCLK(时钟,主机产生)、CS/SS(片选,一般由主机发送或者直接使能,通常为低电平有效)

●SPI接口介绍

SCK:时钟信号,由主设备产生,所以主设备SCK信号为输出模式,从设备的SCK信号为输入模式。

CS:使能信号,由主设备控制从设备,,所以主设备CS信号为输出模式,从设备的CS信号为输入模式。

MOSI:主设备数据输出,从设备数据输入,所以主设备MOSI信号为输出模式,从设备的MOSI信号为输入模式。

MISO:主设备数据输入,从设备数据输出,所以主设备MISO信号为输入模式,从设备的MISO信号为输出模式。

●SPI接口连接图

注意:MOSI和MISO不能交叉连接(可以把主从机理解为一个整体系统,MOSI为系统主机发送从机接收的数据线,MISO为主机接收从机发送的数据线)

●SPI数据传输方向

SPI作为全双工的的串行通信协议,数据传输时高位在前,低位在后。主机和从机公用由主机产生的SCK信号,所以在每个时钟周期内主机和从机有1bit的数据交换(因为MOSI和MISO数据线上的数据都是在时钟的边沿处被采样)。如下图:

SPI协议规定数据采样是在SCK的上升沿或下降沿时刻(由SPI模式决定,下面会说到),观察上图,在SCK的边沿处(上升沿或下降沿),主机会在MISO数据线上采样(接收来从机的数据),从机会在MOSI数据线上采样(接收来自主机的数据),所以每个时钟周期中会有一bit的数据交换。

SPI传输模式

SPI总线传输一共有4种模式,这4种模式分别由时钟极性(CPOL)和时钟相位(CPHA)来定义。

CPOL:规定了SCK时钟信号空闲状态的电平

CPHA:规定了数据是在SCK时钟的上升沿还是下降沿被采样

----------- ------------------------------------

模式0:CPOL=0,CPHA =0  SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据)

模式1:CPOL=0,CPHA =1  SCK空闲为低电平,数据在SCK的下降沿被采样(提取数据)

模式2:CPOL=1,CPHA =0  SCK空闲为高电平,数据在SCK的下降沿被采样(提取数据)

模式3:CPOL=1,CPHA =1  SCK空闲为高电平,数据在SCK的上升沿被采样(提取数据)

以模式0为例:SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据),在SCK的下降沿切换数据线的数据。

◐在时钟的第1个上升沿(游标1处)(采样点)

MOSI上数据为1,则在此边沿从机采样(提取)数据为1,采样点在MOSI数据线的中间。

MISO上数据为0,则在此边沿主机采样(提取)数据为0,采样点在MISO数据线的中间。

◐在时钟的第1个下降沿(游标2处)(切换点)

MOSI上数据由1切换为0,,数据在时钟下降沿时切换数据。

MISO上数据由0切换为1,,数据在时钟下降沿时切换数据。

◐在时钟的第2~8个上升沿(采样点),主机在MISO上采样数据,从机在MOSI上采样数据。

◐在时钟的第2~8个下降沿(切换点),主机在MISO上切换数据,从机在MOSI上切换数据

通过模拟SPI程序来加深理解

使用STM32L4R5ZI MCU进行的测试

初始化代码:

/**SPI1 GPIO Configuration

PA5 ------> SPI1_SCK

PA6 ------> SPI1_MISO

PA7 ------> SPI1_MOSI

*/

#define SPI_SCK_PIN GPIO_PIN_5

#define SPI_SCK_GPIO_PORT GPIOA

#define SPI_MOSI_PIN GPIO_PIN_7

#define SPI_MOSI_GPIO_PORT GPIOA

#define SPI_MISO_PIN GPIO_PIN_6

#define SPI_MISO_GPIO_PORT GPIOA

#define SPI_NSS_PIN GPIO_PIN_14

#define SPI_NSS_GPIO_PORT GPIOD

#define SPI_SCK_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()

#define SPI_MISO_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()

#define SPI_MOSI_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()

#define SPI_NSS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()

#define MOSI_H HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET)

#define MOSI_L HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_RESET)

#define SCK_H HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET)

#define SCK_L HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_RESET)

#define MISO HAL_GPIO_ReadPin(SPI_MISO_GPIO_PORT, SPI_MISO_PIN)

#define NSS_H HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET)

#define NSS_L HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_RESET)

·

void SPI_Init(void)

{

/*##-1- Enable peripherals and GPIO Clocks #########################*/

/* Enable GPIO TX/RX clock */

SPI_SCK_GPIO_CLK_ENABLE();

SPI_MISO_GPIO_CLK_ENABLE();

SPI_MOSI_GPIO_CLK_ENABLE();

SPI_NSS_GPIO_CLK_ENABLE();

/*##-2- Configure peripheral GPIO #######################*/

/* SPI SCK GPIO pin configuration */

GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.Pin = SPI_SCK_PIN;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

//GPIO_InitStruct.Pull = GPIO_PULLDOWN;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

HAL_GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStruct);

HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET);

/* SPI MISO GPIO pin configuration */

GPIO_InitStruct.Pin = SPI_MISO_PIN;

GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

HAL_GPIO_Init(SPI_MISO_GPIO_PORT, &GPIO_InitStruct);

/* SPI MOSI GPIO pin configuration */

GPIO_InitStruct.Pin = SPI_MOSI_PIN;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

HAL_GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);

HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET);

GPIO_InitStruct.Pin = SPI_NSS_PIN;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

HAL_GPIO_Init(SPI_NSS_GPIO_PORT, &GPIO_InitStruct);

HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET);

}

模拟SPI4种工作模式:

/* CPOL = 0, CPHA = 0, MSB first */

uint8_t SOFT_SPI_RW_MODE0( uint8_t write_dat )

{

uint8_t i, read_dat;

for( i = 0; i < 8; i++ )

{

if( write_dat & 0x80 )

MOSI_H;

else

MOSI_L;

write_dat <<= 1;

delay_us(1);

SCK_H;

read_dat <<= 1;

if( MISO )

read_dat++;

delay_us(1);

SCK_L;

__nop();

}

return read_dat;

}

/* CPOL=0,CPHA=1, MSB first */

uint8_t SOFT_SPI_RW_MODE1(uint8_t byte)

{

uint8_t i,Temp=0;

for(i=0;i<8;i++) // 循环8次

{

SCK_H; //拉高时钟

if(byte&0x80)

{

MOSI_H; //若最到位为高,则输出高

}

else

{

MOSI_L; //若最到位为低,则输出低

}

byte <<= 1; // 低一位移位到最高位

delay_us(1);

SCK_L; //拉低时钟

Temp <<= 1; //数据左移

if(MISO)

Temp++; //若从从机接收到高电平,数据自加一

delay_us(1);

}

return (Temp); //返回数据

}

/* CPOL=1,CPHA=0, MSB first */

uint8_t SOFT_SPI_RW_MODE2(uint8_t byte)

{

uint8_t i,Temp=0;

for(i=0;i<8;i++) // 循环8次

{

if(byte&0x80)

{

MOSI_H; //若最到位为高,则输出高

}

else

{

MOSI_L; //若最到位为低,则输出低

}

byte <<= 1; // 低一位移位到最高位

delay_us(1);

SCK_L; //拉低时钟

Temp <<= 1; //数据左移

if(MISO)

Temp++; //若从从机接收到高电平,数据自加一

delay_us(1);

SCK_H; //拉高时钟

}

return (Temp); //返回数据

}

/* CPOL = 1, CPHA = 1, MSB first */

uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat )

{

uint8_t i, read_dat;

for( i = 0; i < 8; i++ )

{

SCK_L;

if( write_dat & 0x80 )

MOSI_H;

else

MOSI_L;

write_dat <<= 1;

delay_us(1);

SCK_H;

read_dat <<= 1;

if( MISO )

read_dat++;

delay_us(1);

__nop();

}

return read_dat;

}

java如何编写spi接口_软件模拟SPI接口程序代码(4种模式)相关推荐

  1. 【STM32】0.96寸OLED显示屏(7针SPI协议)软件模拟SPI

    Author:AXYZdong 自动化专业 工科男 有一点思考,有一点想法,有一点理性 [自制展示]2020鼠年大吉 文章目录 概述 3.1硬件设计 3.2软件设计 3.2.1编程要点 3.2.2代码 ...

  2. 单片机软件模拟SPI接口—加深理解SPI总线协议

    单片机软件模拟SPI接口-加深理解SPI总线协议   SPI(Serial Peripheral Interfacer 串行外设接口)是摩托罗拉公司推出的一种同步串行通讯接口,用于微处理器臌控制器和外 ...

  3. 软件模拟SPI接口程序代码(4种模式)

    软件模拟SPI接口程序代码(4种模式) SPI协议简介 SPI的通信原理很简单,一般主从方式工作,这种模式通常有一个主设备和一个或多个从设备,通常采用的是4根线,它们是MISO(数据输入,针对主机来说 ...

  4. STM32F103软件模拟SPI接口驱动ILI9486液晶屏

    STM32F103软件模拟SPI接口驱动ILI9486液晶屏 ILI9486的工作模式 ILI9486的SPI总线方式简介 ILI9486的3线SPI总线底层驱动配置步骤 ILI9486的工作模式 I ...

  5. 软件模拟SPI时序实现25Q64读写操作

    软件模拟SPI时序实现25Q64读写操作 单片机采用SPI/IIC通讯协议访问外围电子模块如:显示屏.EEPROM.FLASH.各种电子传感器等等越来越多,掌握SPI/IIC通讯协议访问外设非常必要. ...

  6. 一文搞懂——软件模拟SPI

    关于stm32通信协议:软件模拟SPI.软件模拟I2C的总结(fishing_8)_To_be_a_fisher的博客-CSDN博客_stm32 软件spi 发现一篇写的软件模拟SPI的比较容易理解的 ...

  7. 关于stm32通信协议:软件模拟SPI、软件模拟I2C的总结(fishing_8)

    趁着帮老师代上嵌入式实验课的机会,又重新熟悉了一遍stm32的通信协议:串口协议.SPI协议.I2C协议.RS485协议.大概半年前,是过了一遍的,但也只停留于读了遍代码,跑了下例程,最近又过了一遍( ...

  8. 用 java swing 编写的富文本编辑器,成品小程序,拿来即可用

    这里写自定义目录标题 用 java swing 编写的富文本编辑器,成品小程序,拿来即可用 用 java swing 编写的富文本编辑器,成品小程序,拿来即可用 前言 在最开始的开始,我也一直在找一个 ...

  9. 微信小程序实名认证接口_人脸核身接口整理

    一.微信小程序实名认证接口_人脸核身接口整理 开场一个字: 悲观.目前实名接口,人脸识别接口开放度不高."实名信息授权"已经回收. 二.人脸核身接口 1.使用条件 需要现申请通过才 ...

最新文章

  1. IT专业人士需要知道的2018年七大技术趋势
  2. [No0000A6]Visual Studio 2015 中的常用命令的默认键盘快捷键-VS2015 Shortcut
  3. Unity5x编辑器的视图一
  4. boost::mp11::mp_min相关用法的测试程序
  5. 回调函数与PHP实例
  6. elasticsearch原理_花几分钟看一下Elasticsearch原理解析与性能调优
  7. 为什么计算机中0.2+0.1不等于0.3!?
  8. 在Kubernetes上部署和管理PostgreSQL
  9. 06 is和==的区别 encode()编码 decode()解码
  10. Java版扫雷小游戏
  11. php cas 票据认证失败,解决CAS客户端验证ST票据时发生的TicketValidationException问题...
  12. js 正则匹配两个字符串中间的字符,一级匹配带有反斜杠的字符串
  13. 2021届秋招提前批——携程数据分析笔试
  14. wd移动硬盘不能识别_西部数据移动硬盘无法识别恢复
  15. tp3.2 生成条形码
  16. 常用函数+星期+月份+缩写+四季
  17. 本地RTMP流媒体服务器搭建拉流简易版
  18. android+win8+双系统,Android/Win8双系统 天敏iBox睿盒D9i评测上
  19. css扇子展开,CSS3 绝妙的扇形折叠展开加载动画
  20. PF_RING 6.0.2在Redhat 6.3 x86_64上编译和安装

热门文章

  1. PyCharm代码格式化插件
  2. 面试的一般流程及其常见的问题
  3. OSChina 周五乱弹 —— 夏日限定梦想
  4. 易基因 | 简化基因组DNA甲基化测序(RRBS)实验怎么做?
  5. 用java编写图形用户界面_Java编写图形用户界面程序
  6. OpenCV基础(7)OpenCV中的颜色空间
  7. 使用xpath爬取学院新闻
  8. 深入浅出理解数据分析系列之:Python安装Excel文档库openpyxl和Pycharm为项目安装Excel文档库openpyxl
  9. 电容笔和Apple pencil区别有什么?双十一值得入手的电容笔推荐
  10. 跨时钟域问题(二)(单bit信号跨时钟域 1. 电平同步器 2. 边沿同步器 3. 脉冲检测器)