MSP432的串行通信

专栏

基于MSP432的嵌入式系统实践

数字通信基本知识

组成

  • 发送器:处理要发送的信息,将其构造成一定格式的帧。

  • 接收器:接收信息并解析信息。

  • 通信介质:发送器和接收器之间的桥梁,为信息提供物理介质,通常为双绞线、光纤或无线射频。

串行通信和并行通信

  • 串行通信:将数据一位一位地由端口送出或接收进来
  • 并行通信:数据的各个数据位(一般为8位及其整数倍)在多条数据线上同时被传输
  • 并行通信的传输速度快、效率高,但抗干扰能力差,且需要的资源多,一般用于短距离、高带宽的大数据量传输
  • 串行通信节省传输线,但数据传送效率没有并行通信高

同步通信和异步通信

  • 异步通信:处理器之间不使用公共的参考时钟,通信双方分别有自己的时钟源,但必须使用相同的波特率。例如UART就是属于串行异步通信。
  • 同步通信:由主机提供时钟与数据,从机使用该时钟接收数据或发送数据,即通信双方公用时钟源。例如:SPI和I2C就属于串行同步通信。

异步串行通信的通用基础知识

定义

串行通信接口,即异步串行通信,简称UART,也就是我们常说的“串口”或SCI,在USB未普及之前,就是PC机必备的通信接口之一

特殊地位

串行通信具有特殊重要地位的原因

  • 原因一:在通信方式上,属于单字节通信,是嵌入式开发中重要的调试手段之一
  • 原因二:它是最简单的串行通信方式,硬件上所说的232、485通信均是指这个串口通信
  • 原因三:硬件接线简单,与MCU引脚直接相连的一般只需要发送线、接收线和地线

异步串行通信的格式

串行通信数据以字节为单位,按位的顺序从发送线送出。从MCU引脚来看,高电平就是逻辑“1”,低电平就是逻辑“0”

异步串行通信的格式

串行通信格式

  • 串行通信的发送线,平时处于逻辑“1”状态
  • 开始发送一个字节前,先发送一位逻辑“0”,即起始位,表示发送一个字节的开始
  • 随后发送一个字节,然后回到平时状态的逻辑“1”
  • 每发送一个字节前,均要先发送一个逻辑”0“,这个起始位这就是”异步“之含义,所以称为异步通信
  • LSB模式 最低有效位模式
  • MSB模式 最高有效位模式
  • UART默认LSB模式

串行通信的波特率

波特率定义

人们把每秒内传送的位数叫做波特率

单位是:位/秒,记为bps

常用的波特率有9600、19200等

波特率基本概念

在包含开始位与停止位的情况下,发送一个字节需要10位,很容易计算出,在特定波特率下,发送1K字节所需要的时间。波特率越高,位长越小,易受电磁干扰,所以串行通信速度不能很高。距离短时可以适当提高波特率,但提高幅度有限

奇偶校验

目的

在异步串行通信中,如何知道一个字节的传输是否正确?最常见的方法是增加一个位(奇偶校验位),供错误检测使用

定义

​ 字符奇偶校验检测(Character Parity Checking,CPC)称为垂直冗余检测(Vertical Redundancy,VRC),它是为每个字符增加一个额外位使字符中“1”的个数为奇数或偶数

​ 奇数或偶数依据使用的是“奇校验检查”还是“偶校验检查”而定。当使用”奇校验检查“时,如果字符数据位中“1”的数目是偶数,校验位应为“1”,如果“1”的数目是奇数,校验位应为“0”。当使用”偶校验检查“时,如果字符数据位中“1”的数目是偶数,校验位应为“0”,如果是奇数则为“1”

实例

ASCII字符”R“,其位构成是1010010

由于字符“R”中有3个位为“1”,若使用奇校验检查,则校验位为0;如果使用偶校验检查,则校验位为1

