MTK 各部分硬件相关驱动

http://blog.csdn.net/jiangyu912/article/details/5692050

 声明:资料为公司同事整理和提供

  

 

一:LCD

文件位于custom/drv/LCD

以华立维的一款240X320的屏为例介绍如何添加LCD驱动

gprs.mak

LCD_MODULE = HUALIWEI_SSD1289_LCM

MAIN_LCD_SIZE = 240X320

Option

COM_DEFS_FOR_HUALIWEI_SSD1289_LCM = HUALIWEI_SSD1289_LCM SSD1289 COLOR_LCD TFT_MAINLCD QVGA_MAINLCD

 

在custom/drv/LCD添加HUALIWEI_SSD1289_LCM文件夹,下面有5个文件。文件名同MTK系统自带的(lcd.c lcd_hw.h lcd_sw.h lcd_sw_inc.h lcd_sw_rnd.h)。

 

HUALIWEI--------------屏的厂家

SSD1289-----------------屏的驱动芯片

LCM----------------------屏

240X320-----------------屏的分辨率

COLOR_LCD----------彩色

TFT_MAINLCD-------屏的类型,对应的还有CSTN,OLED。目前主要是TFT

QVGA_MAINLCD----屏的分辨率

 

 

做了上述修改以后,编译时,lcd驱动就对应HUALIWEI_SSD1289_LCM文件夹里的驱动。文件夹里的5个文件,通常lcd_hw.h, lcd_sw_rnd不需要修改。lcd_sw_inc.h只是定义屏的分辨率。如下:

#ifdef __MMI_MAINLCD_128X128__

#define LCD_WIDTH 128

#define LCD_HEIGHT 128

#elif (defined(__MMI_MAINLCD_128X160__))

#define LCD_WIDTH 128

#define LCD_HEIGHT 160

#elif (defined(__MMI_MAINLCD_176X220__))

#define LCD_WIDTH 176

#define LCD_HEIGHT 220

#elif (defined(__MMI_MAINLCD_240X320__))

#define LCD_WIDTH 240

#define LCD_HEIGHT 320

#endif

 

#define UI_DEVICE_WIDTH LCD_WIDTH

#define UI_DEVICE_HEIGHT LCD_HEIGHT

修改比较多的是lcd.c和lcd_sw.h。

Lcd_sw.h

#define LCD_CMD_DMA_MODE---------是否使用DMA方式?(DMA简单,速度快,通过MTK的寄存器进行操作,但灵活性差。非DMA方式,直接对地址操作,灵活性好,但速度会有影响。目前,一般都是用DMA方式)

#define LCD_16BIT_MODE-----------------lcd使用16位总线?(由硬件决定)

 

 

#define LCD_SSD1289_CTRL_ADDR LCD_PARALLEL0_A0_LOW_ADDR

#define LCD_SSD1289_DATA_ADDR LCD_PARALLEL0_A0_HIGH_ADDR

#define MAIN_LCD_CMD_ADDR LCD_SSD1289_CTRL_ADDR

#define MAIN_LCD_DATA_ADDR LCD_SSD1289_DATA_ADDR

 

#define MAIN_LCD_OUTPUT_FORMAT LCM_16BIT_16_BPP_RGB565_1

 

 

 

#define LCD_delay_SSD1289() /

{/

volatile kal_uint16 iI; /

for (iI = 0; iI < 0x20; iI++);/

}

 

#ifdef LCD_CMD_DMA_MODE-------------DMA方式

 

#define LCD_SEND_DMA_CMD(n) /

{/

while (LCD_IS_RUNNING);/

DISABLE_LCD_TRANSFER_COMPLETE_INT;/

DISABLE_ALL_LCD_LAYER_WINDOW;/

SET_LCD_ROI_CTRL_NUMBER_OF_CMD(n);/

ENABLE_LCD_ROI_CTRL_CMD_FIRST;/

SET_LCD_ROI_WINDOW_SIZE(0, 0);/

START_LCD_TRANSFER;/

while (LCD_IS_RUNNING);/

}

 

#define LCD_CtrlWrite_SSD1289(_data) /

