STM32-SPI资料整理
目录
一、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资料整理相关推荐
- STM32 资料整理贴(更新到10年1月)[转]
看到9G从QQ群上转的,后来还有没贴完 ,后面还有一大堆 链接地址 http://www.stmsky.com/bbs/viewthread.php?tid=2103&extra=page%3 ...
- STM32 资料整理贴
STM32 资料整理贴(更新到10年3月) http://www.stmsky.com/bbs/viewthread.php?tid=2103 很好多资料不错的. 转载于:https://www.cn ...
- LPS25HB 气压计 资料整理
LPS25HB 气压计 资料整理 文章目录 LPS25HB 气压计 资料整理 LPS25HB 的主要特性: LPS25HB 的应用场景: LPS25HB的管脚: LPS25HB的机械物理性能展表 LP ...
- 嵌入式相关芯片资料整理
嵌入式相关芯片资料整理 各类芯片简介 **嵌入式相关芯片资料整理** 一.TFT_LCD芯片简介 二.M74HC688MR芯片简介 三.M74HC573M1R芯片简介 四.STM32F103RBT6芯 ...
- 如何查找STM32开发资料
推荐 分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang Ⅰ.概述 该 ...
- STM32 SPI+DMA 驱动 SRAM LY68L6400SLIT 应用笔记
关键词:库函数,STM32F407,SPI+DMA ,SPI-DMA,SRAM , LY68L6400SLIT,STM32CubeMX 编 辑:大黄蜂 说明:本笔记记录 基于 STM32F407 + ...
- 开发STM32相关资料下载
Ⅰ.写在前面 很多初学的朋友经常都会问"******"资料哪儿有? "******"文档在哪儿下载? "******"教程在哪儿可以获取的到 ...
- 【Benewake(北醒) 】短距 TFmini Plus 12m介绍以及资料整理
目录 1 前言 2 产品介绍 3 产品快速测试 3.1 产品规格书及使用说明书 3.2 通用上位机测试说明 3.3 通用指令串口助手使用说明 3.4 产品快速测试说明 3.5 操作视频 4 基于开源硬 ...
- 【Benewake(北醒) 】长距 TF350 350m介绍以及资料整理
目录 1 前言 2 产品介绍 3 产品快速测试 3.1 产品规格书及使用说明书 3.2 通用上位机测试说明 3.3 通用指令串口助手使用说明 3.4 产品快速测试说明 4 基于开源硬件的运用整理 4. ...
- 【Benewake(北醒) 】短距 TFmini-S 12m介绍以及资料整理
目录 1 前言 2 产品介绍 3 产品快速测试 3.1 产品规格书及使用说明书 3.2 通用上位机测试说明 3.3 通用指令串口助手使用说明 3.4 产品快速测试说明 3.5 操作视频 4 基于开源硬 ...
最新文章
- java虚拟机规范-加载、链接与初始化
- 邮箱有什么用_大公司为什么要用企业邮箱?大公司企业邮箱用什么比较好?
- Python虚拟环境virtualenv的安装与使用详解(转)
- AUTOSAR从入门到精通100讲(四十四)-AUTOSAR 通信服务-PDU Router
- 不使用输入框如何实现下拉_如何利用Axure实现下拉子菜单?
- 如何得到当前浏览器是什么
- 如何在VS 2010中使用 VS2013的解决方案
- 关于 Eureka 2.x,别再人云亦云了!
- IAR for 8051安装教程
- Fiddler中文乱码设置
- QT网络编程TCP/UDP开发流程 制作网络调试助手
- roseha 8.9 for linux oracle 11g,RoseHA 9.0 for Linux配合Oracle12c配置文档_v2.0-2015-04.pdf
- android电视工程模式,智能电视进入工厂/工程模式教程汇总!
- 萤石开放平台-摄像头画面如何在小程序上播放?
- 为什么使用Python保存的视频特别大!!(数据速率/总比特率)
- Stepping Number
- Crossbar率先发难—欲彻底埋葬英特尔的3D XPoint技术
- 罗丹明 PEG 巯基,Rhodamine PEG Thiol,荧光染料标记巯基/硫醇
- u盘正常接入后计算机无法看到,U盘连接到电脑之后,电脑无反应怎么办?
- 微信是怎么打造平台型生态商业模式的?