SPI通信详解——STM32实验

一、简介

        SPI 协议是由摩托罗拉公司提出的通讯协议 (Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在 ADCLCD 等设备与 MCU 间,要求通讯速率较高的场合。

二、物理层

SPI 通讯设备之间的常用连接方式见下图   

SPI 通讯使用 3 条总线及片选线, 3 条总线分别为 SCK MOSI MISO ,片选线为,它们的作用介绍如下:

(1) ( Slave Select):从设备选择信号线,常称为片选信号线,也称为 NSSCS,以下用 NSS 表示。当有多个 SPI 从设备与 SPI 主机相连时,设备的其它信号线 SCKMOSI MISO 同时并联到相 同的 SPI 总线上,即无论有多少个从设备,都共同只使用这 3 条总线;而每个从设备都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号 线。I2C 协议中通过设备地址来寻址、选中总线上的某个设备并与其进行通讯;而 SPI 协议中没有设备地址,它使用 NSS 信号线来寻址,当主机要选择从设备时,把该从设备的 NSS 信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行 SPI 通讯。所以 SPI 通讯以 NSS 线置低电平为开始信号,以 NSS 线被拉高作为结束信号。

(2) SCK (Serial Clock) :时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率,不同的设备支持的最高时钟频率不一样,如 STM32 SPI 时钟频率最大为 f pclk /2 ,两个设备之间 通讯时,通讯速率受限于低速设备。
(3) MOSI (Master Output Slave Input) :主设备输出 / 从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
(4) MISO(Master Input, Slave Output) :主设备输入 / 从设备输出引脚。主机从这条信号线读入数据,从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。

三、协议层

I2C 的类似, SPI 协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节

IIC 通信详解icon-default.png?t=N7T8https://blog.csdn.net/2301_76655007/article/details/137338978?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171214204316800186566742%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=171214204316800186566742&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-137338978-null-null.142^v100^pc_search_result_base2&utm_term=IIC%E9%80%9A%E4%BF%A1%E8%AF%A6%E8%A7%A3%E2%80%94%E2%80%94STM32%20IIC%E5%AE%9E%E9%AA%8C%28%E9%87%8E%E7%81%AB%E6%8C%87%E5%8D%97%E8%80%85%29&spm=1018.2226.3001.4187

 

这是一个主机的通讯时序。 NSS SCK MOSI 信号都由主机控制产生,而 MISO 的信号由从机产生,主机通过该信号线读取从机的数据。 MOSI MISO 的信号只在 NSS 为低电平的时候才有效,在 SCK 的每个时钟周期 MOSI MISO 传输一位数据。

3.1 起始和停止信号

        在上图 中的①标号处, NSS 信号线由高变低,是 SPI 通讯的起始信号。 NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知道自己被主机选中了,开 始准备与主机通讯。在图中的⑥标号处, NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通 讯结束,从机的选中状态被取消。

3.2 数据有效性      

        SPI 使用 MOSI MISO 信号线来传输数据,使用 SCK 信号线进行数据同步。 MOSI MISO 据线在 SCK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时, MSB 先行或 LSB 先行并没有作硬性规定,但要保证两个 SPI 通讯设备之间使用同样的协定,一般都 会采用上图 中的 MSB 先行模式。
        观察图中的标号②③处,MOSI MISO 的数据在 SCK 的上升沿期间变化输出,在 SCK 的下降沿时 被采样。即在 SCK 的下降沿时刻, MOSI MISO 的数据有效,高电平时表示数据“ 1 ”,为低电 平时表示数据“ 0 ”。在其它时刻,数据无效, MOSI MISO 为下一次表示数据做准备。
        SPI 每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制。

3.3 CPOL/CPHA 及通讯模式

        上面讲述的图 SPI 通讯时序 中的时序只是 SPI 中的其中一种通讯模式, SPI 一共有四种通讯模式, 它们的主要区别是总线空闲时 SCK 的时钟状态以及数据采样时刻。为方便说明,在此引入“时 钟极性 CPOL ”和“时钟相位 CPHA ”的概念。
        时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时, SCK 信号线的电平信号 ( SPI 通讯开始前、 NSS 线为高电平时 SCK 的状态 ) CPOL=0 时, SCK 在空闲状态时为低电平, CPOL=1 时,则相 反。

        时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时,MOSI MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。见下图CPHA = 0 时的 SPI 通讯模式 及图 CPHA = 1 时的 SPI 通讯模式

        由 CPOL CPHA 的不同状态, SPI 分成了四种模式,见表 SPI 的四种模式 ,主机与从机需要工 作在相同的模式下才可以正常通讯,实际中采用较多的是“模式 0 ”与“模式 3 ”。

四、STM32的 SPI 架构

I2C 外设一样, STM32 芯片也集成了专门用于 SPI 协议通讯的外设。

4.1 spi 外设简介

        STM32 的 SPI 外设可用作通讯的主机及从机,支持最高的 SCK 时钟频率为 f pclk /2 (STM32F103 号的芯片默认 f pclk1 36MHz f pclk2 72MHz) ,完全支持 SPI 协议的 4 种模式,数据帧长度可设 置为 8 位或 16 位,可设置数据 MSB 先行或 LSB 先行。它还支持双线全双工 ( 前面小节说明的都 是这种模式 ) 、双线单向以及单线模式。其中双线单向模式可以同时使用 MOSI MISO 数据线 向一个方向传输数据,可以加快一倍的传输速度。而单线模式则可以减少硬件接线,当然这样速 率会受到影响。我们只讲解双线全双工模式。

4.2 spi 外设架构解析

                                                      SPI架构图

4.2.1 通信引脚

        SPI 的所有硬件架构都从图 SPI 架构图 中左侧 MOSIMISOSCK NSS 线展开的。STM32 片有多个 SPI 外设,它们的 SPI 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚。

        其中 SPI1 APB2 上的设备,最高通信速率达 36Mbtis/sSPI2SPI3 APB1 上的设备,最高通信速率为 18Mbits/s。除了通讯速率,在其它功能上没有差异。其中 SPI3 用到了下载接口的引脚,这几个引脚默认功能是下载,第二功能才是 IO 口,如果想使用 SPI3 接口,则程序上必须先禁用掉这几个 IO 口的下载功能。一般在资源不是十分紧张的情况下,这几个 IO 口是专门用于下载和调试程序,不会复用为 SPI3

4.2.2 时钟控制逻辑
SCK 线的时钟信号,由波特率发生器根据“控制寄存器 CR1 ”中的 BR[0:2] 位控制,该位是对 f pclk时钟的分频因子,对 f pclk 的分频结果就是 SCK 引脚的输出时钟频率,计算方法见表 BR 位对 fpclk 的分频
其中的 f pclk 频率是指 SPI 所在的 APB 总线频率, APB1 f pclk1 APB2 f pckl2
通过配置“控制寄存器 CR ”的“ CPOL 位”及“ CPHA ”位可以把 SPI 设置成前面分析的 4 SPI 模式
4.2.3 数据逻辑控制

        SPI MOSI MISO 都连接到数据移位寄存器上,数据移位寄存器的数据来源及目标接收、发送缓冲区以及 MISOMOSI 线。当向外发送数据的时候,数据移位寄存器以“发送缓冲区”为数据源,把数据一位一位地通过数据线发送出去;当从外部接收数据的时候,数据移位寄存器把数据线采样到的数据一位一位地存储到“接收缓冲区”中。通过写 SPI 的“数据寄存器 DR”把数据填充到发送缓冲区中,通讯读“数据寄存器 DR”,可以获取接收缓冲区中的内容。其中数据帧长度可以通过“控制寄存器 CR1”的“DFF 位”配置成 8 位及 16 位模式;配置“LSBFIRST 位” 可选择 MSB 先行还是 LSB 先行。

4.2.4 整体逻辑控制
        整体控制逻辑负责协调整个 SPI 外设,控制逻辑的工作模式根据我们配置的“控制寄存器 (CR1/CR2) ”的参数而改变,基本的控制参数包括前面提到的 SPI 模式、波特率、 LSB 先行、主 从模式、单双向模式等等。在外设工作时,控制逻辑会根据外设的工作状态修改“状态寄存器 (SR) ”,我们只要读取状态寄存器相关的寄存器位,就可以了解 SPI 的工作状态了。除此之外,控 制逻辑还根据要求,负责控制产生 SPI 中断信号、 DMA 请求及控制 NSS 信号线。
        实际应用中,我们一般不使用 STM32 SPI 外设的标准 NSS 信号线,而是更简单地使用普通的 GPIO ,软件控制它的电平输出,从而产生通讯起始和停止信号。

4.3通信过程

       STM32 使用 SPI 外设通讯时,在通讯的不同阶段它会对“状态寄存器 SR”的不同数据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。

 

主模式收发流程及事件说明如下:
(1) 控制 NSS 信号线,产生起始信号 ( 图中没有画出 )
(2) 把要发送的数据写入到“数据寄存器 DR ”中,该数据会被存储到发送缓冲区;
(3) 通讯开始, SCK 时钟开始运行。 MOSI 把发送缓冲区中的数据一位一位地传输出去; MISO 则把数据一位一位地存储进接收缓冲区中;
(4) 当发送完一帧数据的时候,“状态寄存器 SR ”中的“ TXE 标志位”会被置 1 ,表示传输完一帧,发送缓冲区已空;类似地,当接收完一帧数据的时候,“ RXNE 标志位”会被置 1 ,表示传输 完一帧,接收缓冲区非空;
(5) 等待到“ TXE 标志位”为 1 时,若还要继续发送数据,则再次往“数据寄存器 DR ”写入数据即可;等待到“ RXNE 标志位”为 1 时,通过读取“数据寄存器 DR ”可以获取接收缓冲区中的 内容。
        假如我们使能了 TXE RXNE 中断, TXE RXNE 1 时会产生 SPI 中断信号,进入同一个中 断服务函数,到 SPI 中断服务程序后,可通过检查寄存器位来了解是哪一个事件,再分别进行处 理。也可以使用 DMA 方式来收发“数据寄存器 DR ”中的数据。

五、STM32 SPI实验

以 STM32F103VET 野火指南者开发板 SPI—读写串行 FLASH 实验为例。

5.1 spi 初始化结构体

typedef struct
{
 uint16_t SPI_Direction; /* 设置 SPI 的单双向模式 */
 uint16_t SPI_Mode; /* 设置 SPI 的主/从机端模式 */
 uint16_t SPI_DataSize; /* 设置 SPI 的数据帧长度,可选 8/16 位 */
 uint16_t SPI_CPOL; /* 设置时钟极性 CPOL,可选高/低电平 */
 uint16_t SPI_CPHA; /* 设置时钟相位,可选奇/偶数边沿采样 */
 uint16_t SPI_NSS; /* 设置 NSS 引脚由 SPI 硬件控制还是软件控制*/
 uint16_t SPI_BaudRatePrescaler; /* 设置时钟分频因子,fpclk/分频数 =fSCK */
 uint16_t SPI_FirstBit; /* 设置 MSB/LSB 先行 */
 uint16_t SPI_CRCPolynomial; /* 设置 CRC 校验的表达式 */
} SPI_InitTypeDef;
(1) SPI_Direction
本成员设置 SPI 的通讯方向,可设置为双线全双工 (SPI_Direction_2Lines_FullDuplex) ,双线只接收 (SPI_Direction_2Lines_RxOnly) ,单线只接收 (SPI_Direction_1Line_Rx) 、单线只发送模式 (SPI_Direction_1Line_Tx)
(2) SPI_Mode
本成员设置 SPI 工作在主机模式 (SPI_Mode_Master) 或从机模式 (SPI_Mode_Slave ) ,这两个模式的最大区别为 SPI SCK 信号线的时序, SCK 的时序是由通讯中的主机产生的。若被配置为从 机模式, STM32 SPI 外设将接受外来的 SCK 信号。
(3) SPI_DataSize
本成员可以选择 SPI 通讯的数据帧大小是为 8 (SPI_DataSize_8b) 还是 16 (SPI_DataSize_16b)
(4) SPI_CPOL SPI_CPHA
这两个成员配置 SPI 的时钟极性 CPOL 和时钟相位 CPHA ,这两个配置影响到 SPI 的通讯模式,关于 CPOL CPHA 的说明参考前面“通讯模式”小节。 时钟极性 CPOL 成员,可设置为高电平 (SPI_CPOL_High) 或低电平 (SPI_CPOL_Low ) 时钟 相 位 CPHA 则 可 以 设 置 为 SPI_CPHA_1Edge( SCK 的 奇 数 边 沿 采 集 数 据 ) SPI_CPHA_2Edge( SCK 的偶数边沿采集数据 )
(5) SPI_NSS
本成员配置 NSS 引脚的使用模式,可以选择为硬件模式 (SPI_NSS_Hard ) 与软件模式(SPI_NSS_Soft ) ,在硬件模式中的 SPI 片选信号由 SPI 硬件自动产生,而软件模式则需要我们 亲自把相应的 GPIO 端口拉高或置低产生非片选和片选信号。实际中软件模式应用比较多。
(6) SPI_BaudRatePrescaler
本成员设置波特率分频因子,分频后的时钟即为 SPI SCK 信号线的时钟频率。这个成员参数可设置为 fpclk 2 4 6 8 16 32 64 128 256 分频。
(7) SPI_FirstBit
所有串行的通讯协议都会有 MSB 先行 ( 高位数据在前 ) 还是 LSB 先行 ( 低位数据在前 ) 的问题,而STM32 SPI 模块可以通过这个结构体成员,对这个特性编程控制。
(8) SPI_CRCPolynomial
这是 SPI CRC 校验中的多项式,若我们使用 CRC 校验时,就使用这个成员的参数 ( 多项式 ) ,来计算 CRC 的值。

5.2编程要点

(1) 初始化通讯使用的目标引脚及端口时钟;
(2) 使能 SPI 外设的时钟;
(3) 配置 SPI 外设的模式、地址、速率等参数并使能 SPI 外设;
(4) 编写基本 SPI 按字节收发的函数;
(5) 编写对 FLASH 擦除及读写操作的的函数;
(6) 编写测试程序,对读写数据进行校验。

5.3核心代码

/**
  * @brief  SPI_FLASH初始化
  * @param  无
  * @retval 无
  */
void SPI_FLASH_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 使能SPI时钟 */
	FLASH_SPI_APBxClock_FUN ( FLASH_SPI_CLK, ENABLE );
	
	/* 使能SPI引脚相关的时钟 */
 	FLASH_SPI_CS_APBxClock_FUN ( FLASH_SPI_CS_CLK|FLASH_SPI_SCK_CLK|
																	FLASH_SPI_MISO_PIN|FLASH_SPI_MOSI_PIN, ENABLE );
	
  /* 配置SPI的 CS引脚,普通IO即可 */
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);
	
  /* 配置SPI的 SCK引脚*/
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);

  /* 配置SPI的 MISO引脚*/
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
  GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStructure);

  /* 配置SPI的 MOSI引脚*/
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
  GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);

  /* 停止信号 FLASH: CS引脚高电平*/
  SPI_FLASH_CS_HIGH();

  /* SPI 模式配置 */
  // FLASH芯片 支持SPI模式0及模式3,据此设置CPOL CPHA
  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_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(FLASH_SPIx , &SPI_InitStructure);

  /* 使能 SPI  */
  SPI_Cmd(FLASH_SPIx , ENABLE);
	
}