{/

SET_LCD_CMD_PARAMETER(0, LCD_CMD, _data);/ --------写的是命令

LCD_SEND_DMA_CMD(1);/

}

#define LCD_DataWrite_SSD1289(_data) /

{/

SET_LCD_CMD_PARAMETER(0, LCD_DATA, _data);/ --------写的是数据

LCD_SEND_DMA_CMD(1);/

}

#else ----------非DMA方式

#define LCD_CtrlWrite_SSD1289(_data) /

{/

*(volatile kal_uint32 *) LCD_SSD1289_CTRL_ADDR = _data;/ --------写的是命令

LCD_delay_SSD1289();/

}

 

#define LCD_DataWrite_SSD1289(_data) /

{/

*(volatile kal_uint32 *) LCD_SSD1289_DATA_ADDR = _data;/------------写的是数据

LCD_delay_SSD1289();/

}

#endif

 

#define LCD_DataRead_SSD1289 (*(volatile kal_uint16 *)LCD_SSD1289_DATA_ADDR);

------用于读LCD id,兼容lcd用。(这个需要硬件上接读lcd的信号)

 

 

Lcd.c

LCD_Funcs LCD_func_SSD1289 = {

LCD_Init_SSD1289,

LCD_PWRON_SSD1289,

LCD_SetContrast_SSD1289,

LCD_ON_SSD1289,

LCD_BlockWrite_SSD1289,

LCD_Size_SSD1289,

LCD_EnterSleep_SSD1289,

LCD_ExitSleep_SSD1289,

LCD_Partial_On_SSD1289,

LCD_Partial_Off_SSD1289,

LCD_Partial_line_SSD1289,

 

LCD_GetParm_SSD1289,

LCD_SetBias_SSD1289,

LCD_Contrast_SSD1289,

LCD_LineRate_SSD1289,

LCD_Temp_Compensate_SSD1289

#ifdef __LCD_ESD_RECOVERY__

,LCD_ESD_check_SSD1289

#endif

};

 

 

void LCD_FunConfig(void)

{

MainLCD = &LCD_func_SSD1289;

}

 

上层通过这个LCD_func_SSD1289来调用相应的lcd驱动函数的。这个结构体里的很多函数不需要修改。经常需要修改的有以下几个函数:

LCD_Init_SSD1289(), LCD_BlockWrite_SSD1289(), LCD_EnterSleep_SSD1289(),

LCD_ExitSleep_SSD1289()。

这其中,LCD_Init_SSD1289(), LCD_EnterSleep_SSD1289(), LCD_ExitSleep_SSD1289(),屏厂会提供,只需要按照写就可以了。LCD_BlockWrite_SSD1289()需要根据LCD的datasheet写。

见ssd1289+2.2topsun-init.txt

LCD_Init_SSD1289()

{

……………….

LCD_CtrlWrite_SSD1289(0x0000);

LCD_DataWrite_SSD1289(0x0001);

 

LCD_CtrlWrite_SSD1289(0x0003);

LCD_DataWrite_SSD1289(0xa8a4);

…………………

}

 

 

void LCD_BlockWrite_SSD1289(kal_uint16 startx,kal_uint16 starty,kal_uint16 endx,kal_uint16 endy)

{

…………………….

SET_LCD_CMD_PARAMETER(0,LCD_CMD, 0x4E); ---------表示寄存器

SET_LCD_CMD_PARAMETER(1,LCD_DATA, startx); ----------表示寄存器中的值

SET_LCD_CMD_PARAMETER(2,LCD_CMD, 0x4F);

SET_LCD_CMD_PARAMETER(3,LCD_DATA, starty);

SET_LCD_CMD_PARAMETER(4,LCD_CMD, 0x44);

SET_LCD_CMD_PARAMETER(5,LCD_DATA, (((endx & 0x00ff)<<8) | (startx & 0x00ff)));

SET_LCD_CMD_PARAMETER(6,LCD_CMD, 0x45);

SET_LCD_CMD_PARAMETER(7,LCD_DATA, starty);

SET_LCD_CMD_PARAMETER(8,LCD_CMD, 0x46);

SET_LCD_CMD_PARAMETER(9,LCD_DATA, endy);

 

SET_LCD_CMD_PARAMETER(10,LCD_CMD, 0x22);

 

ENABLE_LCD_TRANSFER_COMPLETE_INT;

ENABLE_LCD_ROI_CTRL_CMD_FIRST;

SET_LCD_ROI_CTRL_NUMBER_OF_CMD(11);

START_LCD_TRANSFER;

}

 

