CH582、CH592、CH584硬件IIC驱动 OLED显示屏

一、IIC简要介绍

IIC(Inter-Integrated Circuit)是一种由飞利浦公司开发的串行通信协议,主要用于微控制器与外设之间的低速、短距离数据传输‌。其核心特性如下:

1. ‌物理结构

  • 仅需两根双向信号线:
    • SDA(串行数据线)‌:传输数据
    • SCL(串行时钟线)‌:同步通信时序‌
  • 采用开漏输出设计,依赖上拉电阻维持高电平,支持多设备连接‌。

2. ‌通信模式

  • 半双工‌:同一时间仅支持单向传输(主机→从机或从机→主机),通过动态切换方向实现双向通信‌。
  • 全双工协议对比‌:SPI等协议需独立发送/接收线路,而IIC通过硬件简化节省资源‌。

3. ‌典型应用场景

  • 适用于传感器、EEPROM等低速外设,尤其适合硬件资源受限的嵌入式系统‌。
  • 通过主机控制SCL和地址帧中的读写位来管理通信流程‌。

4. ‌通信流程示例

  1. 起始条件‌:SCL高电平时,SDA由高→低跳变‌。
  2. 地址传输‌:7位设备地址+1位读写位,从机响应ACK‌。
  3. 数据交换‌:按字节传输,每字节后跟随ACK确认‌。
  4. 停止条件‌:SCL高电平时,SDA由低→高跳变‌。

5. ‌优势与局限

  • 优势‌:硬件简单、成本低,支持多主多从拓扑‌。
  • 局限‌:速率较低(标准模式100kbps),依赖上拉电阻且易受干扰‌。

二、连接多个IIC设备

一)、硬件连接方式

  1. 总线拓扑设计

    • 将所有设备的‌SDA‌和‌SCL‌引脚分别并联连接,确保信号线物理上共享‌。
    • 在总线的‌SDA‌和‌SCL‌线上各添加一个‌4.7kΩ~10kΩ‌的上拉电阻,连接到电源正极(VCC),确保空闲时为高电平‌。
  2. 地址冲突处理

    • 每个IIC设备需配置‌唯一地址‌(7位或10位),通过跳线或寄存器设置‌。
    • 部分设备(如PCF8574)支持通过硬件跳帽修改地址,避免冲突‌。

      注:不同的IIC设备地址及设置方式不同,请参考相关设备的文档。

二)、通信流程关键点

  1. 主机控制时序

    • 主机发送‌起始条件‌(SCL高时SDA下降沿),后接‌从机地址+读写位‌,从机通过ACK确认响应‌。
    • 数据按字节传输,每字节后需从机返回ACK/NACK信号‌

三、CH592等MCU硬件IIC接口配置要点

需将SCL/SDA引脚配置为上拉输入方式。

    GPIOB_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13, GPIO_ModeIN_PU);

这里有点比较奇怪的地方,如果使用软件模拟IIC来驱动的话,需要将这两引脚配置为推挽输出模式。

时钟初始化
典型配置参数:400kHz通信速率,16:9占空比,7位地址模式。关键代码如下:

    I2C_Init(I2C_Mode_I2C, 400000, I2C_DutyCycle_16_9, I2C_Ack_Enable, I2C_AckAddr_7bit, MASTER_ADDR);

四、4Pin IIC 驱动OLED屏介绍

这里以中景园的驱动芯片为SSD1315的OLED显示屏为例说明。

从上图中,我们很容易看出,该OLED屏的IIC地址为0x78。

该公司好象也有驱动芯片为SSD1306的OLED显示屏,两种屏的IIC地址不同,SSD1306的IIC地址是0x3C。

为从图中,我们可以看出数据格式为:

S ->SSD1315 地址->ACK->Control byte ->ACK->Data byte ->Control byte ->ACK->Data byte-> P

S:起始位

P:  停止位

Control byte: 最高位通常为0。Bit6:数据/命令选择,1表示接下来发送的是数据,0表示发送的是命令。

五、CH592 MCU 的IIC接口使用指南

对比OLED屏的介绍,我们很容易理解接下来的驱动代码。

六、实例代码


#ifdef OLED_USE_IIC
void OLED_Write_nByte(u8 * buff,u8 len,u8 cmd)
{
    uint8_t mode;

    cmd == OLED_CMD ? (mode = 0x00) : (mode = 0x40);
    IIC_Send_n_Byte(OLED_IIC_ADDR,mode,buff,len);
}