注:几乎所有的MCU的串行异步通信接口,都提供这种功能。但实际编程使用较少,原因是单字节校验意义不大

串行通信传输方式术语

1.全双工(Full-duplex)

​ 数据传送是双向的,且可以同时接收与发送数据。这种传输方式中,除了地线之外,需要两根数据线,站在任何一端的角度看,一根为发送线,另一根为接收线。一般情况下,MCU的异步串行通信接口均是全双工的。

2.半双工(Half-duplex)

​ 数据传送也是双向的,但是在这种传输方式中,除地线之外,一般只有一根数据线。任何时刻,只能由一方发送数据,另一方接收数据,不能同时收发。

3.单工(Simplex)

​ 数据传送是单向的,一端为发送端,另一端为接收端。这种传输方式中,除了地线之外,只要一根数据线就可以了。有线广播就是单工的。

为使数据传输得更远,美国电子工业协会制定了串行物理接口标准RS232

异步创新通信格式:实际的异步串行通信采用的是NRZ数据格式,即“标准不归零传号/空号数据格式”。“不归零”是:用负电平表示一种二进制值,正电平表示另一种二进制值,不使用零电平。“传号/空号”分别是表示两种状态的物理名称,逻辑名称记为“1/0”。

RS232总线标准

  • RS232采用负逻辑
  • -15V ~ -3V为逻辑 “ 1 ”
  • +3V ~ +15V为逻辑 “ 0 ”
  • 最大的传输距离是30m
  • 通信速率一般低于20Kbps

9芯串行接口排列

注:RS232一般使用9芯串行接口
RS232串口接线图

引脚号功能引脚号功能
1接收线信号检测6数据通信设备准备就绪(DSR)
2接收数据线(RXD)7请求发送(RTS)
3发送数据线(TXD)8允许发送(CTS)
4数据终端准备就绪(DTR)9振铃指示
5信号地(SG)

注:在RS232通信中,常常只用三根线:接收线、发送线和地线

串口通信接口电平转换电路

​ 随着USB接口的普及,9芯接口正在逐渐从PC机,特别是从便携式电脑上消失。于是出现232-USB转换线、TTL-USB转换线,在PC机上安装相应的驱动软件,就可在PC机上使用一般的串行通信编程方式,通过USB接口实现与MCU的串行通信。
串行通信接口主要功能
UART编程模型

编程时,程序员并不直接与“发送移位寄存器”和“接收移位寄存器”打交道,只与数据寄存器打交道。

若可以发送,则将待发送的数据放入“数据寄存器”中就可以了,剩下的工作由MCU自动完成。

MCU会将数据从“数据寄存器”送到“发送移位寄存器”,硬件将“发送移位寄存器”的数据一位一位地按照规定的波特率移到发送引脚,供对方接收。

接受时,数据一位一位地从接收引脚进入“接收移位寄存器”,当收到一个完整字节时,MCU会自动将数据送入“数据寄存器”,并将状态寄存器的相应位改变,供程序员判定并取出数据。

UART编程相关

UART编程相关

eUSCI模式下的UART

Enhanced Universal Serial Communication Interface

增强的通用串行通信接口(eUSCI)模块支持多种串行通信模式。不同的eUSCI模块支持不同的模式。每一个不同的eUSCI模块以不同的字母命名,例如:eUSCI_A、eUSCI_B等。MSP432单片机实现了不止一个相同的eUSCI模块,这些模块将以递增的数字命名,例如,MSP432单片机支持四个eUSCI_A模块时,这四个模块应该被命名为eUSCI_A0、eUSCI_A1、eUSCI_A2、eUSCI_A3。

eUSCI_A模块支持以下通信模式:

  1. UART通信模式;
  2. 具有脉冲整型的IrDA通信模式;
  3. 具有自动波特率检测的LIN通信模式;
  4. SPI通信模式。

USCI_B模块支持以下通信模式:

  1. IIC通信模式;
  2. SPI通信模式。