具体的寄存器意义,见datasheet SSD1289_1.1.pdf (P51)datasheet。这个是一般的lcd调试,特殊的不做描述。

 

在硬件没有问题的情况下,lcd没有点亮,可做如下动作:

1) 在LCD_Init_SSD1289()函数下加

{

lcd_drive_ic_id = LCD_DataRead_SSD1289;

 

}

2) LCD_Init_SSD1289()增大lcd复位时间

{

SET_LCD_CTRL_RESET_PIN;

LCD_Delay100us(1000);

CLEAR_LCD_CTRL_RESET_PIN;

LCD_Delay100us(1000);

SET_LCD_CTRL_RESET_PIN;

LCD_Delay100us(1000);

}

3) LCD_Init_SSD1289()添加测试代码

{

{

unsigned int m,n;

GPIO_ModeSetup(25, 0);

GPIO_InitIO(1, 25);

GPIO_WriteIO(1, 25);

for(m=0; m<240; m++)

for(n=0; n<320; n++)

{

LCD_DataWrite_SSD1289(0xf800);

}

}-----------用于判断初始化代码是否正确

}

4) 修改时序,主要是写的时序void init_lcd_interface(void)

{

SET_LCD_PARALLEL_CE2WR_SETUP_TIME((kal_uint32)3);

SET_LCD_PARALLEL_CE2WR_HOLD_TIME(4);

SET_LCD_PARALLEL_CE2RD_SETUP_TIME(3);

SET_LCD_PARALLEL_WRITE_WAIT_STATE(7);

SET_LCD_PARALLEL_READ_LATENCY_TIME(31);

SET_LCD_ROI_CTRL_CMD_LATENCY(10);

}

5) 初始化正确的前提下,检查函数LCD_BlockWrite_SSD1289()。这个时候,屏上应该有显示了。只是显示不正常。

 

二:键盘

通常只需要修改keypad_def.c文件。

一般硬件会提供如下

C0 C1 C2 C3 C4

R1 UP 7 Right 9 VOL+

R2 左软件 OK Down 3 VOL-

R3 SEND 0 8 # 播放/暂停

R4 Left 1 2 右软 快退

R5 * 4 5 6 快进

 

软件只需要填进去就可以了。

const keypad_struct keypad_custom_def = {

{

 

DEVICE_KEY_SK_LEFT,

DEVICE_KEY_SEND,

DEVICE_KEY_SK_RIGHT,

DEVICE_KEY_UP,

DEVICE_KEY_VOL_UP,

DEVICE_KEY_NONE,

DEVICE_KEY_END,

 

 

DEVICE_KEY_1,

DEVICE_KEY_4,

DEVICE_KEY_7,

DEVICE_KEY_MENU,

DEVICE_KEY_VOL_DOWN,

DEVICE_KEY_NONE,

DEVICE_KEY_END,

 

 

DEVICE_KEY_2,

DEVICE_KEY_5,

DEVICE_KEY_8,

DEVICE_KEY_DOWN,

DEVICE_KEY_NONE,

DEVICE_KEY_NONE,

DEVICE_KEY_END,

 

 

DEVICE_KEY_3,

DEVICE_KEY_6,

DEVICE_KEY_9,

DEVICE_KEY_LEFT,

DEVICE_KEY_FUNCTION,

DEVICE_KEY_NONE,

DEVICE_KEY_END,

 

 

DEVICE_KEY_STAR,

DEVICE_KEY_0,

DEVICE_KEY_HASH,

DEVICE_KEY_RIGHT,

DEVICE_KEY_NONE,

DEVICE_KEY_NONE,

DEVICE_KEY_END,

 

 

DEVICE_KEY_NONE,

DEVICE_KEY_NONE,

DEVICE_KEY_NONE,

DEVICE_KEY_NONE,

DEVICE_KEY_NONE,

DEVICE_KEY_NONE,

DEVICE_KEY_END

},

Custom_Keypress_Period,

};

 

