目录

一、SPI的简介

1、SPI物理层

2、协议层

(1)SPI基本通讯时序

(2)起始信号与停止信号

(3)数据有效性

(4)SPI的4种通讯模式 (CPOL - 时钟极性 与 CPHA - 时钟相位)

二、 软件模拟SPI示例

1、软件SPI结构体 以及 SPI模式枚举

2、SPI初始化函数

3、SPI读写函数

三、 STM32-SPI 外设使用示例(HAL库)

四、SPI常规调试手段


一、SPI的简介

1、SPI物理层

SPI 一般使用4条线进行通信:

  • NSS:为片选线
  • MOSI: 主机数据输出、从机数据输入
  • MISO:主机数据输入、从机数据输出
  • SCK:时钟线,由主机提供时钟输出

2、协议层

(1)SPI基本通讯时序

(2)起始信号与停止信号

  • 开始信号:NSS 由 高变低
  • 停止信号:NSS 由 低变高

(3)数据有效性

  • SPI 使用 SCK线进行数据同步,MOSI与MISO在SCK的每个时钟周期传输一位数据、且数据的 输入 与 输出 是同步进行的
  • 进行数据传输时,一般采取MSB先行(先发送高字节,再发低字节)
  • SPI 每次数据传输可以8位或16位为单位,每次传输的单位数不受限制

(4)SPI的4种通讯模式 (CPOL - 时钟极性 与 CPHA - 时钟相位)

  • 时钟极性 CPOL: 表示SCK的空闲状态时候的电平。 (如: CPOL = 0   ----  SCK空闲状态为低电平; CPOL = 1 ---- SCK空闲状态为高电平)
  • 时钟相位 CPHA: 表示数据何时被采样。(如: CPHA = 0 ---- SCK的奇数边沿被采样; CPHA = 1 ---- SCK的偶数边沿被采样)

SPI的四种模式:

CPHA = 0时(采样边沿为 奇数边沿的SPI时序图)

CPHA = 1时(采样边沿为 偶数边沿的SPI时序图)

二、 软件模拟SPI示例

1、软件SPI结构体 以及 SPI模式枚举

typedef enum
{MODE_0 = 0,   /* CPOL = 0, CPHA = 0;  */MODE_1,         /* CPOL = 0, CPHA = 1;  */MODE_2,         /* CPOL = 1, CPHA = 0;  */MODE_3,         /* CPOL = 1, CPHA = 1;  */}exSPIModeEnum;typedef struct SoftSPIHandle
{GPIO_TypeDef * NSS_Port;GPIO_TypeDef * SCK_Port;GPIO_TypeDef * MOSI_Port;GPIO_TypeDef * MISO_Port;uint16_t NSS_Pin;uint16_t SCK_Pin;uint16_t MOSI_Pin;uint16_t MISO_Pin;exSPIModeEnum mode;void (* SetHigh)(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);void (* SetLow)(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);void (* SetMode)(struct SoftSPIHandle xSoftSPIHandle, exSPIModeEnum eMode);uint8_t (* ReadPin)(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);void (* SoftSPIWriteData)(struct SoftSPIHandle xSoftSPIHandle, uint8_t *pData, uint32_t uiLength);void (* SoftSPIReadData)(struct SoftSPIHandle xSoftSPIHandle, uint8_t *pData, uint32_t uiLength);}SoftSPIHandle;

2、SPI初始化函数