下面首先介绍eUSCI的异步模式——URAT。

UART

Universal Asynchronous Receiver and Transmitter

异步通信收发器

UART的特点及结构

UART即异步串行通信,可设置成全双工异步通讯方式,与PC(个人计算机)等通讯;或设置成半双工同步模式与其他外设通信,如ADC或DAC。

MSP432单片机内置了UART功能,它的作用是将外部设备串行数据转换为并行数据接收;讲内部并行数据转换为串行数据发送。在通用异步收发模式下eUSCI_Ax模块通过两个外部收发引脚UCAxRXD和UCAxTXD把MSP432单片机与外界连接起来。当寄存器UCAxCLT0的UCSYNC控制位被清零,UCMODEx控制位被配置为00时,eUSCI_A模块被配置为UART异步通信模式。

UART的特点如下

  1. 传输7位或8位数据,可采用奇校验、偶校验或者无校验;
  2. 具有独立的发送和接收移位寄存器;
  3. 具有独立的发送和接收缓存寄存器;
  4. 支持最低位优先或最高位优先的数据发送和接收方式;
  5. 内置多处理器系统,包括线路空闲和地址位通信协议;
  6. 通过有效的起始位检测,将MSP432单片机从低功耗模式下唤醒;
  7. 可编程实现分频因子为整数或小数;
  8. 具有用于检测错误或排除错误的状态标志位;

UART运行机理

UART结构图
图①串行数据接收逻辑
图②波特率发生器
图③串行数据发送逻辑

在UART模式下,其结构如图。由图可知,在UART模式下,eUSCI_A模块由串行数据接收逻辑(图①)、波特率发生器(图②)和串行数据发送逻辑(图③)三个部分组成。串行数据接收逻辑用于接收串行数据,包括接收移位寄存器、接收缓存寄存器和接收状态寄存器以及接收标志位设置逻辑。波特率发生器用于产生接收和发送的时钟信号,其参考时钟可以来源于ACLK或SMCLK,也可以来自于外部时钟输入UCLK,通过整数或小数分频得到特定的数据传输波特率。传输数据发送逻辑用于发送串行数据,包括发送移位寄存器、发送缓存寄存器和发送状态寄存器以及发送标志位设置逻辑。在UART模式下,eUSCI_A异步的以一定速率向另一个设备发送和接收字符,每个字符的传输时钟是基于软件对波特率的设定,发送和接收要使用相同的波特率。

应用

串口是嵌入式系统与外界联系的重要手段,主要用于以下两个方面:

  • UART直接和其他的控制器进行数据交换
  • UART和PC机通信:由于PC机串口是RS232电平,所以连接时需要使用RS232转换器

使用UART通信

使用UART通信需要两个引脚(将在下面的示例中用到),如下表:

引脚名称类型描述
RXD输入串行输入,接收数据
TXD输出串行输出,发送数据

串行发送机TxMachine

TxMachine支持下面的工作特性:

  1. 奇偶校验位的生成
  2. 清除发送
  3. 中断字符发送
  4. 双缓存区操作

串行接收机RxMachine

RxMachine把接收到的串行数据送到接收移位寄存器,接收完成后,数据送到串行接收缓存寄存器(SxRBUF),用户从SxRBUF中读取接收到的数据。

串行接收机在接收过程中能够检测出以下三种错误条件:

  1. 奇偶校验错:检测到奇偶校验错时,奇偶错标志位被置位。
  2. 帧错误:未收到停止位时,帧错误标志位被置位。
  3. 超越错误:当接收到一个新的字符前,以前收到的字符没有被CPU读走,旧的数据被覆盖,那么超越错误标志位被置位。

波特率的计算

一般填入波特率寄存器中的值都是通过如下的公式求出来:

UART_BR = MCLK / (BaudRate * N)

注意:N为波特率因子,大多数芯片取N = 16