/*******************************************************************
 * @function   :Write a byte of content to the OLED screen
 * @parameters :dat:Content to be written
                cmd:0-write command
                                    1-write data
 * @retvalue   :None
********************************************************************/
void OLED_WriteByte(uint8_t dat,uint8_t cmd)
{
    uint8_t mode;

    cmd == OLED_CMD ? (mode = 0x40) : (mode = 0x00);
    IIC_Send_OneByte(OLED_IIC_ADDR,mode,dat);
}
#else
void IIC_delay(void)
{
    u8 t=3;
    while(t--);
}

void I2C_Start(void)
{
    OLED_SDA_Set();
    OLED_SCL_Set();
    IIC_delay();
    OLED_SDA_Clr();
    IIC_delay();
    OLED_SCL_Clr();
    IIC_delay();
}

void I2C_Stop(void)
{
    OLED_SDA_Clr();
    OLED_SCL_Set();
    IIC_delay();
    OLED_SDA_Set();
}

void I2C_WaitAck(void)
{
    OLED_SDA_Set();
    IIC_delay();
    OLED_SCL_Set();
    IIC_delay();
    OLED_SCL_Clr();
    IIC_delay();
}

void Send_Byte(u8 dat)
{
    u8 i;
    for(i=0;i<8;i++)
    {
        if(dat&0x80)
        {
            OLED_SDA_Set();
        }
        else
        {
            OLED_SDA_Clr();
        }
        IIC_delay();
        OLED_SCL_Set();
        IIC_delay();
        OLED_SCL_Clr();
        dat<<=1;
    }
}

void OLED_Write_nByte(u8 * buff,u8 len,u8 mode)
{
    I2C_Start();
    Send_Byte(0x78);
    I2C_WaitAck();
    if(mode)
        Send_Byte(0x40);
    else
        Send_Byte(0x00);
    I2C_WaitAck();
    for (u8 index = 0; index < len; index ++)
    {
        Send_Byte(buff[index]);
        I2C_WaitAck();
    }
    I2C_Stop();
}

void OLED_WriteByte(u8 dat,u8 mode)
{
    I2C_Start();
    Send_Byte(0x78);
    I2C_WaitAck();
    if(mode)
        Send_Byte(0x40);
    else
        Send_Byte(0x00);
    I2C_WaitAck();
    Send_Byte(dat);
    I2C_WaitAck();
    I2C_Stop();
}
#endif