void vSoftSPIInit(exSPIModeEnum eMode)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* 管脚初始化 */SOFT_SPI_CLK_ENABLE();/**SPI1 GPIO ConfigurationPB14    ------> SPI1_NSSPB3     ------> SPI1_SCKPB4     ------> SPI1_MISOPB5     ------> SPI1_MOSI*/GPIO_InitStruct.Pin = SOFT_SPI_NSS_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(SOFT_SPI_NSS_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = SOFT_SPI_SCK_PIN;HAL_GPIO_Init(SOFT_SPI_SCK_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = SOFT_SPI_MOSI_PIN;HAL_GPIO_Init(SOFT_SPI_MOSI_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin  = SOFT_SPI_MISO_PIN;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;HAL_GPIO_Init(SOFT_SPI_MISO_PORT, &GPIO_InitStruct);/* 初始化Soft SPI 句柄 */ex_SoftSPIHandle.NSS_Port = ex_SoftSPIHandle.SCK_Port = ex_SoftSPIHandle.MISO_Port = ex_SoftSPIHandle.MOSI_Port = GPIOB;ex_SoftSPIHandle.NSS_Pin = SOFT_SPI_NSS_PIN;ex_SoftSPIHandle.SCK_Pin = SOFT_SPI_SCK_PIN;ex_SoftSPIHandle.MOSI_Pin = SOFT_SPI_MOSI_PIN;ex_SoftSPIHandle.MISO_Pin = SOFT_SPI_MISO_PIN;/* 注册Soft SPI 函数 */ex_SoftSPIHandle.SetHigh = vSetHigh;ex_SoftSPIHandle.SetLow = vSetLow;ex_SoftSPIHandle.SetMode = vSetMode;ex_SoftSPIHandle.ReadPin = HAL_GPIO_ReadPin;ex_SoftSPIHandle.SoftSPIWriteData = vSoftSPIWriteData;ex_SoftSPIHandle.SoftSPIReadData = vSoftSPIReadData;/* 设置对应SPI模式 */ex_SoftSPIHandle.mode = eMode;if(eMode & MODE_0){/* CPOL = 0 ; CPHA = 0 *//* SPI 默认模式0 处于空闲状态 */SOFT_SPI_NSS_High();SOFT_SPI_SCK_Low();}else if(eMode & MODE_1){/* CPOL = 0 ; CPHA = 1 *//* SPI 默认模式1 处于空闲状态 */SOFT_SPI_NSS_High();SOFT_SPI_SCK_Low();}else if(eMode & MODE_2){/* CPOL = 1 ; CPHA = 0 *//* SPI 默认模式2 处于空闲状态 */SOFT_SPI_NSS_High();SOFT_SPI_SCK_High();}else{/* CPOL = 1 ; CPHA = 1 *//* SPI 默认模式3 处于空闲状态 */SOFT_SPI_NSS_High();SOFT_SPI_SCK_High();}}

3、SPI读写函数

static void vSoftSPIWriteData(SoftSPIHandle xSoftSPIHandle, uint8_t *pData, uint32_t uiLength)
{for(uint32_t i = 0; i < uiLength; i++)ucSoftSPIReadWriteByte(xSoftSPIHandle, pData[i]);
}static void vSoftSPIReadData(SoftSPIHandle xSoftSPIHandle, uint8_t *pData, uint32_t uiLength)
{for(uint32_t i = 0; i < uiLength; i++)pData[i] = ucSoftSPIReadWriteByte(xSoftSPIHandle, DummyByte);
}static uint8_t ucSoftSPIReadWriteByte(SoftSPIHandle xSoftSPIHandle, uint8_t ucData)
{uint8_t ucRecvData = 0;if(xSoftSPIHandle.mode == MODE_0){/* CPOL = 0 ; CPHA = 0 *//* 数据传输 */for(uint8_t i = 0; i < 8; i++){/* 发送数据 */xSoftSPIHandle.SetLow(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);if( ucData & 0x80 )xSoftSPIHandle.SetHigh(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);elsexSoftSPIHandle.SetLow(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);ucData <<= 1;xSoftSPIHandle.SetHigh(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);/* 接收数据 */ucRecvData <<= 1;if(xSoftSPIHandle.ReadPin(xSoftSPIHandle.MISO_Port, xSoftSPIHandle.MISO_Pin))ucRecvData |= 1;}xSoftSPIHandle.SetLow(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);}else if(xSoftSPIHandle.mode == MODE_1){/* CPOL = 0 ; CPHA = 1 *//* 数据传输 */for(uint8_t i = 0; i < 8; i++){/* 发送数据 */xSoftSPIHandle.SetHigh(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);if( ucData & 0x80 )xSoftSPIHandle.SetHigh(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);elsexSoftSPIHandle.SetLow(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);ucData <<= 1;xSoftSPIHandle.SetLow(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);/* 接收数据 */ucRecvData <<= 1;if(xSoftSPIHandle.ReadPin(xSoftSPIHandle.MISO_Port, xSoftSPIHandle.MISO_Pin))ucRecvData |= 1;}xSoftSPIHandle.SetLow(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);}else if(xSoftSPIHandle.mode == MODE_2){/* CPOL = 1 ; CPHA = 0 *//* 数据传输 */for(uint8_t i = 0; i < 8; i++){/* 发送数据 */xSoftSPIHandle.SetHigh(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);if( ucData & 0x80 )xSoftSPIHandle.SetHigh(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);elsexSoftSPIHandle.SetLow(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);ucData <<= 1;xSoftSPIHandle.SetLow(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);/* 接收数据 */ucRecvData <<= 1;if(xSoftSPIHandle.ReadPin(xSoftSPIHandle.MISO_Port, xSoftSPIHandle.MISO_Pin))ucRecvData |= 1;}xSoftSPIHandle.SetHigh(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);}else{/* CPOL = 1 ; CPHA = 1 *//* 数据传输 */for(uint8_t i = 0; i < 8; i++){/* 发送数据 */xSoftSPIHandle.SetLow(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);if( ucData & 0x80 )xSoftSPIHandle.SetHigh(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);elsexSoftSPIHandle.SetLow(xSoftSPIHandle.MOSI_Port, xSoftSPIHandle.MOSI_Pin);ucData <<= 1;xSoftSPIHandle.SetHigh(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);vDelayus(2);/* 接收数据 */ucRecvData <<= 1;if(xSoftSPIHandle.ReadPin(xSoftSPIHandle.MISO_Port, xSoftSPIHandle.MISO_Pin))ucRecvData |= 1;}xSoftSPIHandle.SetHigh(xSoftSPIHandle.SCK_Port, xSoftSPIHandle.SCK_Pin);}return ucRecvData;
}

三、 STM32-SPI 外设使用示例(HAL库)

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspInit 0 *//* USER CODE END SPI1_MspInit 0 *//* SPI1 clock enable */__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**SPI1 GPIO ConfigurationPB3     ------> SPI1_SCKPB4     ------> SPI1_MISOPB5     ------> SPI1_MOSIPB14 ------> SPI1_NSS*/GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_InitStruct.Pin  = SPI1_NSS_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;HAL_GPIO_Init(SPI1_NSS_Port, &GPIO_InitStruct);/* USER CODE BEGIN SPI1_MspInit 1 *//* USER CODE END SPI1_MspInit 1 */}
}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspDeInit 0 *//* USER CODE END SPI1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI1_CLK_DISABLE();/**SPI1 GPIO ConfigurationPB3     ------> SPI1_SCKPB4     ------> SPI1_MISOPB5     ------> SPI1_MOSI*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);/* USER CODE BEGIN SPI1_MspDeInit 1 *//* USER CODE END SPI1_MspDeInit 1 */}
}void vSPI1Init(void)
{ex_SPI1Handle.Instance = SPI1;ex_SPI1Handle.Init.Mode = SPI_MODE_MASTER;ex_SPI1Handle.Init.Direction = SPI_DIRECTION_2LINES;ex_SPI1Handle.Init.DataSize = SPI_DATASIZE_8BIT;ex_SPI1Handle.Init.CLKPolarity = SPI_POLARITY_LOW;ex_SPI1Handle.Init.CLKPhase = SPI_PHASE_1EDGE;ex_SPI1Handle.Init.NSS = SPI_NSS_SOFT;ex_SPI1Handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;ex_SPI1Handle.Init.FirstBit = SPI_FIRSTBIT_MSB;ex_SPI1Handle.Init.TIMode = SPI_TIMODE_DISABLE;ex_SPI1Handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;ex_SPI1Handle.Init.CRCPolynomial = 10;HAL_SPI_Init(&ex_SPI1Handle);
}int8_t cSPIWriteData(SPI_HandleTypeDef *ex_SPIhandle, uint8_t *pData, uint16_t usLength)
{int8_t status = HAL_ERROR;status = HAL_SPI_Transmit(ex_SPIhandle, pData, usLength, 1000);return status;
}int8_t cSPIReadData(SPI_HandleTypeDef *ex_SPIhandle, uint8_t *pData, uint16_t usLength)
{int8_t status = HAL_ERROR;status = HAL_SPI_Receive(ex_SPIhandle, pData, usLength, 1000);return status;}