三:音频PA开关 afe.c

void AFE_SwitchExtAmplifier( char sw_on )

{

if( sw_on )

{

GPIO_WriteIO( 1, 5 );----------使用的是GPIO5,每个项目会不同,需根据硬件修改

}

else

{

GPIO_WriteIO( 0, 5 );

}

}

 

 

 

四:USB电源开关 usb_custom.c

void USB_PowerControl(kal_bool enable)

{

#ifdef __USB_ENABLE__

GPIO_ModeSetup(35, 0); --------使用的是GPIO35,每个项目会不同,需根据硬件修改

 

GPIO_InitIO(1, 35);

if (enable == KAL_TRUE)

GPIO_WriteIO(1,35);

else

GPIO_WriteIO(0,35);

#endif

}

 

五:lcd背光custom_equipment.c

kal_bool custom_cfg_gpio_set_level(kal_uint8 gpio_dev_type, kal_uint8 gpio_dev_level )

{

case GPIO_DEV_LED_MAINLCD:

……………

break;

}

 

lcd背光驱动,一般有以下两种方式:

1) PWM方式

GPIO_ModeSetup(25, 2);

PWM_level(gpio_dev_level);

2) gpio脉冲方式。这个根据背光芯片的要求,可能有所不同。

{

GPIO_ModeSetup(25, 0);

GPIO_InitIO(1, 25);

if (gpio_dev_level == LED_LIGHT_LEVEL0)

{

GPIO_WriteIO(0, 25);

BL_Delay50us(100);

}

else

{

kal_uint8 level_array[6] = {0, 28, 20, 10, 6, 2};

 

savedMask=SaveAndSetIRQMask();

 

 

 

 

for(j=0; j< level_array[gpio_dev_level]; j++)

{

volatile kal_uint16 delay;

 

GPIO_WriteIO(0,25);

for (delay =0;delay <5;delay++){}

GPIO_WriteIO(1, 25 );

for (delay =0;delay <5;delay++){}

}

RestoreIRQMask(savedMask);

BL_Delay50us(20);

}

}

 

六:键盘背光custom_equipment.c

kal_bool custom_cfg_gpio_set_level(kal_uint8 gpio_dev_type, kal_uint8 gpio_dev_level )

{

case GPIO_DEV_LED_KEY:

……………

break;

}

一般通过gpio口拉高拉低来开关。不同项目,gpio口可能不同。

{

GPIO_InitIO(1, 27);

GPIO_ModeSetup(27, 0);

if (gpio_dev_level == LED_LIGHT_LEVEL0)

{

GPIO_WriteIO(0,27);

}

else

{

GPIO_WriteIO(1,27);

}

}

 

七:振动custom_equipment.c

kal_bool custom_cfg_gpio_set_level(kal_uint8 gpio_dev_type, kal_uint8 gpio_dev_level )

{

case GPIO_DEV_VIBRATOR:

……………

break;

}

一般通过gpio口拉高拉低来开关。不同项目,gpio口可能不同。

{

GPIO_InitIO(1, 6);

GPIO_ModeSetup(6, 0);

 

if (gpio_dev_level == LED_LIGHT_LEVEL0)

{

GPIO_WriteIO(0,6);

}

else

{

GPIO_WriteIO(1,6);

}

break;

}

 

八:flash修改custom_MemoryDevice.h

首先硬件会提供项目中使用的flash型号或datasheet。然后到mcu/tools

/MemoryDeviceList/ MemoryDeviceList_XXX..xls(一般是日期最靠前的那个)查找,是否有flash对应的型号。如果有,表示软件支持这颗flash,如果没有,表示软件不支持这颗flash,那需要调加或需要MTK释放新的软件。

支持的话,需用将custom_MemoryDevice.h中添加对应的型号

#define CS0_PART_NUMBER S71GL128NB0BFW9Z

#define CS1_PART_NUMBER S71GL128NB0BFW9Z

通常来说,开不了机,首先要检查flash是否配置正确。

 

九:ADC的配置adc_channel.c

 

const kal_uint8 ADC_VBAT = 0;

const kal_uint8 ADC_VISENSE = 1;

