1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1.前言
STM32的SPI外设可用作通讯的主机及从机,支持最高的SCK时钟频率为fpclk/2 (STM32F103型号的芯片默认 fpclk1为 36MHz,fpclk2为 72MHz),完全支持 SPI协议的4种模式,数据帧长度可设置为8位或16位,可设置数据 MSB先行或 LSB 先行。它还支持双线全双工、双线单向以及单线模式。其中双线单向模式可以同时使用 MOSI及 MISO 数据线向一个方向传输数据,可以加快一倍的传输速度。而单线模式则可以减少硬件接线,当然这样速率会受到影响。 备注:下面的介绍都是基于STM32F103平台。2.SPI功能框图 通常SPI通过4个引脚与外部器件相连:
[tr]引脚SPI1SPI2[/tr]
3.初始化SPI接口 初始化SPI接口主要步骤:
void Bsp_Spi_Init(void) { SPI_InitTypeDef SPI_InitStructure; Bsp_Spi_LowLevel_Init(); /*!< Deselect the FLASH: Chip Select high */ BMI160_CS_HIGH(); /*!< SPI configuration */ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(BMI160_SPI, &SPI_InitStructure); /*!< Enable the sFLASH_SPI */ SPI_Cmd(BMI160_SPI, ENABLE); } 根据实际测试,传输速率为4.5M,与我们SPI初始化预想的值是一样的。 4.SPI通信读写数据 STM32使用 SPI外设通讯时,在通讯的不同阶段它会对“状态寄存器 SR”的不同数据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。下图是“主模式”流程,即 STM32 作为 SPI 通讯的主机端时的数据收发过程。 主模式收发流程及事件说明如下:
/** * @brief 使用SPI读取一个字节的数据 * @param 读取数据的地址 * @retval 返回接收到的数据状态 */ int8_t SPI_FLASH_ReadByte(uint8_t* pBuffer) { SPITimeout = SPIT_FLAG_TIMEOUT; /* 等待接收缓冲区非空,RXNE事件 */ while (SPI_I2S_GetFlagStatus(BMI160_SPI, SPI_I2S_FLAG_RXNE) == RESET) { if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(1); } /* 读取数据寄存器,获取接收缓冲区数据 */ *pBuffer =SPI_I2S_ReceiveData(BMI160_SPI); return 0; } /** * @brief 使用SPI发送一个字节的数据 * @param byte:要发送的数据 * @retval 返回接发送的数据状态 */ int8_t SPI_FLASH_SendByte(uint8_t byte) { SPITimeout = SPIT_FLAG_TIMEOUT; /* 等待发送缓冲区为空,TXE事件 */ while (SPI_I2S_GetFlagStatus(BMI160_SPI, SPI_I2S_FLAG_TXE) == RESET) { if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0); } /* 写入数据寄存器,把要写入的数据写入发送缓冲区 */ SPI_I2S_SendData(BMI160_SPI, byte); return 0; } /** * @brief Writes block of data to the Slave. * @param pBuffer: pointer to the buffer containing the data to be written * to the Slave. * @param WriteAddr: Slave's internal address to write to. * @param NumByteToWrite: number of bytes to write to the Slave. * @retval Communication result */ int8_t Bsp_Spi_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { int8_t ret; uint8_t tmpBuf; /*!< Select the Slave: Chip Select low */ BMI160_CS_LOW(); ret = SPI_FLASH_SendByte(WriteAddr); ret = SPI_FLASH_ReadByte(&tmpBuf); /*!< while there is data to be written on the Slave*/ while (NumByteToWrite--) { /*!< Send the current byte */ ret = SPI_FLASH_SendByte(*pBuffer); ret = SPI_FLASH_ReadByte(&tmpBuf); /*!< Point on the next byte to be written */ pBuffer++; } /*!< Deselect the FLASH: Chip Select high */ BMI160_CS_HIGH(); return ret; } /** * @brief Reads a block of data from the Slave. * @param pBuffer: pointer to the buffer that receives the data read from the Slave. * @param ReadAddr: Slave internal address to read from. * @param NumByteToRead: number of bytes to read from the Slave. * @retval Communication result */ int8_t Bsp_Spi_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) { int8_t ret; uint8_t tmpBuf; /*!< Select the FLASH: Chip Select low */ BMI160_CS_LOW(); ret = SPI_FLASH_SendByte(ReadAddr); ret = SPI_FLASH_ReadByte(&tmpBuf); while (NumByteToRead--) /*!< while there is data to be read */ { /*!< Read a byte from the FLASH */ ret = SPI_FLASH_SendByte(Dummy_Byte); ret = SPI_FLASH_ReadByte(pBuffer); /*!< Point to the next location where the byte read will be saved */ pBuffer++; } /*!< Deselect the FLASH: Chip Select high */ BMI160_CS_HIGH(); return ret; } 备注:其中SPI工作在全双工的模式:5.验证结果 移植SPI IMU BMI160后设备打印的log: starting up!!! BMI160 Init is successful!!! rslt = 0, chip_id = 0xd1 BMI160 accel & gyro config is successful!!! [accel] X = 1.11g/s, Y = 0.26g/s, Z = 9.95g/s [gyro] X = 0.30°/s, Y = -0.24°/s, Z = -0.37°/s [accel] X = 1.01g/s, Y = 0.17g/s, Z = 10.06g/s 下面是逻辑分析仪通信时抓取的数据(读取Chip ID的数据): |
||
|
||
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1763 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1617 浏览 1 评论
1059 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
723 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1670 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
726浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
592浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 17:12 , Processed in 0.734331 second(s), Total 75, Slave 59 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号