/**
  * @brief  使用SPI发送一个字节的数据
  * @param  byte:要发送的数据
  * @retval 返回接收到的数据
  */
u8 SPI_FLASH_SendByte(u8 byte)
{
	 SPITimeout = SPIT_FLAG_TIMEOUT;
  /* 等待发送缓冲区为空,TXE事件 */
  while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_TXE) == RESET)
	{
    if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);
   }

  /* 写入数据寄存器,把要写入的数据写入发送缓冲区 */
  SPI_I2S_SendData(FLASH_SPIx , byte);

	SPITimeout = SPIT_FLAG_TIMEOUT;
  /* 等待接收缓冲区非空,RXNE事件 */
  while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_RXNE) == RESET)
  {
    if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(1);
   }

  /* 读取数据寄存器,获取接收缓冲区数据 */
  return SPI_I2S_ReceiveData(FLASH_SPIx );
}

/**
  * @brief  使用SPI读取一个字节的数据
  * @param  无
  * @retval 返回接收到的数据
  */
u8 SPI_FLASH_ReadByte(void)
{
  return (SPI_FLASH_SendByte(Dummy_Byte));
}
  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: stm32与fpga连接原理图一般分为三个部分:stm32芯片、fpga芯片与连接器。其中,stm32芯片和fpga芯片之间的连接可以通过VHDL硬件描述语言进行实现,具体可以采用SPI、I2C、UART等通信方式实现连接。 在通信方式中,SPI(Serial Peripheral Interface)是一种基于同步时序的通信方式,该方式可以实现stm32与fpga间的数据传输。SPI通信方式需要4根线,包括SCK(时钟信号)、MOSI(主机数据输出,被动设备数据输入)、MISO(主机数据输入,被动设备数据输出)和SS(片选信号)。 另外,I2C(Inter-Integrated Circuit)是一种基于两根线(SDA和SCL)的串行通信方式,该方式可以实现stm32与fpga间的数据传输。在I2C通信方式中,SDA是数据线,SCL是时钟线。而UART(Universal Asynchronous Receiver-Transmitter)是一种异步串行通信方式,该方式可以实现stm32与fpga间的数据传输。 无论采用何种通信方式,连接器就成为了连接stm32和fpga的关键部分。连接器有多种,例如针脚连接器、Flex连接器、板对板连接器等。选择合适的连接器可以确保stm32与fpga之间的通信稳定性,保证连接的可靠性和持久性。 总之,stm32与fpga连接原理图的设计需要根据具体的应用场景进行选择,采用合适的通信方式和连接器,确保连接的稳定性和可靠性。 ### 回答2: STM32和FPGA是现代电子设计中非常重要的组件,它们可以单独使用,也可以连接在一起以实现更强大的功能。STM32是一款单片微控制器,其通常与各种硬件设备连接在一起以实现各种功能。而FPGA是现场可编程门阵列,其具有高度可定制性和灵活性,可以支持多种不同的应用场景。 连接STM32和FPGA时,需要按照一定的原理图进行连接。下面是连接STM32和FPGA的一般性原理图: 首先,作为一个微控制器,STM32需要与各种外设连接在一起,包括FPGA。在原理图中,STM32连接到FPGA的GPIO引脚,这些引脚具有特定的功能。GPIO引脚是通用输入输出引脚,可以被编程成输入或输出,用于连接STM32与其他设备、模块或器件。 其次,在原理图中,还需要一些额外的电路来保护STM32和FPGA。例如,为了保护STM32的输入输出引脚,可以添加保护二极管和电阻。这些电路可以避免过电压和电流对电路造成损害。 最后,还需要在原理图中添加时钟和复位电路,以确保STM32和FPGA的正确工作。时钟电路可以提供正确的时钟频率,以使STM32和FPGA按照正确的速度运行。复位电路可以确保在开机时正确初始化STM32和FPGA。 综上所述,连接STM32和FPGA需要按照一定的原理图进行连接,其中包含GPIO引脚、保护电路、时钟电路和复位电路等组件。这些电路可以确保STM32和FPGA的正常运行,并实现各种强大的功能。 ### 回答3: STM32(意法半导体公司生产的一种微控制器)和FPGA(现场可编程门阵列)之间的连接通常使用标准的接口协议,例如SPI(串行外设接口)、I2C(串行总线接口)或UART(通用异步收发传输器)等。 这些接口中,SPI接口是最常用的,因为它提供了快速的通信速度和可靠性,同时还能够通过主从模式实现多个设备的连接。使用SPI接口连接STM32和FPGA时,需要在STM32上配置SPI主模式,并在FPGA上实现SPI从模式。然后,在这两个设备之间连接一根包含SPI信号线的线缆,如MOSI(主输入/从输出)、MISO(主输出/从输入)、CLK(时钟线)等。 此外,还可以使用I2C接口连接STM32和FPGA。在这种情况下,STM32的配置将作为I2C主控,并将向FPGA发送一些配置命令,以控制FPGA的操作。 I2C接口需要两个引脚,即SDA(串行数据线)和SCL(串行时钟线)。 在UART接口中,使用单个引脚进行数据传输。STM32将配置为UART主控,并将通过单个引脚将数据传输到FPGA中。 在STM32和FPGA之间选择合适的接口协议需要考虑多种因素。例如通信速率、通信距离、通信复杂性等,因此需要根据具体的应用场景来选择合适的协议和连接方式。 总的来说,连接STM32和FPGA的原理图是基于所选接口的,每种接口都有其特定的引脚配置和通信协议,因此需要精心设计和配置,以确保连接的可靠性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值