有些波特率计算精度较高,它们有两个波特率寄存器UART_BR1和UART_BR2,其中UART_BR1则用来存放上式计算出来的整数部分,而UART_BR2则用来存放上式计算出来的小数部分,这样计算出来的波特率就更精确,误差更小。

如果假设时钟源选择12MHz,如果要取UART2的9600波特率,那么如何计算

  1. N = 12000000/9600 = 1250
  2. 1 -> OS16 UCBR2 = INT(1250/16) = 78
  3. UCBRF2 = INT(N/ 6 - INT(N/16)) * 16 = INT(0.125 * 16) = 2
  4. N = N - INT(N)

其中根据第一步,N=1250,INT(N)=0,因此N-INT(N)=0,查表TABLE24-4,可以得到UCBRSx的值应该为0.

注意,如果N-INT(N)不等于0,那么按照官方文档要求,在TABLE24-4中按照往前靠的原则进行查表,例如小数部分为0.125,那么查表对应数据为0.100对应的数值。

UART相关寄存器

1寄存器地址分析

  • MSP432芯片有四个UART模块。每个模块有其对应的寄存器。以下地址分析均为16进制,为书写简化起见,在不至于引起歧义的情况下,略去十六进制后缀“0x”不写。
  • UART模块x的寄存器地址=4000_1000+x * 400+n * 2(x = 0~3;n = 0~15(除2、10、11、12), n代表寄存器号)。

2控制寄存器

  • eUSCI_Ax控制字寄存器0(UCAxCTLW0)
  • eUSCI_Ax控制字寄存器1(UCAxCTLW1)
  • eUSCI_Ax中断使能寄存器(UCAxIE)
  • eUSCI_Ax调制控制字寄存器(UCAxMCTLW)

3状态寄存器

  • eUSCI_Ax状态寄存器(UCAxSTATW)
  • eUSCI_Ax中断标志寄存器(UCAxIFG)
  • eUSCI_Ax中断向量寄存器(UCAxIV)

4波特率寄存器

  • eUSCI_Ax波特率控制字寄存器(UCAxBRW)
  • eUSCI_Ax自动波特率控制寄存器(UCAxABCTL)

5数据寄存器

  • eUSCI_Ax接收缓存区寄存器(UCAxRXBUF)
  • eUSCI_Ax发送缓存区寄存器(UCAxTXBUF)

常用波特率列表

  • 300
  • 600
  • 1200
  • 2400
  • 4800
  • 9600
  • 19200
  • 38400
  • 43000
  • 56000
  • 57600
  • 115200

MSP432中的UART

MSP432中的UART

当MSP432要发送数据时,发送缓冲器中要发送的值装入发送移位寄存器中,再一位一位地从发送端口UCAxTXD发送出去。

当MSP432要接收数据时,数据从UCAxRXD一位一位地送入接收移位寄存器,然后装入接收缓存寄存器中。接收端在接收数据时可以实现错误检测、解码、帧听等功能。

初始化配置

  • 时钟配置——时钟源、时钟频率等
  • GPIO配置——TXD、RXD
  • UART配置——数据帧格式、波特率等
  • 中断配置

UART相关的SDK函数

void UART_clearInterruptFlag ( uint32_t moduleInstance,uint_fast8_t mask )
Clears UART interrupt sources.
    
void UART_disableInterrupt ( uint32_t modulelnstance,uint_fast8_t mask )
Disables individual UART interrupt sources.
    
void UART_disableModule ( uint32_t modulelnstance )
Disables the UART block.
    
void UART_enableInterrupt ( uint32_t modulelnstance,uint_fast8_t mask )
Enables individual UART interrupt sources.
    
void UART_enableModule ( uint32_t modulelnstance )
Enables the UART block.
    
uint_fast8_t UART_getEnabledInterruptStatus ( uint32_t modulelnstance )
Gets the current UART interrupt status masked with the enabled interrupts. This function is usefulto call in lSRs to get a list of pending interrupts that are actually enabled and could have causedthe lSR.
    
