【通信协议】SPI总线

2024-08-24 06:36
文章标签 总线 spi 通信协议

本文主要是介绍【通信协议】SPI总线,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

SPI简介

硬件电路

SPI模式

软件模拟初始化 

时序基本单元

起始条件

终止条件

发送与接收

 SPI基本单元代码 

MySPI.h

MySPI.c  


SPI简介

SPI(Serial Peripheral Interface),即串行外围设备接口,是由Motorola公司开发的一种高速全双工通用数据总线。它被广泛地使用在要求通讯速率较高的场合。

特征

  • 同步,全双工,串行
  • 通讯速率较高
  • 支持总线挂载多设备(一主多从)
  • 四条通信线
  • 短距离

通信线

SCK(Serial Clock):串行时钟线,主机生成时钟,主机和从机根据电平边沿(上升沿或下降沿)发送数据位、接收数据位

MOSI(Master Output Slave Input):主机输出,从机输入

MISO(Master Input Slave Output):主机输入,从机输出

SS(Slave Select):指定主机与哪个从机通信,同一时间主机只能选择一个从机,故只能设置一个SS低为电平。未被选中(NSS引脚为高电平)的从设备会忽略总线上的数据传输

传输速度

SPI总线上的主设备必须在通信开始时候配置并生成相应的时钟信号。从理论上讲,只要实际可行,时钟速率就可以是你想要的任何速率,当然这个速率受限于每个系统能提供多大的系统时钟频率,以及最大的速率。

硬件电路

所有SPI设备的SCK、MOSI、MISO分别连在一起

主机另外引出多条SS控制线,分别接到各从机的SS引脚

输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

当从机的SS引l脚为高电平,也就是从机未被选中时,它的MISO引脚,必须切换为高阻态,在SS为低电平时,MISO才允许变为推挽输出。在SS未被选中的状态,从机的MISO引脚必须关断输出,即配置输出为高阻态。

SPI模式

SPI 根据时钟极性和时钟相位的不同可以有4种工作模式,通常在编写 SPI 设备驱动程序时需要特别注意从设备的时钟相位与时钟极性,如果与主设备不一致时,一般都不能进行正常的通信

  1. 模式0(CKPL=0,CKPH=0):

    • 时钟极性(Clock Polarity)为0,表示时钟空闲状态为低电平。
    • 时钟相位(Clock Phase)为0,表示数据在时钟信号的奇数边沿(时钟上升沿)进行采样和稳定。
  2. 模式1(CKPL=0,CKPH=1):

    • 时钟极性为0,时钟空闲状态为低电平。
    • 时钟相位为1,数据在时钟信号的偶数边沿(时钟下降沿)进行采样和稳定。
  3. 模式2(CKPL=1,CKPH=0):

    • 时钟极性为1,时钟空闲状态为高电平。
    • 时钟相位为0,数据在时钟信号的奇数边沿(时钟下降沿)进行采样和稳定。
  4. 模式3(CKPL=1,CKPH=1):

    • 时钟极性为1,时钟空闲状态为高电平。
    • 时钟相位为1,数据在时钟信号的偶数边沿(时钟上升沿)进行采样和稳定。

软件模拟初始化 

根据SPI硬件规定:

MISO(Master Input Slave Output),SCK(Serial Clock),SS(Slave Select)均配置为推挽输出

MISO(Master Input Slave Output)配置为上拉输入

GPIO的其它参数的理解可以阅读下方博客,这里不再赘述。

【STM32】GPIO和AFIO标准库使用框架_gpio afio-CSDN博客

本篇软件模拟使用SPI的模式0 

void MySPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}void MySPI_W_SCK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}void MySPI_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}uint8_t MySPI_R_MISO(void)
{return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}void MySPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//推挽输出默认输出低电平MySPI_W_SS(1);//不选择从机,空闲状态MySPI_W_SCK(0);//模式0空闲时的SCKGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);}

时序基本单元

起始条件

SS(Slave Select)从高电平切换到低电平

void MySPI_Start(void)
{
//初始化时已经配置空闲状态时为高电平,现拉低选择从机MySPI_W_SS(0);
}

终止条件

SS从低电平切换到高电平

void MySPI_Stop(void)
{
//通讯过程中,SS为低电平,拉高代表通讯结束MySPI_W_SS(1);
}

发送与接收

SPI只有主模式和从模式之分,没有读和写的说法,外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。也就是说,你发一个数据必然会收到一个数据;你要收一个数据必须也要先发一个数据。

硬件SPI,主机SCK电平变化与数据读写几乎同时进行,但软件SPI,程序是一条一条执行的,软件模拟就先变化时钟,再读写数据位,不是同时进行的

交换一个字节(模式0)

CPOL=0:空闲状态时,SCK为低电平

CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据

在SS下降沿的时候,主机和从机就需要移出数据,那样SCK的第一个边沿才能移入数据

