STM32-SPI接口

article/2025/8/23 6:26:18

一、SPI协议【SerialPeripheral Interface】

        串行外围设备接口,是一种高速全双工的通信总线。在ADC/LCD等与MCU间通信。

1、SPI信号线

        SPI 包含 4 条总线,SPI 总线包含 4 条总线,分别为SS 、SCK、MOSI、MISO。

(1)SS(SlaveSelect):片选信号线,当有多个 SPI 设备与 MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其他的 SCK、MOSI、MISO 线则为多个设备并联到相同的 SPI 总线上,低电平有效。

(2)SCK (Serial Clock):时钟信号线,由主通信设备产生,不同的设备支持的时钟频率不一样,如 STM32 的 SPI 时钟频率最大为 f PCLK /2。

(3)MOSI (Master Output, Slave Input):主设备输出 / 从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入数据,即这条线上数据的方向为主机到从机。

(4)MISO(Master Input, Slave Output):主设备输入 / 从设备输出引脚。主机从这条信号线读入数据,从机的数据则由这条信号线输出,即在这条线上数据的方向为从机到主机。

2、SPI模式

根据 SPI 时钟极性(CPOL)和时钟相位(CPHA) 配置的不同,分为 4 种 SPI 模式。时钟极性是指 SPI 通信设备处于空闲状态时(也可以认为这是 SPI 通信开始时,即SS 为低电平时),SCK 信号线的电平信号。CPOL=0 时, SCK 在空闲状态时为低电平,CPOL=1 时则相反。时钟相位是指数据采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的奇数边沿被采样。当 CPHA=1 时,数据线在 SCK 的偶数边沿采样。

首先,由主机把片选信号线SS 拉低,意为主机输出,在SS 被拉低的时刻,SCK 分为两种情况,若我们设置为 CPOL=0,则 SCK 时序在这个时刻为低电平,若设置为 CPOL=1,则 SCK 在这个时刻为高电平。采样时刻都是在 SCK 的奇数边沿(注意奇数边沿有时为下降沿,有时为上升沿)。

CPHA=1时,数据信号的采样时刻为偶数边沿。

 

二、SPI特性及架构

(1)单次传输可选择为 8 或 16 位。

(2)波特率预分频系数(最大为 fPCLK/2) 。

(3)时钟极性(CPOL)和相位(CPHA)可编程设置 。

(4)数据顺序的传输顺序可进行编程选择,MSB 在前或 LSB 在前。

(5)可触发中断的专用发送和接收标志。

(6)可以使用 DMA 进行数据传输操作。

1、SPI架构

MISO 数据线接收到的信号经移位寄存器处理后把数据转移到接收缓冲区,然后这个数据就可以由我们的软件从接收缓冲区读出了。

当要发送数据时,我们把数据写入发送缓冲区,硬件将会把它用移位寄存器处理后输出到 MOSI 数据线。

SCK 的时钟信号则由波特率发生器产生,我们可以通过波特率控制位(BR)来控制它输出的波特率。

控制寄存器 CR1 掌管着主控制电路,STM32 的 SPI 模块的协议设置(时钟极性、相位等)就是由它来制定的。而控制寄存器 CR2 则用于设置各种中断使能。

最后为 NSS 引脚,这个引脚扮演着 SPI 协议中的SS 片选信号线的角色,如果我们把 NSS 引脚配置为硬件自动控制,SPI 模块能够自动判别它能否成为 SPI 的主机,或自动进入 SPI 从机模式。但实际上我们用得更多的是由软件控制某些 GPIO 引脚单独作为SS信号,这个 GPIO 引脚可以随便选择。

 

三、SPI接口读取Flash

        各信号线相应连接到 Flash(型号 :W25X16/W25Q16)的 CS、CLK、DO 和 DIO 线,实现SPI 通信,对 Flash进行读写,其中 W25X16 和 W25Q16 在程序上不同的地方是 FLASH 的ID 不一样。

        读取 Flash 的 ID 信息,写入数据,并读取出来进行校验,通过串口打印写入与读取出来的数据,输出测试结果。

        不同的设备都会相应的有不同的指令,如 EEPROM 中会把第一个数据解释为存储矩阵的地址(实质就是指令)。而 Flash 则定义了更多的指令,有写指令、读指令、读ID 指令等。