uint_fast8_t UART_getInterruptStatus ( uint32_t modulelnstance,uint8_t mask )
Gets the current UART interrupt status.

bool UART_initModule ( uint32_t modulelnstance,consteusCI_UART_ConfigV1 * config )
Initialization routine for the UART block.The values to be written into the UCAxBRW and UCAxMCTLW registers should be pre-computed and passed into the initialization function.

UART操作实例

程序功能:MSP432通过UART与PC通信。

描述:MSP432将通过串口收到的字符发回给PC,并在串口调试工具中显示出来。UART帧格式被配置为一个起始位,一个停止位,无校验位。使用的波特率为9600Baud。若使用UART0,P1.2与P1.3分别为接收端口与发送端口;若使用UART3,P9.6与P9.7分别为接收端口与发送端口。查看对应针脚可参阅官方手册表4-1。下面是MSP432通过UART0和UART3与PC通信:

UART0:UCA0RXD(P1.2),UCA0TXD(P1.3)
因为MSP432P401R串口0被跳帽接到仿真器上了,将跳帽取下来用杜邦线接到通信设备即可。

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
//配置结构体
const eUSCI_UART_Config uartConfig =
{
    EUSCI_A_UART_CLOCKSOURCE_SMCLK,//时钟源
    78,//BRDIV = 78
    2,//UCxBRF = 2
    0,//UCxBRS = 0
    EUSCI_A_UART_NO_PARITY,//无校验
    EUSCI_A_UART_LSB_FIRST,//低位先行
    EUSCI_A_UART_ONE_STOP_BIT,//一个停止位
    EUSCI_A_UART_MODE,//UART模式
    EUSCI_A_UART_OVERSAMPLINE_BAUDRATE_GENERATION
};

//主函数
int main(void)
{
    MAP_WDT_A_holdTimer();
    //GPIO配置
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN2|GPIO_PIN3,GPIO_PRIMARY_MODULE_FUNCTION);
    //配置DCO频率
    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
    //配置UART
    MAP_UART_initModule(EUSCI_A0_BASE,&uartConfig);
    MAP_UART_enableModule(EUSCI_A0_BASE);
    //使能中断
    MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    MAP_Interrupt_enableSleepOnIsrExit();
    MAP_Interrupt_enableMaster();
    //打印数据
    printf("Hello MSP432!\r\n");
    UART_transmitData(EUSCI_A0_BASE,'A');
    UART_transmitData(EUSCI_A0_BASE,'B');
    while(1)
    {
        MAP_PCM_gotoLPM0();//低功耗模式0,串口中断唤醒
    }
}

//中断服务子程序
void EUSCIA0_IRQHandler(void)
{
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);

    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
    {
        uint32_t val;
        val = UART_receiveData(EUSCI_A0_BASE);//变量val就是接收到的数据的值
        UART_transmitData(EUSCI_A0_BASE,val);//将接收到的数据发送回去
    }
}

//标准输入输出函数对接
int fputc(int ch,FILE *f)
{
    UART_transmitData(EUSCI_A0_BASE,ch & 0xFF);
    return ch;
}

int fgetc(FILE *f)
{
    while(EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG != UART_getInterruptStatus(EUSCI_A0_BASE,EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG));
    return UART_receiveData(EUSCI_A0_BASE);
}

UART3:UCA3RXD(P9.6),UCA3TXD(P9.7)

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
//配置结构体
const eUSCI_UART_Config uartConfig =
{
    EUSCI_A_UART_CLOCKSOURCE_SMCLK,//时钟源
    78,//BRDIV = 78
    2,//UCxBRF = 2
    0,//UCxBRS = 0
    EUSCI_A_UART_NO_PARITY,//无校验
    EUSCI_A_UART_LSB_FIRST,//低位先行
    EUSCI_A_UART_ONE_STOP_BIT,//一个停止位
    EUSCI_A_UART_MODE,//UART模式
    EUSCI_A_UART_OVERSAMPLINE_BAUDRATE_GENERATION
};

