【SPI协议】

2023-11-04

一、SPI介绍

SPI是“全双工”通信,具有单独的发送和接收线,可以同时进行发送和接收,从机不主动发起访问,总是被动执行操作

SPI包含4根逻辑线:
MISO: 主机输入,从机输出
MOSI: 主机输出,从机输入
SCLK: 串行时钟信号,此信号由主机产生。从机不产生时钟信号。
CS: 片选信号,由主机产生,用来控制与哪个从机通信,通常是低电平为选中。

SPI有个时钟极性需要配置,也就是需要配置时钟极性(CPOL)和时钟相位(CPHA),时钟极性和相位共同决定读取数据的方式,也就是说我在什么时候进行取数据。
CPOL: 0 时钟空闲时为低电平
CPOL: 1 时钟空闲时为高电平
CPHA: 0 在时钟信号SCK的第一个跳变沿采样
CPHA: 1 在时钟信号SCK的第二个跳变沿采样

SPI的时钟极性和相位的配置通常称为 SPI模式,遵循以下约定:
在这里插入图片描述
SPI通讯的优势
使SPI作为串行通信接口脱颖而出的原因很多;

全双工串行通信;
高速数据传输速率。
简单的软件配置;
极其灵活的数据传输,不限于8位,它可以是任意大小的字;
非常简单的硬件结构。从站不需要唯一地址(与I2C不同)。从机使用主机时钟,不需要精密时钟振荡器/晶振(与UART不同)。不需要收发器(与CAN不同)。

SPI的缺点
没有硬件从机应答信号(主机可能在不知情的情况下无处发送);
通常仅支持一个主设备;
需要更多的引脚(与I2C不同);
没有定义硬件级别的错误检查协议;
与RS-232和CAN总线相比,只能支持非常短的距离;

二、SPI使用举例

SPI如何实现读写呢?
不同的从机芯片读写方式不同,如下为ADXL345加速度传感器的读写时序,其时序方案按照时钟极性(CPOL)= 1、 时钟相位(CPHA)= 1执行,读写如下如:
在这里插入图片描述
SPI写入寄存器:
ADXL345写寄存器的方式是:如上图写时先发送寄存器地址值随后是寄存器值,则SPI写寄存器的程序如下:

/* SPI向从机寄存器写数据 */
int Single_Write(unsigned char REG_Address,unsigned char REG_data)
{
    int ret = 0;
	uint32_t timeout = 1000;
    uint8_t data[2] = {0}; //构造数据结构,用于发送spi数据
	
	data[0] = REG_Address;
	data[1] = REG_data;
	uint16_t size = sizeof(data);
	
    HAL_GPIO_WritePin(GPIOA, CS_PIN, GPIO_PIN_RESET); //片选拉低,开始通信
    ret = HAL_SPI_Transmit(&hspi1, data, size, timeout); //SPI发送2字节数据
	if (ret != HAL_OK)
	{
		printf("SPI Transmit err ret = %d\n",ret);
		return -1;
	}
    
    HAL_GPIO_WritePin(GPIOA, CS_PIN, GPIO_PIN_SET);	 //片选拉高,通信结束
	return 0;
}