SPI-FLASH通信:

(1)配置 I/O端口,使能 GPIO。

(2)根据将要进行通信器件的 SPI模式,配置 STM32的 SPI,使能 SPI时钟。

(3)配置好 SPI后,根据各种 Flash定义的命令控制对它的读写。

注意在写操作前要先进行存储扇区的擦除操作,擦除操作前也要先发出“写使能”命令

1、 main.c

 

 
  1. int main(void)

  2. {

  3. /* 配置串口 1 为:115200 8-N-1 */

  4. USART1_Config();

  5. printf("\r\n 这是一个 2M 串行 flash(W25X16)实验 \r\n");

  6.  
  7. /* 2M 串行 flash W25Q16 初始化 */

  8. SPI_FLASH_Init();

  9.  
  10. /* Get SPI Flash Device ID */

  11. DeviceID = SPI_FLASH_ReadDeviceID();

  12.  
  13. Delay( 200 );

  14.  
  15. /* Get SPI Flash ID */

  16. FlashID = SPI_FLASH_ReadID();

  17.  
  18. printf("\r\n FlashID is 0x%X, Manufacturer Device ID is 0x%X\r\n", FlashID, DeviceID);

  19.  
  20. /* Check the SPI Flash ID */

  21. if (FlashID == sFLASH_ID) /* #define sFLASH_ID 0xEF3015 */

  22. {

  23. printf("\r\n 检测到串行 flash W25X16 !\r\n");

  24.  
  25. SPI_FLASH_SectorErase(FLASH_SectorToErase);

  26. SPI_FLASH_BufferWrite(Tx_Buffer, FLASH_WriteAddress, BufferSize);

  27. printf("\r\n 写入的数据为:%s \r\t", Tx_Buffer);

  28.  
  29. SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);

  30. printf("\r\n 读出的数据为:%s \r\n", Tx_Buffer);

  31. /* 检查写入的数据与读出的数据是否相等 */

  32. TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);

  33.  
  34. if ( PASSED == TransferStatus1 )

  35. {

  36. printf("\r\n 2M 串行 flash(W25X16)测试成功!\n\r");

  37. }

  38. else

  39. {

  40. printf("\r\n 2M 串行 flash(W25X16)测试失败!\n\r");

  41. }

  42. }// if (FlashID == sFLASH_ID)

  43. else

  44. {

  45. printf("\r\n 获取不到 W25X16 ID!\n\r");

  46.  
  47. }

  48.  
  49. SPI_Flash_PowerDown();

  50. while (1);

  51. }

 

(1)调用 USART1Confi g() 初始化串口。

(2)调用 SPI_FLASH_Init() 初始化 SPI 模块。

(3)调用 SPI_FLASH_ReadDeviceID() 读取 Flash 器件生产厂商的 ID 信息。

(4)调用 SPI_FLASH_ReadID() 读取 Flash 器件的设备 ID 信息

(5)若读取得的ID正确, 则调用 SPI_FLASH_SectorErase()把 Flash 的内 容擦除,擦除后调用SPI_FLASH_BufferWrite() 向Flash 写入数据,然后再调用SPI_FLASH_BufferRead()从刚刚写入的地址中读出数据。最后调用 Buffercmp() 函数对写入的数据与读取的数据进行比较,若写入的数据与读出的数据相同,则把标志变量TransferStatus1 赋值为 PASSED(自定义的枚举变量)。

(6)最后调用 SPI_Flash_PowerDown()函数关闭 Flash 设备的电源,因为数据写入到Flash 后并不会因断电而丢失,我们在使用它时才重新开启 Flash 的电源

 