/*******************************************************************
 * @function   :Set coordinates in the OLED screen
 * @parameters :x:x coordinates
                y:y coordinates
 * @retvalue   :None
********************************************************************/
void OLED_Set_Pos(unsigned char x, unsigned char y) 
{
#if 1
    u8 cmdbuff[3];

    cmdbuff[0] = YLevel+y/PAGE_SIZE;
    cmdbuff[1] = (((x+2)&0xf0)>>4)|0x10;
    cmdbuff[2] = (x+2)&0x0f;
    OLED_Write_nByte(cmdbuff,sizeof(cmdbuff),OLED_CMD);
#else
 	OLED_WriteByte(YLevel+y/PAGE_SIZE,OLED_CMD);
	OLED_WriteByte((((x+2)&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WriteByte(((x+2)&0x0f),OLED_CMD);
#endif
}  

/*******************************************************************
 * @name       :void OLED_Display_On(void) 
 * @date       :2018-08-27
 * @function   :Turn on OLED display
 * @parameters :None
 * @retvalue   :None
********************************************************************/ 	 
//开启OLED显示  
void OLED_Display_On(void)
{
    u8 cmdbuff[3] = {0x8D,0x14,0xAF};

    OLED_Write_nByte(cmdbuff,sizeof(cmdbuff),OLED_CMD);

//	OLED_WriteByte(0X8D,OLED_CMD);  //SET DCDC命令
//	OLED_WriteByte(0X14,OLED_CMD);  //DCDC ON
//	OLED_WriteByte(0XAF,OLED_CMD);  //DISPLAY ON
}

/*******************************************************************
 * @name       :void OLED_Display_Off(void)
 * @date       :2018-08-27
 * @function   :Turn off OLED display
 * @parameters :None
 * @retvalue   :None
********************************************************************/    
//关闭OLED显示   
void OLED_Display_Off(void)
{
    u8 cmdbuff[3] = {0x8D,0x10,0xAE};

    OLED_Write_nByte(cmdbuff,sizeof(cmdbuff),OLED_CMD);
//	OLED_WriteByte(0X8D,OLED_CMD);  //SET DCDC命令
//	OLED_WriteByte(0X10,OLED_CMD);  //DCDC OFF
//	OLED_WriteByte(0XAE,OLED_CMD);  //DISPLAY OFF
}

/*******************************************************************
 * @name       :void OLED_Set_Pixel(unsigned char x, unsigned char y,unsigned char color)
 * @date       :2018-08-27
 * @function   :set the value of pixel to RAM
 * @parameters :x:the x coordinates of pixel
                y:the y coordinates of pixel
								color:the color value of the point
								      1-white
											0-black
 * @retvalue   :None
********************************************************************/ 
void OLED_Set_Pixel(unsigned char x, unsigned char y,unsigned char color)
{
	if(color)
	{
		OLED_buffer[(y/PAGE_SIZE)*WIDTH+x]|= (1<<(y%PAGE_SIZE))&0xff;
	}
	else
	{
		OLED_buffer[(y/PAGE_SIZE)*WIDTH+x]&= ~((1<<(y%PAGE_SIZE))&0xff);
	}
}		   			 

/*******************************************************************
 * @name       :void OLED_Display(void)
 * @date       :2018-08-27
 * @function   :Display in OLED screen
 * @parameters :None
 * @retvalue   :None
********************************************************************/  
void OLED_Display(void)
{
	u8 i,n;
	u8 cmdbuff[3];

	cmdbuff[1] = XLevelH;
    cmdbuff[2] = XLevelL;
	for(i=0;i<PAGE_SIZE;i++)  
	{  
	    cmdbuff[0] = YLevel+i;
	    OLED_Write_nByte(cmdbuff,sizeof(cmdbuff),OLED_CMD);
#if 0
	    OLED_WriteByte (YLevel+i,OLED_CMD);    //设置页地址(0~7)
        OLED_WriteByte (XLevelH,OLED_CMD);      //设置显示位置—列高地址
		OLED_WriteByte (XLevelL,OLED_CMD);      //设置显示位置—列低地址
		for(n=0;n<WIDTH;n++)
		{
			OLED_WriteByte(OLED_buffer[i*WIDTH+n],OLED_DATA);
		}
#endif
		OLED_Write_nByte(&OLED_buffer[i*WIDTH],WIDTH,OLED_DATA);
	}   //更新显示
}

/*******************************************************************
 * @name       :void OLED_Clear(unsigned dat)  
 * @date       :2018-08-27
 * @function   :clear OLED screen
 * @parameters :dat:0-Display full black
                    1-Display full white
 * @retvalue   :None
********************************************************************/ 
void OLED_Clear(uint8_t dat)
{  
	if(dat)
	{
		memset(OLED_buffer,0xff,sizeof(OLED_buffer));
	}
	else
	{
		memset(OLED_buffer,0,sizeof(OLED_buffer));
	}
	OLED_Display();
}

/*******************************************************************
 * @name       :void OLED_Init_GPIO(void)
 * @date       :2018-08-27
 * @function   :Reset OLED screen
 * @parameters :None
 * @retvalue   :None
********************************************************************/ 
void OLED_Init_GPIO(void)
{
#ifdef OLED_USE_IIC
    GPIOB_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13, GPIO_ModeIN_PU);
    I2C_Init(I2C_Mode_I2C, 400000, I2C_DutyCycle_16_9, I2C_Ack_Enable, I2C_AckAddr_7bit, MASTER_ADDR);
    WaitIICBusy();
#else
    GPIOB_ModeCfg(OLED_SDA_PIN | OLED_SCL_PIN, GPIO_ModeOut_PP_5mA);
#endif
}

/*******************************************************************
 * @name       :void OLED_Init(void)
 * @date       :2018-08-27
 * @function   :initialise OLED SH1106 control IC
 * @parameters :None
 * @retvalue   :None
********************************************************************/ 				    
void OLED_Init(void)
{
    u8 InitCmd[] = {0xAE,0x00,0x10,0x40,0x81,0xCF,0xA1,0xC8,0xA6,0xA8,0x3F,
        0xD3,0x00,0xD5,0x80,0xD9,0xF1,0xDA,0x12,0xDB,0x30,0x20,0x02,0x8D,0x14};

    OLED_Init_GPIO(); //初始化GPIO

#if 0
	OLED_Display_Off(); //power off
	OLED_WriteByte(0xAE,OLED_CMD);//--turn off oled panel
	OLED_WriteByte(0x00,OLED_CMD);//---set low column address
	OLED_WriteByte(0x10,OLED_CMD);//---set high column address
	OLED_WriteByte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	OLED_WriteByte(0x81,OLED_CMD);//--set contrast control register
	OLED_WriteByte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
	OLED_WriteByte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	OLED_WriteByte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	OLED_WriteByte(0xA6,OLED_CMD);//--set normal display
	OLED_WriteByte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WriteByte(0x3f,OLED_CMD);//--1/64 duty
	OLED_WriteByte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WriteByte(0x00,OLED_CMD);//-not offset
	OLED_WriteByte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	OLED_WriteByte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WriteByte(0xD9,OLED_CMD);//--set pre-charge period
	OLED_WriteByte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WriteByte(0xDA,OLED_CMD);//--set com pins hardware configuration
	OLED_WriteByte(0x12,OLED_CMD);
	OLED_WriteByte(0xDB,OLED_CMD);//--set vcomh
	OLED_WriteByte(0x30,OLED_CMD);//Set VCOM Deselect Level
	OLED_WriteByte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	OLED_WriteByte(0x02,OLED_CMD);//
	OLED_WriteByte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	OLED_WriteByte(0x14,OLED_CMD);//--set(0x10) disable

//	OLED_WriteByte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
//	OLED_WriteByte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
//	OLED_WriteByte(0xAF,OLED_CMD);//--turn on oled panel
#else
    OLED_Write_nByte(InitCmd,sizeof(InitCmd),OLED_CMD);
#endif
    OLED_Clear(0);
//    OLED_WriteByte(0xAF,OLED_CMD); /*display ON*/
	OLED_Set_Pos(0,0);

    OLED_Display_On(); // power on
}  
#ifndef __OLED_H
#define __OLED_H			  	 
#include "HAL.h"
 
#define PAGE_SIZE    8
#define XLevelL		   0x00
#define XLevelH		   0x10
#define YLevel       0xB0
#define	Brightness	 0xFF 
#define WIDTH 	     128
#define HEIGHT 	     64	

#define OLED_IIC_ADDR 0x78
typedef  uint8_t u8;
typedef  uint16_t u16;
typedef  uint32_t u32;

enum{
	OLED_CMD = 0,
	OLED_DATA
};


#ifndef OLED_USE_IIC
#define OLED_USE_IIC
#endif

#define delay_ms(x) DelayMs(x)

#define OLED_SDA   BV(12)   //4 Pin OLED屏SDA
#define OLED_SCL   BV(13)   //7 Pin OLED屏SCL

#define OLED_SDA_OUT   (R32_PB_OUT)   //7 Pin OLED屏SDA
#define OLED_SCL_OUT   (R32_PB_OUT)  //7 Pin OLED屏SCL

#define OLED_SDA_DIR   (R32_PB_DIR |= OLED_SDA)   //7 Pin OLED屏SDA
#define OLED_SCL_DIR   (R32_PB_DIR |= OLED_SCL)   //7 Pin OLED屏SCL

#define OLED_SDA_PIN   GPIO_Pin_12   //4 Pin OLED屏SDA
#define OLED_SCL_PIN   GPIO_Pin_13   //7 Pin OLED屏SCL

#define OLED_SDA_Set()    (OLED_SDA_OUT |= OLED_SDA)
#define OLED_SDA_Clr()    (OLED_SDA_OUT &= (~OLED_SDA))
#define OLED_SCL_Set()    (OLED_SCL_OUT |= OLED_SCL)
#define OLED_SCL_Clr()    (OLED_SCL_OUT &= (~OLED_SCL))

void OLED_WriteByte(uint8_t data,uint8_t cmd);    
void OLED_Display_On(void);
void OLED_Display_Off(void);

void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_Reset(void);
void OLED_Init_GPIO(void);	   							   		    
void OLED_Init(void);
void OLED_Set_Pixel(unsigned char x, unsigned char y,unsigned char color);
void OLED_Display(void);
void OLED_Clear(uint8_t dat);

extern void IIC_Send_OneByte(uint8_t addr, uint8_t mode, uint8_t data);
extern void IIC_Send_2_Byte(uint8_t addr, uint8_t mode, uint8_t data1,uint8_t data2);
extern void IIC_Send_n_Byte(uint8_t addr, uint8_t mode, uint8_t *src, uint8_t len);
extern BOOL WaitIICBusy(void);


#endif
//mode : 0x40 command  0x00 data.
void IIC_Send_OneByte(uint8_t addr, uint8_t mode, uint8_t data)
{
    while(I2C_GetFlagStatus(I2C_FLAG_BUSY));                            //IIC主机判忙
//    if (WaitIICBusy())
//        return;
    I2C_GenerateSTART(ENABLE);                                          //起始信号
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));               //判断BUSY, MSL and SB flags
//    if (Wait_IIC_ModeSelect())
//        return;
    I2C_Send7bitAddress(addr, I2C_Direction_Transmitter);               //发送地址+最低位0表示为“写”
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //判断BUSY, MSL, ADDR, TXE and TRA flags
//    if (Wait_IIC_Trans_ModeSelected())
//        return;

    I2C_SendData(mode);

//ACK之后直接写入数据
    while(!I2C_GetFlagStatus(I2C_FLAG_TXE));                            //获取TxE的状态    数据寄存器为空标志位,可以向其中写数据
//    if (Wait_IIC_SendBuffEmpty())
//        return;
    I2C_SendData(data);                                                 //发送寄存器的地址
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));          //判断TRA, BUSY, MSL, TXE and BTF flags
//    if (Wait_IIC_Trans_Finish())
//        return;

    I2C_GenerateSTOP(ENABLE);                                           //停止信号
}