四、SPI常规调试手段

1、如:SPI FLASH 可以发送 读取芯片ID的指令查看是否能够正确返回芯片的ID

参考资料为:

【野火】《STM32 HAL库开发实战指南-基于F407》

【正点原子】《STM32F4开发指南(HAL库版)》

STM32-SPI资料整理相关推荐

  1. STM32 资料整理贴(更新到10年1月)[转]

    看到9G从QQ群上转的,后来还有没贴完 ,后面还有一大堆 链接地址 http://www.stmsky.com/bbs/viewthread.php?tid=2103&extra=page%3 ...

  2. STM32 资料整理贴

    STM32 资料整理贴(更新到10年3月) http://www.stmsky.com/bbs/viewthread.php?tid=2103 很好多资料不错的. 转载于:https://www.cn ...

  3. LPS25HB 气压计 资料整理

    LPS25HB 气压计 资料整理 文章目录 LPS25HB 气压计 资料整理 LPS25HB 的主要特性: LPS25HB 的应用场景: LPS25HB的管脚: LPS25HB的机械物理性能展表 LP ...

  4. 嵌入式相关芯片资料整理

    嵌入式相关芯片资料整理 各类芯片简介 **嵌入式相关芯片资料整理** 一.TFT_LCD芯片简介 二.M74HC688MR芯片简介 三.M74HC573M1R芯片简介 四.STM32F103RBT6芯 ...

  5. 如何查找STM32开发资料

    推荐 分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang Ⅰ.概述 该 ...

  6. STM32 SPI+DMA 驱动 SRAM LY68L6400SLIT 应用笔记

    关键词:库函数,STM32F407,SPI+DMA ,SPI-DMA,SRAM , LY68L6400SLIT,STM32CubeMX 编 辑:大黄蜂 说明:本笔记记录 基于 STM32F407 + ...

  7. 开发STM32相关资料下载

    Ⅰ.写在前面 很多初学的朋友经常都会问"******"资料哪儿有? "******"文档在哪儿下载? "******"教程在哪儿可以获取的到 ...

  8. 【Benewake(北醒) 】短距 TFmini Plus 12m介绍以及资料整理

    目录 1 前言 2 产品介绍 3 产品快速测试 3.1 产品规格书及使用说明书 3.2 通用上位机测试说明 3.3 通用指令串口助手使用说明 3.4 产品快速测试说明 3.5 操作视频 4 基于开源硬 ...

  9. 【Benewake(北醒) 】长距 TF350 350m介绍以及资料整理

    目录 1 前言 2 产品介绍 3 产品快速测试 3.1 产品规格书及使用说明书 3.2 通用上位机测试说明 3.3 通用指令串口助手使用说明 3.4 产品快速测试说明 4 基于开源硬件的运用整理 4. ...

  10. 【Benewake(北醒) 】短距 TFmini-S 12m介绍以及资料整理

    目录 1 前言 2 产品介绍 3 产品快速测试 3.1 产品规格书及使用说明书 3.2 通用上位机测试说明 3.3 通用指令串口助手使用说明 3.4 产品快速测试说明 3.5 操作视频 4 基于开源硬 ...