2、SPI初始化

 

 
  1. #define SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOA, GPIO_Pin_4)

  2. #define SPI_FLASH_CS_LOW() GPIO_ResetBits(GPIOA, GPIO_Pin_4)

  3.  
  4. void SPI_FLASH_Init(void)

  5. {

  6. SPI_InitTypeDef SPI_InitStructure;

  7. GPIO_InitTypeDef GPIO_InitStructure;

  8.  
  9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);

  10. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  11.  
  12. /* SCK */

  13. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

  14. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  15. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  16. GPIO_Init(GPIOA, &GPIO_InitStructure);

  17.  
  18. /* MISO */

  19. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

  20. GPIO_Init(GPIOA, &GPIO_InitStructure);

  21.  
  22. /* MOS */

  23. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

  24. GPIO_Init(GPIOA, &GPIO_InitStructure);

  25.  
  26. /* CS */

  27. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  28. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  29. GPIO_Init(GPIOA, &GPIO_InitStructure);

  30.  
  31. SPI_FLASH_CS_HIGH();

  32.  
  33. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  34. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  35. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

  36. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

  37. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  38. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  39. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

  40. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

  41. SPI_InitStructure.SPI_CRCPolynomial = 7;

  42. SPI_Init(SPI1, &SPI_InitStructure);

  43.  
  44. SPI_Cmd(SPI1, ENABLE);

  45. }

 

(1)SPI_Mode :主机模式(SPI_Mode_Master)或从机模式(SPI_Mode_Slave),这两个模式的最大区别为 SPI 的 SCK 信号线的时序,SCK 的时序是由通信中的主机产生的。若被配置为从机模式,STM32 的 SPI 模块将接受外来的 SCK 信号。
(2)SPI_DataSize : SPI 每次通信的数据大小(称为数据帧)为 8 位还是 16 位。

(3)SPI_CPOL 和 SPI_CPHA :配置SPI的时钟极性(CPOL)和时钟相位CPHA),这两个配置影响到 SPI 的通信模式,该设置要符合将要互相通信的设备的要求。CPOL 分别可以取 SPI_CPOL_High(SPI 通信空闲时 SCK 为高电平)和SPI_CPOL_Low(SPI 通信空闲时 SCK 为低电平)。CPHA 则可以取 SPI_CPHA_1Edge(在 SCK 的奇数边沿采集数据) 和 SPI_CPHA_2Edge(在 SCK偶数边沿采集数据)。

(4)SPI_NSS :配置NSS引脚的使用模式,硬件模式(SPI_NSS_Hard)与软件模式(SPI_NSS_Soft),在硬件模式中的 SPI 片选信号由硬件自动产生,而软件模式则需要我们亲自把相应的 GPIO 端口拉高或置低产生非片选和片选信号。如果外界条件允许,硬件模式还会自动将 STM32 的 SPI 设置为主机。我们使用软件模式,向这个成员赋值为 SPI_NSS_Soft。

(5)SPI_BaudRatePrescaler:本成员设置波特率分频值,分频后的时钟即为 SPI 的 SCK信号线的时钟频率。这个成员参数可设置为 f PCLK 的 2、4、6、8、16、32、64、128、256 分频。赋值为 SPI_BaudRatePrescaler_4,即 f PCLK 的 4 分频。

(6)SPI_FirstBit:所有串行的通信协议都会有 MSB 先行(高位数据在前)还是 LSB先行(低位数据在前)的问题,而 STM32 的 SPI 模块可以通过这个结构体成员,对这个特性编程控制。据 Flash 的通信时序,我们向这个成员赋值为MSB先行(SPI_FirstBit_MSB)。

(7)SPI_CRCPolynomial:这是 SPI 的 CRC 校验中的多项式,若我们使用 CRC 校验时,就使用这个成员的参数(多项式)来计算 CRC 的值。由于本实验的 Flash 不支持 CRC校验,所以我们向这个结构体成员赋值为 7 实际上是没有意义的。

配置完这些结构体成员后,我们要调用 SPI_Init() 函数把这些参数写入寄存器中,实现SPI 的初始化,然后调用 SPI_Cmd() 来使能 SPI1。

 