const kal_uint8 ADC_VBATTMP = 2;

const kal_uint8 ADC_VCHARGER = 3;

const kal_uint8 ADC_ACCESSORYID = 5;

const kal_uint8 ADC_PCBTMP = 4;

#if defined(__CHARGER_USB_DETECT_WIHT_ONE_EINT__)

const kal_uint8 ADC_CHR_USB = 6;

#endif

 

如果需要修改,硬件工程师会提供ADC对应的功能。

 

十:外部中断的配置eint_def.c

const kal_uint8 AUX_EINT_NO = 0;

const kal_uint8 CHRDET_EINT_NO = EINT_CHANNEL_NOT_EXIST;

 

#if defined(__PHONE_CLAMSHELL__) || defined(__PHONE_SLIDE__)

const kal_uint8 CLAMDET_EINT_NO = EINT_CHANNEL_NOT_EXIST;

#endif

 

#ifdef __USB_ENABLE__

const kal_uint8 USB_EINT_NO = EINT_CHANNEL_NOT_EXIST;

#else

const kal_uint8 USB_EINT_NO = EINT_CHANNEL_NOT_EXIST;

#endif

 

#ifdef __BT_SUPPORT__

const kal_uint8 BT_EINT_NO = 1;

#endif

 

#if defined(__CHARGER_USB_DETECT_WIHT_ONE_EINT__)

const kal_uint8 CHR_USB_EINT_NO = 2;

#endif

 

#ifdef __SWDBG_SUPPORT__

const kal_uint8 SWDBG_EINT_NO = EINT_CHANNEL_NOT_EXIST;

#endif

 

#if defined(MOTION_SENSOR_SUPPORT)

const kal_uint8 MOTION_SENSOR_EINT_NO = EINT_CHANNEL_NOT_EXIST;

 

#endif

 

#if defined(TOUCH_PANEL_SUPPORT) || defined(HAND_WRITING)

const kal_uint8 TOUCH_PANEL_EINT_NO = 3;

#endif

 

#ifdef __WIFI_SUPPORT__

const kal_uint8 WIFI_EINT_NO = EINT_CHANNEL_NOT_EXIST;

#endif

 

 

一般,EINT_CHANNEL_NOT_EXIST表示硬件上没有这个中断,也就是没有这个功能。如果需要修改,硬件工程师会提供相关的资料。

 

十一:触摸屏

触摸屏相关的文件有eint_def.c,touch_panel.c,touch_panel.h,touch_panel_buffer.h,

touch_panel_custom.c,touch_panel_custom.h,touch_panel_main.c,touch_panel_spi.c,

touch_panel_spi.h,touchscreen.c。

而对驱动来说,一般需要修改以下文件:

eint_def.c

#if defined(TOUCH_PANEL_SUPPORT) || defined(HAND_WRITING)

const kal_uint8 TOUCH_PANEL_EINT_NO = 3;

#endif

 

kal_uint8 custom_eint_sw_debounce_time_delay[EINT_MAX_CHANNEL] =

{

50,

0,

50,

0

};

 

touch_panel_spi.h

#define SPI_DIN_PIN 0

#define SPI_CLK_PIN 40

#define SPI_DOUT_PIN 42

#define SPI_CS_PIN 32

#define SPI_BUSY_PIN 30

触摸屏对应的控制引脚,由硬件决定

 

touch_panel.c

kal_uint32 ADC_X_START=370;

kal_uint32 ADC_X_END=3740;

kal_uint32 ADC_Y_START=300;

kal_uint32 ADC_Y_END=3690;

kal_uint32 SCREEN_X_START=0;

kal_uint32 SCREEN_X_END=240;

kal_uint32 SCREEN_Y_START=0;

kal_uint32 SCREEN_Y_END=320;

 

touch_panel_custom.h

#define TOUCH_PANEL_ADC_X_START 370

#define TOUCH_PANEL_ADC_X_END 3740

#define TOUCH_PANEL_ADC_Y_START 300

#define TOUCH_PANEL_ADC_Y_END 3690

 

#define TOUCH_PANEL_COORD_X_START 0

#define TOUCH_PANEL_COORD_X_END 239