//主函数
int main(void)
{
    MAP_WDT_A_holdTimer();
    //GPIO配置
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P9,GPIO_PIN6|GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);
    //配置DCO频率
    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
    //配置UART
    MAP_UART_initModule(EUSCI_A3_BASE,&uartConfig);
    MAP_UART_enableModule(EUSCI_A3_BASE);
    //使能中断
    MAP_UART_enableInterrupt(EUSCI_A3_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    MAP_Interrupt_enableInterrupt(INT_EUSCIA3);
    MAP_Interrupt_enableSleepOnIsrExit();
    MAP_Interrupt_enableMaster();
    //打印数据
    printf("Hello MSP432!\r\n");
    UART_transmitData(EUSCI_A3_BASE,'A');
    UART_transmitData(EUSCI_A3_BASE,'B');
    while(1)
    {
        MAP_PCM_gotoLPM0();//低功耗模式0,串口中断唤醒
    }
}

//中断服务子程序
void EUSCIA3_IRQHandler(void)
{
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A3_BASE);

    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
    {
        uint32_t val;
        val = UART_receiveData(EUSCI_A3_BASE);//变量val就是接收到的数据的值
        UART_transmitData(EUSCI_A3_BASE,val);//将接收到的数据发送回去
    }
}

//标准输入输出函数对接
int fputc(int ch,FILE *f)
{
    UART_transmitData(EUSCI_A3_BASE,ch & 0xFF);
    return ch;
}

int fgetc(FILE *f)
{
    while(EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG != UART_getInterruptStatus(EUSCI_A3_BASE,EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG));
    return UART_receiveData(EUSCI_A3_BASE);
}

资料

MSP432P401R官方手册

  • 25
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
你可以使用串口通信来实现OpenMV和MSP432之间的数据传输。首先,确保OpenMV和MSP432都连接到相同的串口引脚上(例如,TX连接到RX,RX连接到TX)。然后,你需要在OpenMV和MSP432上分别编写相应的代码来实现串口通信。 在OpenMV的代码中,你可以使用`uart`模块来进行串口通信。以下是一个简单的示例代码,展示了如何从OpenMV向MSP432发送数据: ```python import time from pyb import UART uart = UART(3, 9600) # 选择合适的串口号和波特率 while True: uart.write("Hello from OpenMV!") # 向串口发送数据 time.sleep(1000) # 等待1秒钟 ``` 在MSP432的代码中,你需要使用相应的串口库来实现串口通信。以下是一个简单的示例代码,展示了如何从MSP432接收来自OpenMV的数据: ```c #include <msp432.h> void UART_Init() { // 初始化串口配置 EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST; EUSCI_A0->CTLW0 = EUSCI_A_CTLW0_SWRST | EUSCI_A_CTLW0_SSEL__SMCLK; EUSCI_A0->BRW = 26; EUSCI_A0->MCTLW = (2 << EUSCI_A_MCTLW_BRS_OFS) | EUSCI_A_MCTLW_OS16; EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; EUSCI_A0->IE |= EUSCI_A_IE_RXIE; } void UART_SendString(const char* str) { while (*str) { while (!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); EUSCI_A0->TXBUF = *str++; } } void UART_ReceiveHandler(char c) { // 处理接收到的字符 // ... } int main(void) { // 初始化MSP432 // ... UART_Init(); while (1) { // 主循环 // ... } } void EUSCIA0_IRQHandler() { if (EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG) { UART_ReceiveHandler(EUSCI_A0->RXBUF); } } ``` 这只是一个简单的示例,你可以根据实际需求进行相应的修改和扩展。确保OpenMV和MSP432串口参数(如波特率)相匹配,并根据实际情况进行调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FantasyQin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值