void IIC_Send_2_Byte(uint8_t addr, uint8_t mode, uint8_t data1,uint8_t data2)
{
//    while(I2C_GetFlagStatus(I2C_FLAG_BUSY));                            //IIC主机判忙
    if (WaitIICBusy())
        return;

    I2C_GenerateSTART(ENABLE);                                          //起始信号
//    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));               //判断BUSY, MSL and SB flags
    if (Wait_IIC_ModeSelect())
        return;

    I2C_Send7bitAddress(addr, I2C_Direction_Transmitter);               //发送地址+最低位0表示为“写”
//    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //判断BUSY, MSL, ADDR, TXE and TRA flags
    if (Wait_IIC_Trans_ModeSelected())
        return;
    I2C_SendData(mode);                                              //发送寄存器的地址

//    while(!I2C_GetFlagStatus(I2C_FLAG_TXE));                            //获取TxE的状态    数据寄存器为空标志位,可以向其中写数据
    if (Wait_IIC_SendBuffEmpty())
        return;

    I2C_SendData(data1);                                             //发送寄存器的地址
//    while(!I2C_GetFlagStatus(I2C_FLAG_TXE));                            //获取TxE的状态    数据寄存器为空标志位,可以向其中写数据
    if (Wait_IIC_SendBuffEmpty())
        return;

    I2C_SendData(data2);                                             //发送寄存器的地址

//    while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));          //判断TRA, BUSY, MSL, TXE and BTF flags
    if (Wait_IIC_Trans_Finish())
        return;
    I2C_GenerateSTOP(ENABLE);                                           //停止信号
}