最新文章

  1. java虚拟机规范-加载、链接与初始化
  2. 邮箱有什么用_大公司为什么要用企业邮箱?大公司企业邮箱用什么比较好?
  3. Python虚拟环境virtualenv的安装与使用详解(转)
  4. AUTOSAR从入门到精通100讲(四十四)-AUTOSAR 通信服务-PDU Router
  5. 不使用输入框如何实现下拉_如何利用Axure实现下拉子菜单?
  6. 如何得到当前浏览器是什么
  7. 如何在VS 2010中使用 VS2013的解决方案
  8. 关于 Eureka 2.x,别再人云亦云了!
  9. IAR for 8051安装教程
  10. Fiddler中文乱码设置
  11. QT网络编程TCP/UDP开发流程 制作网络调试助手
  12. roseha 8.9 for linux oracle 11g,RoseHA 9.0 for Linux配合Oracle12c配置文档_v2.0-2015-04.pdf
  13. android电视工程模式,智能电视进入工厂/工程模式教程汇总!
  14. 萤石开放平台-摄像头画面如何在小程序上播放?
  15. 为什么使用Python保存的视频特别大!!(数据速率/总比特率)
  16. Stepping Number
  17. Crossbar率先发难—欲彻底埋葬英特尔的3D XPoint技术
  18. 罗丹明 PEG 巯基,Rhodamine PEG Thiol,荧光染料标记巯基/硫醇
  19. u盘正常接入后计算机无法看到,U盘连接到电脑之后,电脑无反应怎么办?
  20. 微信是怎么打造平台型生态商业模式的?

热门文章

  1. 2014年中南大学上机复试
  2. JAVA-读取excel转成html 将excel表格转换为HTML文件格式 转成前端表格样式
  3. 阿里巴巴Java开发规范(终极版v1.3.0)--个人整理
  4. 火焰图(FlameGraph)的使用
  5. jeesite代码生成器的使用(初学者)
  6. 仙人掌之歌——路转峰回(3)
  7. mdobus传输数据为正接收到为负数
  8. 一些技能点语法糖(上)
  9. 性能测试和优化实录(mybatisplus异步写库@Async引起的对象无法释放问题)
  10. vue webapp之music(六)利用axios与后端接口代理请求歌单推荐数据