2、读FLASH的ID

 

 
  1. #define Dummy_Byte 0xFF

  2.  
  3. u8 SPI_FLASH_SendByte(u8 byte)

  4. {

  5. // 等待发送数据寄存器清空

  6. while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET);

  7.  
  8. SPI_I2S_SendData(SPI1, byte); // 向从机发送数据

  9. while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET); // 等待接收数据寄存器非空

  10.  
  11. return SPI_I2S_ReceiveData(SPI1); // 获取接收寄存器中的数据

  12. }

  13. u32 SPI_FLASH_ReadDeviceID(void)

  14. {

  15. u32 Temp = 0;

  16.  
  17. SPI_FLASH_CS_LOW();

  18. SPI_FLASH_SendByte(W25X_DeviceID);

  19. SPI_FLASH_SendByte(Dummy_Byte);

  20. SPI_FLASH_SendByte(Dummy_Byte);

  21. SPI_FLASH_SendByte(Dummy_Byte);

  22. Temp = SPI_FLASH_SendByte(Dummy_Byte);

  23. SPI_FLASH_CS_HIGH();

  24.  
  25. return Temp;

  26. }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

 

3、读取厂商ID

 

 
  1. u32 SPI_FLASH_ReadID(void)

  2. {

  3. u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

  4.  
  5. SPI_FLASH_CS_LOW();

  6. SPI_FLASH_SendByte(W25X_JedecDeviceID); // 0x9F

  7. Temp0 = SPI_FLASH_SendByte(Dummy_Byte);

  8. Temp1 = SPI_FLASH_SendByte(Dummy_Byte);

  9. Temp2 = SPI_FLASH_SendByte(Dummy_Byte);

  10. SPI_FLASH_CS_HIGH();

  11.  
  12. Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

  13. return Temp;

  14. }

 

4、擦除FLASH内容

 

 
  1. void SPI_FLASH_WriteEnable(void)

  2. {

  3. SPI_FLASH_CS_LOW();

  4. SPI_FLASH_SendByte(W25X_WriteEnable); // 06H

  5. SPI_FLASH_CS_HIGH();

  6. }

  7.  
  8. void SPI_FLASH_WaitForWriteEnd(void)

  9. {

  10. u8 FLASH_Status = 0;

  11.  
  12. SPI_FLASH_CS_LOW();

  13. SPI_FLASH_SendByte(W25X_ReadStatusReg); // 05H

  14. do

  15. {

  16. FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);

  17. }

  18. while ((FLASH_Status & WIP_Flag) == SET);

  19. SPI_FLASH_CS_HIGH();

  20. }

  21.  
  22. void SPI_FLASH_SectorErase(u32 SectorAddr)

  23. {

  24. SPI_FLASH_WriteEnable();

  25. SPI_FLASH_WaitForWriteEnd();

  26.  
  27. SPI_FLASH_CS_LOW();

  28. SPI_FLASH_SendByte(W25X_SectorErase); // 20H

  29. SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);

  30. SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);

  31. SPI_FLASH_SendByte(SectorAddr & 0xFF);

  32. SPI_FLASH_CS_HIGH();

  33.  
  34. SPI_FLASH_WaitForWriteEnd();

  35. }

 

5、向Flash写数据——分页

 

 
  1. void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)

  2. {

  3. SPI_FLASH_WriteEnable();

  4.  
  5. SPI_FLASH_CS_LOW();

  6. SPI_FLASH_SendByte(W25X_PageProgram); // 02H

  7. SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);

  8. SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);

  9. SPI_FLASH_SendByte(WriteAddr & 0xFF);

  10.  
  11. if(NumByteToWrite > SPI_FLASH_PerWritePageSize)

  12. {

  13. NumByteToWrite = SPI_FLASH_PerWritePageSize;

  14. }

  15.  
  16. while (NumByteToWrite--)

  17. {

  18. SPI_FLASH_SendByte(*pBuffer);

  19. pBuffer++;

  20. }

  21. SPI_FLASH_CS_HIGH();

  22.  
  23. SPI_FLASH_WaitForWriteEnd();

  24. }

  25.  
  26.  
  27. void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)

  28. {

  29. u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

  30.  
  31. Addr = WriteAddr % SPI_FLASH_PageSize;

  32. count = SPI_FLASH_PageSize - Addr;

  33. NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;

  34. NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;

  35.  
  36. if (Addr == 0)

  37. {

  38. if (NumOfPage == 0)

  39. {

  40. SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);

  41. }

  42. else

  43. {

  44. while (NumOfPage--)

  45. {

  46. SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);

  47. WriteAddr += SPI_FLASH_PageSize;

  48. pBuffer += SPI_FLASH_PageSize;

  49. }

  50.  
  51. SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);

  52. }

  53. }

  54. else

  55. {

  56. if (NumOfPage == 0)

  57. {

  58. if (NumOfSingle > count)

  59. {

  60. temp = NumOfSingle - count;

  61.  
  62. SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);

  63. WriteAddr += count;

  64. pBuffer += count;

  65.  
  66. SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);

  67. }

  68. else

  69. {

  70. SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);

  71. }

  72. }

  73. else

  74. {

  75. NumByteToWrite -= count;

  76. NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;

  77. NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;

  78.  
  79. SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);

  80. WriteAddr += count;

  81. pBuffer += count;

  82.  
  83. while (NumOfPage--)

  84. {

  85. SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);

  86. WriteAddr += SPI_FLASH_PageSize;

  87. pBuffer += SPI_FLASH_PageSize;

  88. }

  89.  
  90. if (NumOfSingle != 0)

  91. {

  92. SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);

  93. }

  94. }

  95. }

  96. }

 