#define TOUCH_PANEL_COORD_Y_START 0

#define TOUCH_PANEL_COORD_Y_END 319

touch_panel.c和touch_panel_custom.h的值是对应的。这个值不正确,会导致触摸屏不校准,触摸屏不能用。这个值可以简单得到;

touch_panel_custom.c

format下载完以后,点击触摸屏的左上脚(x_start,y_start)

和右下脚(x_end,y_end),得到的值就是,可以通过log得到。

void tp_read_adc(kal_int16 *x, kal_int16 *y)

{

*y=serial_read_data();

*x=serial_read_data();

kal_prompt_trace(MOD_MMI,”!!!!!!! *x = %d *y = %d”,*x,*y);

}

 

十二:蓝牙,目前都是用BTMTK_MT6601

一般需要修改btmtk_config.c和eint_def.c

eint_def.c

#ifdef __BT_SUPPORT__

const kal_uint8 BT_EINT_NO = 1;

#endif

 

btmtk_config.c

#ifdef __BTMODULE_MT6601__

 

const unsigned char bt_gpio_setting[16] =

{ 34, 1, // power on : pin(if use GPO, please plus 100), pol

3, 1, // reset : pin(if use GPO, please plus 100), pol

1, 1, // bt2gsm : pin(EINT n), pol

49, 50, // rxd3, txd3

0xFF, 0xFF, // cts3, rts3

0xff, 0xff, // lpoclk, mode

51, 54, // PCM clk, PCM sync

52, 53 // PCM data output, PCM data input

};

 

#endif

 

蓝牙对应的控制引脚,由硬件决定

 

十三:FM

目前使用的FM有MT6188,SI4700,RDA5800。

MT6188的驱动对应的文件是MT6188.c。通常来说,只需要修改

#define CRYCLK 26 //GPIO26

//这个脚不一定需要,根据硬件 #define LE 4 /// GPIO4

#define SDA 48 //GPIO48

#define SCL 47 //GPIO47

SI4700和RDA5800对应的驱动文件是SI4700。

一般需要的修改的也是控制引脚

#define RST 1

#define EN 4

#define SCLK 47

#define SDIO 48

#define FM_CLK 26

 

添加SI4700的驱动

gprs.mak

FM_RADIO_CHIP = SI4720 #MT6188

 

/fm_drv/下添加文件

SI4700_drv.c

 

/make/fm_drv/fm_drv.lis文件中添加

fm_drv/SI4700_drv.c

 

十四:camera

gprs.mak

CMOS_SENSOR = OV7670

 

camera相关的文件位于

/custom/drv/camera/DESHENG25_GEMINI_BB/

/custom/drv/yuv_sensor/

 

一般需要修改如下文件:

camera_hw.c

#define MODULE_POWER_PIN 34// camera电源脚

 

Sccb.h

#define SCCB_SERIAL_CLK_PIN 8 //SCL

#define SCCB_SERIAL_DATA_PIN 9 //SDA

 

/custom/drv/yuv_sensor/OV7670下的image_sensor.c,image_sensor.h

一般来说,image_sensor.c和image_sensor.h由camera厂商提供。

 

如果要新添加一种camera,如MC501CB。

则:

gprs.mak

CMOS_SENSOR = MC501CB

 

/custom/drv/yuv_sensor/

下添加文件夹MC501CB。文件夹下有如下文件:image_sensor.c, image_sensor.h,usbvideo_attr.c。

image_sensor.c和image_sensor.h由camera厂商提供,而usbvideo_attr.c一般不需要修改。

 

十五:射频修改

一般修改如下几个文件:l1d_custom_rf.h,m12193.c,m12193.h,chr_parameter.c

射频会提供相应的参数,只需要找到相应的位置,填进去。

 

十六:音频参数的修改nvram_default_audio.c

这个文件对应正常,耳机,免提模式下的音频参数。

GAIN_NOR_XXX 正常模式

GAIN_HED_XXX 耳机模式

GAIN_HED_XXX 免提模式

 

十七:初始gpio配置gpio_drv.c

void GPIO_init(void)

{

 

}

这个函数对gpio口进行初始的配置。如果配置不正确,会引起耗流问题。根据

硬件来写。

 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值