void IIC_Send_n_Byte(uint8_t addr, uint8_t mode, uint8_t *src, uint8_t len)
{
//    while(I2C_GetFlagStatus(I2C_FLAG_BUSY));                            //IIC主机判忙
    if (WaitIICBusy())
        return;

    I2C_GenerateSTART(ENABLE);                                          //起始信号
//    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));               //判断BUSY, MSL and SB flags
    if (Wait_IIC_ModeSelect())
        return;

    I2C_Send7bitAddress(addr, I2C_Direction_Transmitter);               //发送地址+最低位0表示为“写”
//    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //判断BUSY, MSL, ADDR, TXE and TRA flags
    if (Wait_IIC_Trans_ModeSelected())
        return;

    I2C_SendData(mode);                                              //发送寄存器的地址

//ACK之后直接写入数据
    for(uint8_t i=0; i<len; i++)
    {
//        while(!I2C_GetFlagStatus(I2C_FLAG_TXE));                            //获取TxE的状态    数据寄存器为空标志位,可以向其中写数据
        if (Wait_IIC_SendBuffEmpty())
            return;
        I2C_SendData(*(src+i));                                             //发送寄存器的地址
    }

//    while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));          //判断TRA, BUSY, MSL, TXE and BTF flags
    if (Wait_IIC_Trans_Finish())
        return;

    I2C_GenerateSTOP(ENABLE);                                           //停止信号
}

上述代码包含软件模拟实现IIC协议,切换也很简单,只需要简单修改#define OLED_USE_IIC即可。

七、常见问题排查

显示异常:检查VCOMH电压设置(0xDB指令)和预充电周期(0xD9指令)

I2C通信失败:确认总线空闲状态(I2C_FLAG_BUSY)和ACK应答机制

残影现象:增加0x20指令设置内存地址模式,确保寻址正确

完整代码:CH582、CH592、CH584硬件IIC驱动4PinOLED显示屏,代码包含有软件模拟IIC协议驱动OLED屏资源-CSDN下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

永远的元子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值