6、从Flash读

 

 
  1. void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)

  2. {

  3. SPI_FLASH_CS_LOW();

  4. SPI_FLASH_SendByte(W25X_ReadData); // 03H

  5. SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);

  6. SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);

  7. SPI_FLASH_SendByte(ReadAddr & 0xFF);

  8. while (NumByteToRead--)

  9. {

  10. *pBuffer = SPI_FLASH_SendByte(Dummy_Byte);

  11. pBuffer++;

  12. }

  13. SPI_FLASH_CS_HIGH();

  14.  

http://chatgpt.dhexx.cn/article/8iJlMkSA.shtml

相关文章

SPI接口原理与配置

SPI 是英语Serial Peripheral interface的缩写&#xff0c;顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。 SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚上只占用四根线&#xff0…

SPI 接口配置

SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是Motorola公司提出的一种同步串行数据传输标准&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;在很多器件中被广泛应用。 SPI相关缩写 SS: Slave Select&…

D2--FPGA SPI接口通信2022-08-03

1.SPI简介 SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写&#xff0c;通常说SPI接口或SPI协议都是指SPI这一种串行外设接口规范。相对于串口&#xff0c;SPI是一种高速的&#xff08;可达10Mb\s以上&#xff09;&#xff0c;全双工&#xff0c…

[SPI]SPI接口简介

SPI接口简介 前言&#xff1a;串行外设接口(SPI)是微控制器和外围IC&#xff08;如传感器、ADC、DAC、移位寄存器、SRAM等&#xff09;之间使用较广泛的接口之一。本文先简要说明SPI接口&#xff0c;然后介绍ADI公司支持SPI的模拟开关与多路转换器&#xff0c;以及它们如何帮助…

计算机串口接spi,SPI串口模块-SPI接口详细介绍

SPI串口模块-SPI接口详细介绍 1. SPI串口模块-概述 SPI = Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。常规只占用四根线,节约了芯片管脚,PCB的布局省空间。现在越来越多的芯片集成了这种通信协议,常见的有EEPROM、FLASH、AD转换…

SPI接口介绍

SPI接口的全称是”Serial Peripheral Interface”&#xff0c;即串行外围接口。SPI接口主要应用在EEPROM、FLASH、实时时钟、AD转换器&#xff0c;还有数字信号处理器和数字信号解码器之间。SPI接口是在CPU和外围低速器件之间进行同步串行数据传输&#xff0c;在主器件的移位脉…

SPI接口协议的学习1

SPI接口是一种同步串行总线&#xff08;Serial Peripheral Interface&#xff09;。 四线SPI接口连线图&#xff1a; CS为片选脚&#xff0c;用于选中从机。 SCLK为时钟脚&#xff0c;用于数据传输时提供时钟信号。 MOSI为主output&#xff0c;从input&#xff0c;即主机发送…

SPI接口详细介绍

概述 SPI Serial Peripheral Interface&#xff0c;是串行外围设备接口&#xff0c;是一种高速&#xff0c;全双工&#xff0c;同步的通信总线。常规只占用四根线&#xff0c;节约了芯片管脚&#xff0c;PCB的布局省空间。现在越来越多的芯片集成了这种通信协议&#xff0c;常…