SPI读取寄存器:
ADXL345 读寄存器方式:最高位为1表示读取,所以想要实现读取寄存器,要spi写一个最高位为1的数据(uint8_t txData = REG_Address | 0x80; // 设置读取标志位)。随后ADXL345被动向主机发送寄存器的值数据。SPI读寄存器程序如下:

/*SPI单字节读取*/
unsigned char Single_Read(unsigned char REG_Address)
{   
    int ret = 0;
    uint8_t rxData;
	
    uint8_t txData = REG_Address | 0x80; //构造要发送的数据,MSB位置1
    
	HAL_GPIO_WritePin(GPIOA, CS_PIN, GPIO_PIN_RESET); //片选拉低,开始通信
	ret = HAL_SPI_Transmit(&hspi1, &txData, 1, HAL_MAX_DELAY); //spi发送1字节数据
    if (ret != HAL_OK)
    {
	    printf("SPI Transmit err ret = %d\n",ret);
	    return 0;
    } 
    HAL_SPI_Receive(&hspi1, &rxData, 1, HAL_MAX_DELAY); //SPI读取1字节数据
    HAL_GPIO_WritePin(GPIOA, CS_PIN, GPIO_PIN_SET); //通信完毕,片选拉高
    return rxData;
}

看下读取ADXL345设备ID,示波器抓到的时序:
在这里插入图片描述
注:不同的芯片SPI的读取方式可能不同,例如W25Q16之类存储芯片是通过发送不同的指令来实现读写的

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【SPI协议】 的相关文章

  • Oracle锁表处理

    1 查出被锁的表 SELECT object name machine s sid s serial FROM gv locked object l dba objects o gv session s WHERE l object id

随机推荐

  • uni-app 自定义下拉选择列表

    效果图 1 自定义组件ChoiceSelected vue 2 组件代码
  • 利用 MLP(多层感知器)和 RBF(径向基函数)神经网络解决的近似和分类示例问题(Matlab代码实现)

    目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码 1 概述 1 径向基神经网络 径向基函数网络是由三层构成的前向网络 第一层为输入层 节点个数的能与输入的维数 第二层为隐含层 节点个数视问题的复杂度而定 第三层为输出层 节点
  • 【路径规划】基于萤火虫算法求解订单分批问题附matlab代码

    1 内容介绍 0 引 言 现阶段大多数配送中心是劳动力密集型的 配送中心中拣选作业劳动量占据配送中心全部劳动量的 60 1 成本占 40 2 时间占 30 40 3 可见 拣选作业在配送中心的重要性不言而喻 订单分批作为拣选作业的重要环节
  • 5-21 求特殊方程的正整数解

    本题要求对任意给定的正整数N 求方程X 2 Y 2 N的全部正整数解 输入格式 输入在一行中给出正整数N 10000 输出格式 输出方程X 2 Y 2 N的全部正整数解 其中X Y 每组解占1行 两数字间以1空格分隔 按X的递增顺序输出 如
  • ORB_SLAM2源码:ORBmatcher.cc

    ORBmatcher cc中的函数 主要实现 1 路标点和特征点的匹配 2D 3D点对 2 特征点和特征点的匹配 2D 2D点对 SearchByProjection的函数重载看得我一脸懵逼 在这做一下笔记 以后可以参考参考 每个路标点会有
  • Elasticsearch - What‘s new in 8.3

    从5 5 6开始 用过2 X和7 X 不知不觉Elasticsearch已经成长到了8 X 针对目前最新的8 3版本 也再整体学习一下 官网链接 什么是Elasticsearch slogan You Know for search Ela
  • 多重共线性检验 matlab,[求助]多重共线性

    Make sure you haven t made any flagrant errors e g improper use of computed or dummy variables Increase the sample size
  • Stephen Wolfram自述----在Y Combinator创业学校的演讲

    时间 2005年10月25日 地点 哈佛大学 翻译 阮一峰 原文 http www stephenwolfram com publications recent ycombinatorschool 这里是创业学校 所以我觉得 应该跟你们讲一
  • 智能指针类模板:auto_ptr、unique_ptr、shared_ptr的原理与使用

    1 什么是智能指针 智能指针是行为类似于指针的类对象 通常用于管理动态内存分配 C 程序通常手动动态分配堆内存 但如果动态分配的内存没有释放 则会发生内存泄漏 例如代码段1 1 代码段1 1 void demo double pd new
  • C++STL之unordered_set简单使用

    目录 简介 常用函数 代码 运行截图 参考 简介 unordered set 容器 可直译为 无序 set 容器 即 unordered set 容器和 set 容器很像 唯一的区别就在于 set 容器会自行对存储的数据进行排序 而 uno
  • Qt day04

    一 Input Widgets 1 QComboBox 1 添加备选内容 在设计师中双击控件输入添加 在代码中输入 ui gt comboBox gt addItem 金嘉宇 2 常用信号 void currentIndexChanged
  • 【LeetCode——删除重复元素】

    删除数组中的重复元素 leetcode 删除数组中的重复元素 双指针 leetcode 删除数组中的重复元素 输入 nums 0 0 1 1 1 2 2 3 3 4 输出 5 nums 0 1 2 3 4 解释 函数应该返回新的长度 5 并
  • php中的pdo对象,php中PDO操作大对象方法(blob)

    参考php中的官方文档 1 insert blob into databse oracle db new PDO oci scott tiger stmt db gt prepare insert into images id conten
  • (React入门) Context上下文

    React应用中 数据通过props属性自上而下 由父组件向子组件 传递 当组件层级数量增多时 在每一层传递props则很繁琐 Context提供了一种新的组件之间共享数据的方式 允许数据隔代传递 而不必显式的通过组件树逐层传递props
  • 详情页点击标题,滚动到对应主题笔记

    详情页点击标题 滚动到对应主题 防抖 提高性能 不做频繁操作 详情页点击标题 滚动到对应主题 netxTick 图片的高度没有被计算在内 这里是等图片加载完成后获得相对 ref 名 el offsetTop的值 如果不等图片加载完 获取的值
  • g++安装

    我的虚拟机装的是ubuntu14 0 4 今天使用g 的时候 发现竟然没有安装g 百度以后才知道 g 是Linux下C 代码的编译器 gcc是C代码的编译器 找了很多文章 都说安装g 直接sudo apt get g 或者g X X X X
  • 利用MATLAB设计低通滤波器和CIC滤波器

    FDATool界面左下侧排列了一组工具按钮 其功能分别如下所述 创建多速率滤波器 Create a Multirate Filter 滤波器转换 TransForm Filter 设置量化参数 Set Quantization Parame
  • API 接口防刷(接口请求次数限制)

    目录 一 问题 1 解决 2 原理 二 实现 1 导入坐标 2 自定义注解 3 Redis 缓存工具类 4 自定义拦截器 5 WebConfig 配置类 6 异常处理器 1 异常标记码 1 通用对象返回类 7 Redis序列化配置 8 测试
  • 【Flink】yarn集群模式

    预备知识 Linux export 命令的生命周期 断开会话后 export 的环境变量不生效 支持会话级别的新增 删除和修改环境变量 用作之后的程序使用 仅仅用作此次会话期间 基于 YARN 模式部署 Flink 服务 3 1 基于 YA
  • 【SPI协议】

    一 SPI介绍 SPI是 全双工 通信 具有单独的发送和接收线 可以同时进行发送和接收 从机不主动发起访问 总是被动执行操作 SPI包含4根逻辑线 MISO 主机输入 从机输出 MOSI 主机输出 从机输入 SCLK 串行时钟信号 此信号由