uint8_t MySPI_SwapByte(uint8_t ByteSend)
{uint8_t i, ByteReceive = 0x00;for (i = 0; i < 8; i ++){MySPI_W_MOSI(ByteSend & (0x80 >> i));//第一次在SS下降沿时发送数据为位,之后SCK下降沿时发送数据位MySPI_W_SCK(1);if (MySPI_R_MISO() == 1){ByteReceive |= (0x80 >> i);}//SCK上升沿时接收数据位MySPI_W_SCK(0);}return ByteReceive;
}

 SPI基本单元代码 

MySPI.h

#ifndef __MYSPI_H
#define __MYSPI_Hvoid MySPI_Init(void);
void MySPI_Start(void);
void MySPI_Stop(void);
uint8_t MySPI_SwapByte(uint8_t ByteSend);#endif

MySPI.c  

#include "stm32f10x.h"                  // Device headervoid MySPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}void MySPI_W_SCK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}void MySPI_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}uint8_t MySPI_R_MISO(void)
{return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}void MySPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//推挽输出默认输出低电平MySPI_W_SS(1);MySPI_W_SCK(0);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);}void MySPI_Start(void)
{MySPI_W_SS(0);
}void MySPI_Stop(void)
{MySPI_W_SS(1);
}uint8_t MySPI_SwapByte(uint8_t ByteSend)
{uint8_t i, ByteReceive = 0x00;for (i = 0; i < 8; i ++){MySPI_W_MOSI(ByteSend & (0x80 >> i));MySPI_W_SCK(1);if (MySPI_R_MISO() == 1){ByteReceive |= (0x80 >> i);}MySPI_W_SCK(0);}return ByteReceive;
}

这篇关于【通信协议】SPI总线的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101722

相关文章

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

电子电气架构---私有总线通信和诊断规则

电子电气架构—私有总线通信和诊断规则 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节能减排。 无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事.而不是让内心的烦躁、

I2C总线协议(AT24C02C)

本文章是基于TQ2440开发板上的AT24C02C 一, I2C简介       IIC即Inter-Integrated Circut(集成电路总线),有飞利浦在八十年代实际出来. I2C是一种多向控制总线,就是同一个总线下可以连接多个芯片,同时每个芯片都可以作为实时数据传输的控制源. 二. 硬件结构       I2C串行总线一般有两根信号线,一根是双向的数据总线SDA, 一根是

stm32之软件SPI读写W25Q64存储器应用案例

系列文章目录 1. stm32之SPI通信协议 文章目录 系列文章目录前言一、电路接线图二、应用案例代码三、应用案例分析3.1 SPI通信模块3.2 W25Q64模块3.3 主程序 前言 提示:本文主要用作在学习江科大自化协STM32入门教程后做的归纳总结笔记,旨在学习记录,如有侵权请联系作者 本案例使用软件SPI通信的方式实现了STM32与W25Q64 Flas

【STM32】CAN总线基础入门

CAN总线基础入门 一、CAN简介二、主流通信协议对比三、CAN物理层1、CAN硬件电路2、CAN电平标准3、CAN收发器 – TJA1050(高速CAN)4、CAN物理层特性 四、帧格式1、CAN总线帧格式2、数据帧3、数据帧各部分用途简介4、数据帧的发展历史5、遥控帧6、错误帧7、过载帧8、帧间隔9、位填充10、波形实例 五、位同步1、接收方数据采样2、接收方数据采样遇到的问题3、位时序

Flink1.10基于工厂模式的任务提交与SPI机制

《2021年最新版大数据面试题全面开启更新》 Flink任务执行模式包含了yarn-session、standalone、per-job、local, 在1.10中又增加k8s的执行模式,那么在任务提交过程中如何根据不同的执行模式进行任务提交呢?主要通过两个接口来实现:PipelineExecutorFactory 与 PipelineExecutor。PipelineExecutorF

搭建SpringBoot+ Netty + WebSocket 通信协议框架

运用场景:与机器设备进行通讯或者其他场景; pom文件就不上传了,直接上代码,网上都可以找的到 主要是 SpringBoot 和 Netty 的依赖 1.配置类 @Component@ConfigurationProperties(prefix = "ws")public class WebSocketConfig {private int port;private String host

转载 SPI的比喻理解

SPI 传输是一个虚拟的移位寄存器方式。 你这么理解就可以: 主机和从机之间有一条 16 格的传送带。主机一格一格拨动它转动(相当于发送时钟)。 如果是主机发送,它就把一个个的东西放在传送带上,转动 8 次,就传到从机一侧了。这时,从机可以从传送带上将东西取下。如果从机没有取东西,这些东西再转 8 次又回到主机一侧。 如果是主机接收,从机就要把 8 个东西一次放上传送带。当主机转动 8 次,东西就

V90总线伺服报800F错误

1、博途PLC工艺对象位置轴轴控功能块 博途PLC工艺对象位置轴轴控功能块(完整SCL代码)-CSDN博客文章浏览阅读423次。S7-1200PLC脉冲轴位置轴位置控制功能块S7-1200PLC脉冲轴位置轴位置控制功能块优化(完整SCL源代码)_s71200 脉冲轴-CSDN博客文章浏览阅读341次。该博客详细介绍了如何优化S7-1200 PLC的位置控制功能块,使得在轴激活限位时无需复位即可直

EventBus-Vue事件总线解析与使用指南

前言         在Vue.js中,组件通信是开发过程中非常场景的需求。根据不同的场景和需求,Vue提供了多种组件通信方式。比如父子组件通信、兄弟组件通信、跨代组件通信等。当应用程序中两个组件或者说页面之间没有引入和被引入的关系的时,或者说他们之间嵌套的结果复杂的时候,我们可以考虑如何传递数据呢?         其中适用的通信方式有 Vuex、provide 和 inject、Event