软件模拟SPI接口程序代码

目录 SPI协议简介 SPI接口介绍 SPI接口连接图 SPI数据传输方向 SPI传输模式 模拟SPI程序 SPI协议简介 SPI的通信原理很简单&#xff0c;一般主从方式工作&#xff0c;这种模式通常有一个主设备和一个或者多个从设备&#xff0c;通常采用的是4根线&#xff0c;它们是MISO&…

SPI接口及驱动

1. 简介 SPI接口是Motorola 首先提出的全双工三线同步串行外围接口&#xff0c;采用主从模式&#xff08;Master Slave&#xff09;架构。支持多slave模式应用&#xff0c;一般仅支持单Master。时钟由Master控制&#xff0c;在时钟移位脉冲下&#xff0c;数据按位传输&#xf…

SPI 接口

SPI 接口的全称是“Serial Peripheral Interface”意为串行外围接口&#xff0c;是 Motorola 首先在其 MC68HCxx 系列处理器上定义的。SPI 接口主要应用于 EEPROM、FLASH、实时时钟、AD转换器&#xff0c;还有数字信号处理器和数字信号解码器之间。 SPI 接口是在 CPU 和外围低…

ESP32 SPI 接口的应用

总体介绍 1. ESP32 共有 4 个 SPI 控制器 SPI0、SPI1、SPI2、SPI3&#xff0c;用于连接支持 SPI 协议的设备。 SPI0 控制器作为 cache 访问外部存储单元接口使用;SPI1 作为主机使用;SPI2 和 SPI3 控制器既可作为主机使用又可作为从机使用。作主机使用时&#xff0c;每个 SPI 控…

SPI接口简介-Piyu Dhaker

SPI接口简介 作者&#xff1a; Piyu Dhaker 串行外设接口(SPI)是微控制器和外围IC&#xff08;如传感器、ADC、DAC、移位寄存器、SRAM等&#xff09;之间使用最广泛的接口之一。本文先简要说明SPI接口&#xff0c;然后介绍ADI公司支持SPI的模拟开关与多路转换器&#xff0c;以…

弄懂SPI接口

SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是Motorola公司提出的一种同步串行数据传输标准&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;在很多器件中被广泛应用。 SPI相关缩写 SS: Slave Select&…

SPI接口

SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是Motorola公司提出的一种同步串行数据传输标准&#xff0c;在很多器件中被广泛应用。 1. 接口 SPI接口经常被称为4线串行总线&#xff0c;SPI协议是主从模式&#xff1a;从机不主动发起访问&…

SPI接口简介

串行外设接口(SPI)是微控制器和外围IC&#xff08;如传感器、ADC、DAC、移位寄存器、SRAM等&#xff09;之间使用最广泛的接口之一。本文先简要说明SPI接口&#xff0c;然后介绍ADI公司支持SPI的模拟开关与多路转换器&#xff0c;以及它们如何帮助减少系统电路板设计中的数字GP…

SPI接口详解

一、SPI接口简介 SPI 是英语Serial Peripheral interface的缩写&#xff0c;顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。 SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚上只占用…

【科普贴】SPI接口详解

一、SPI接口简介 SPI接口是一种同步串行总线&#xff08;Serial Peripheral Interface&#xff09;多用于Flash存储器&#xff08;如NOR Flash&Nand Flash&#xff09;&#xff0c;ADC、LCD控制器等外围器件的通讯接口。大大增强了处理器的外设扩展能力。 SPI接口缩写 SSE…

第四章 - 程序计数器

文章目录 1.PC 寄存器介绍2.PC 寄存器的作用3.代码示例4.两个常见面试题5.CPU时间片 官网文档 1.PC 寄存器介绍 JVM中的程序计数寄存器&#xff08;Program Counter Register&#xff09;&#xff0c;Register的命名源于CPU的寄存器&#xff0c;寄存器存储指令相关的现场信息。…

运行时数据区 - 程序计数器

① 介绍 JVM中的程序计数寄存器(Program Counter Register)中&#xff0c;Register的命名源于CPU的寄存器&#xff0c;寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。 PC寄存器用来存储指向下一条指令的地址(即将要执行的指令代码)&#xff0c;由执行…