10天学会嵌入式技术之51单片机-day-5

中断与定时器总结 对于单片机来讲,在程序的执行过程中,由于某种外界的原因,必须终止当前执行的程序,而去执行相应的处理程序,待处理结束后,再回来继续执行被终止的程序,这个过程叫中断。中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。它也是单片机最重要的功能之一,是我们学习单片机必须要掌握的。中断的出现代表我们可以完成许多事情,排列一些程序发生的顺序。 阅读详情

第十四章 定时器中断

14.1 需求描述

使用定时器中断的方式实现 LED 闪烁,具体要求是使用定时器 0 令 LED1 每 1 秒钟闪
烁一次。

14.2 定时器使用说明

定时器的基本工作原理,是使用一个 n 位的脉冲计数器,对时钟信号的脉冲进行计数,
每个脉冲加 1,当脉冲计数器达到最大值(2n)时,也就是溢出时,触发定时器中断。关
于时钟信号,需要了解如下概念。

根据定时器的工作原理,可以看出,定时的时间会受到以下几个因素的影响。

(1)脉冲计数器的位数
(2)脉冲计数的初始值
(3)时钟信号的频率

在使用定时器时,需要特别注意上述三个因素。定时器的具体用法如下,以定时器 0
为例。

14.2.2 启用定时器中断

STC89C52 系列共有 3 个定时器,每个定时器都有其对应的中断。定时器 0 的中断允
许控制位位于 IE 寄存器,如下。

开启定时器 0 的中断需要做出如下配置。

// 中断总开关
EA = 1;
// 定时器 0 中断开关
ET0 = 1;

14.2.3 选择定时器工作模式

STC89C52 系列的定时器都有多种工作模式,以适用不同的工作场景。因此开发者需
要根据自己的场景选择相应的工作模式。
 

(1)计数/定时方式

STC89C52 系列的定时器都有定时和计数两种工作方式。定时方式用于产生精确的时
间延迟,计数方式用于统计外部脉冲信号的个数。

两种工作方式的本质是相同的,都是使用脉冲计数器对脉冲进行计数,只不过,定时
方式下的脉冲信号为系统时钟信号,而计数方式下,脉冲信号来自单片机外部引脚。

每个定时器都有一个控制位,用于设置计数/定时方式。定时器 0 的控制位是 TMOD
(Timer Mode,定时器模式)寄存器中的 C/T(Counter/Timer)位。

因此如需使用定时器方式,应将 C/T 控制位设置为 0,注意 TMOD 寄存器不可位寻址。

(2)工作模式

除了可以选择计数/定时方式之外,每个定时器还提供了多种工作模式供开发者选择。
定时器 0 共有 4 个工作模式,如下。

   1)模式 0——13 位定时/计数器
该模式下的脉冲计数器共有 13 位,最大计数为 8192。如下图所示,TL0 和 TH0 为两
个 8 位寄存器,用于存储脉冲计数器数值,该模式下 TL0 只用到了低 5 位。

2)模式 1——16 位定时/计数器

该模式的脉冲计数器共有 16 位,最大计数为 65536。如下图所示,TL0 的 8 位和 TH0
的 8 位都用到了。

3)模式 2——8 位自动重装载

前两种模式,一次定时完毕后,如需再次定时,需要开发者重新为脉冲计数器设定初
始值。而该模式可以在脉冲计数器溢出时,自动重新设置初始值,很适合用于执行周期性
任务。
该模式下,只用 TL0 寄存器用于存储脉冲计算器数值,TH0 则用于存储脉冲计数器的
初始值,每次 TL0 溢出之后, 都会自动将 TH0 的值重新装入 TL0。

4)模式 3——双 8 位定时/计数器
 

该模式下,TL0 和 TH0 分别用作一个 8 位脉冲计数器,如果需要使用两个 8 位定时器
可使用该模式。

这四种工作模式需要两个控制位进行设置,两个控制位位于 TMOD(Timer Mode,定
时器模式)寄存器,如下图所示。

14.2.4 设置脉冲计数器初始值

由于 51 单片机定时器是在脉冲计数器溢出时触发中断,因此定时的长短需要通过脉冲
计数器的初始值控制。因此在使用定时器时,需要先根据期望的定时长短计算出脉冲计数
器的初始值。

下面以定工作模式 1(16 位)为例,介绍初始值的计算过程。

(1)明确每个计数脉冲的时间
根据定时器的结构图可以看出,传递给脉冲计数器的信号是系统时钟信号经过分频后
得到,且分频可选两种,分别是 12 分频和 6 分频,默认是 12 分频。

当前系统的时钟频率为 11.0592MHz,也就是 11059200Hz,所以计数脉冲的频率是
11059200/12 Hz,因此一个计数脉冲的时间是 12/11059200 s,大约是 1.08us。

(2)计算所需脉冲个数

明确每个计数脉冲的时长之后,在根据期望定时时长便能计算出所需脉冲个数。假如
现在需要定时 1ms,那么 1ms 需要的脉冲个数应为 0.001/(12/11059200)。
(3)计算脉冲计数器初始值

假如现在需要定时 1ms,那么 1ms 需要的脉冲个数应为 0.001/(12/11059200),因此定
时器的初始值应为 65536-0.001/(12/11059200),大约等于 64614。
计算完毕后,需要将该值赋予 TL0(低 8 位)和 TH0(高 8 位),如下。

TL0=64414;
Th0=64414>>8;

14.2.5 启动定时器

在做完上述配置后,还需最后一步——启动定时器,启动之后定时器才会开始工作。
定时器的启动可由单片机内部的寄存器控制,也可由单片机的外部引脚控制。具体控制逻
辑如下图所示。
当 GATE=0 时,外部引脚(INT0,P3.2)无效,此时只能由内部寄存器 TR0 控制,
当 TR0=1 时,脉冲计数器开始计数,TR0=0 时,停止计数。
当 GATE=1 时,外部引脚(INT0,P3.2)生效,此时只有当内部寄存器 TR0 和外部引
脚 INT0 都为 1 时,脉冲计数器才开始计数,否则停止计数。

定时器 0 的 GATE 控制位位于 TMODE 寄存器,如下图所示

定时器 0 的 TR0 控制位,位于 TCON 寄存器,如下图所示。

14.2.6 定义中断服务程序

定时器 0 的中断号为 1,因此中断服务函数应定义为。
 

void Timer0_Hander() interrupt 1
{
//编写定时任务逻辑
}

14.3 软件设计

14.3.1 实现思路

(1)启用定时器 0 中断

// 中断总开关
EA = 1;
// 定时器 0 中断开关
ET0 = 1;

(2)选择定时器 0 工作模式

首先需要明确定时/计数的工作方式,其次还需选择脉冲计数器的工作模式。此处选择
计时+模式 1(16 位),具体配置如下
.

另外由于 TMOD 寄存器不可位寻址,所以可在设置工作模式的同时,将 GATE 位也
一并设置好,当前案例不需要外部引脚控制定时器,因此将 GATE 设置为 0 即可。
所以 TMOD 寄存器低四位的值应为 0001,而高四位的值应保持原值,所以可对
TMOD 寄存器做出如下配置。

// GATE=0;C/T=0;M1=0,M0=1
TMOD &= 0xF0;
TMOD |= 0x01;

(3)设置脉冲计数器的初始值

当前需求是令 LED1 每秒钟闪烁一次,具体来说就是每隔 0.5s 改变一下 LED1 的状态,
显然这是一个周期性任务。对于该任务,我们可以先考虑为定时器定时 0.5s,然后在定时
器中断触发后,再次定时 0.5s,这样就能实现周期性任务了。
但是需要注意,0.5s 所需的脉冲个数为 0.5/(12/11059200)= 460800 个,显然已经超出
了 16 位置脉冲计数器的最大值(65536),也就是说定时器不支持 0.5s 的长时间定时。
针对这种情况,就需要令脉冲计数器溢出多次来达到期望的定时时长,具体来讲就是
设定一个较短的定时,比如 1ms,中断之后,再次定时 1ms,直到达到期望的定时时长之
后,再去执行具体的任务。
综上所述,对于当前需求,我们就可以将定时时长设置为 1ms,每次中断之后,就再
定时 1ms,除此之外,我们还需要对中断的次数进行统计,每中断 500 次,就改变一下
LED1 的状态,这样就能够实现 0.5s 的周期性任务了。
所以脉冲计数器的初始值应该设置为 65536-0.001/(12/11059200)= 64614,具体如下。

TL0 = 64614;
TH0 = 64614 >> 8;

(4)启动定时器

由于 GATE 已经设置为 0,因此只需将 TR0 设置为 1,即可启动定时器。

// 启动定时器
TR0 = 1;

(5)定义中断服务程序

按照前文的描述,中断服务程序需要完成如下任务。
(1)重新装载脉冲计数器
(2)统计脉冲次数,每 500 次改变一次 LED1 的状态
具体代码如下。

void Timer0_Hander() interrupt 1
{
//定义静态局部变量
    static unsigned int count = 0;
//重新状态脉冲计数器
    TL0 = 64614;
    TH0 = 64614 >> 8;
//统计中断次数
    if (count++ >= 500) {
        LED1 = ~LED1;
        count = 0;
    }
}

14.3.2 完整代码

1)Util.h

在 Util.h 中增加以下宏定义。

#define FOSC 11059200 // 晶振频率
#define NT 12 // 单片机的工作周期为 12T


2)Dri_Timer0.h

#ifndef __DRI_TIMER0_H__
#define __DRI_TIMER0_H__
#include <STC89C5xRC.H>
#include "Util.h"
void Timer0_Init();
#endif

(3)Dri_Timer0.c

#include "Dri_Timer0.h"
#define T1MS (65536 - FOSC / NT / 1000)
void Timer0_Init()
{
// 中断总开关
    EA = 1;
// 定时器 0 中断开关
    ET0 = 1;
// 定时器 0 工作方式
    TMOD &= 0xF0;
    TMOD |= 0x01;
// 脉冲计数器初始值
    TL0 = T1MS;
    TH0 = T1MS >> 8;
// 启动定时器
    TR0 = 1;
}

4)main.c

#include <STC89C5xRC.H>
#include "Util.h"
#include "Dri_Timer0.h"
#define T1MS (65536 - FOSC / NT / 1000) // 1MS 倒计时(12T 模式)
#define LED1 P00
void main()
{
    Timer0_Init();
    while (1) {}
    }
    void Timer0_Hander() interrupt 1
{
// 定义静态局部变量
    static unsigned int count = 0;
// 重新赋值脉冲计数器
    TL0 = T1MS;
    TH0 = T1MS >> 8;
// 统计中断次数
    if (count++ >= 500) {
        LED1 = ~LED1;
        count = 0;
    }
}

14.4 定时器封装

为使定时器使用起来更加方便和通用,我们可以将定时器代码进一步封装。

14.4.1 实现思路

封装的思想如下图所示

14.4.2 完整代码

1)Dri_Timer0.h

在 Dri 文件夹中新建 Dri_Timer0.h,内容如下:

#ifndef __DRI_TIMER0_H__
#define __DRI_TIMER0_H__
#include <STC89C5xRC.H>
#include "Util.h"
typedef void (*Timer0_Callback)(void);
#define MAX_CALLBACK_COUNT 4
/**
* @brief 定时器初始化
*
*/
void Dri_Timer0_Init();
/**
* @brief 提供注册入口,用这个函数注册完成的函数,会以 1000Hz 的频率被调用
*
* @return 成功返回 1,失败返回 0
*
*/
bit Dri_Timer0_RegisterCallback(Timer0_Callback);
/**
* @brief 反注册回调函数,反注册的函数不会再被周期调用
*
* @return bit 反注册的结果,成功位 1,失败为 0
*/
bit Dri_Timer0_DeregisterCallback(Timer0_Callback);
#endif

2)Dri_Timer0.c

在 Dri 目录中新建 Dri_Timer0.c,内容如下:

#include "Dri_Timer0.h"
#include <STDIO.H>
#define T1MS (65536 - FOSC / NT / 1000)
static Timer0_Callback s_timer0_callbacks[MAX_CALLBACK_COUNT];
void Dri_Timer0_Init()
{
u8 i;
// 总中断开关
    EA = 1;
// 定时器中断开关
    ET0 = 1;
// 设置定时器 0 的工作模式:16 位定时器
    TMOD &= 0xF0;
    TMOD |= 0x01;
// 设置定时器的初始值
    TL0 = T1MS;
    TH0 = T1MS >> 8;
// 定时器 0 的开关
    TR0 = 1;
    for (i = 0; i < MAX_CALLBACK_COUNT; i++)
    {
    s_timer0_callbacks[i] = NULL;
    }
}
bit Dri_Timer0_RegisterCallback(Timer0_Callback callback)
{
// 判断这个函数有没有被注册过
    u8 i;
    for (i = 0; i < MAX_CALLBACK_COUNT; i++)
    {
        if (s_timer0_callbacks[i] == callback)
        {
// 如果该函数被注册过,直接返回
    return 1;
    }
}
// 注册该函数
    for (i = 0; i < MAX_CALLBACK_COUNT; i++)
    {
        if (s_timer0_callbacks[i] == NULL)
        {
            s_timer0_callbacks[i] = callback;
            return 1;
        }
        }
    return 0;
   }

bit Dri_Timer0_DeregisterCallback(Timer0_Callback callback)
{
    u8 i;
    for ( i = 0; i < MAX_CALLBACK_COUNT; i++)
    {
      if (s_callbacks[i]==callback)
      {
           s_callbacks[i]=callback;
           return 1;
      }
      
    }
   return 0; 
}
void Dri_Timer0_Handler() interrupt 1
{
      u8 i;
      //1.重装初始值
      TL0=64414;
      TH0=64414>>8;

      //2.轮询函数指针数组
      for ( i = 0; i < MAX_CALLBACK_COUNT; i++)
      {
            if (s_callbacks[i]!=NULL)
            {
                  s_callbacks[i]();
            }
            
      }
      
}

3)main.c

#include"Dri_Timer0.h"
#include<STC89C5xRC.H>
#include"Com_Util.h"

void LED_Blink()
{
    static u16 count=0;
    if (count>=500)
    {
        P00=~P00;
        count=0;
    }
}

void main()
{
    Dri_Timer0_Init();
    Dri_Timer0_RegisterCallback(LED_Blink);
    while(1){
    }
}

51单片机学习笔记6 -- 定时器中断 定时器中断属于51单片机3种中断类型其中一种,51单片机具有2个定时器T0和T1(定时器0、定时器1),都需要通过寄存器来配置 阅读详情

相关推荐

day01 51单片机

目前使用的51单片机一般是宏晶STC89系列,这其中流传最广的版本,也是我们课程的主角,就是STC89C52RC。

路小飞 1314

51单片机定时器中断

51单片机定时器中断

FuYu5228的博客 6459

【25年】51单片机从零开始入门 Day1—51单片机基础知识与工程创建

【时间】:2025年10月11日【工具】:淘宝上买的普中51单片机开发板 A2标配,69.5元 == 我发现这个是STC89C52RC,注意这个RC,所以后面选配置的记得选RC的!!!!【个人情况】:本科软件工程、研究生计算机技术,本科学过C,了解一点,研究生没用,忘得差不多了,就记得通用知识学习资料:看B站上 江协科技 视频 + 买单片机送课程,他的课B站上也有,太啰嗦了,感觉送的PDF可以。优快云博主:Zevalin爱灰灰 他发的资料也很有用。

Claire的博客 1239

定时器中断案例(针对51单片机初学者)

定时器中断

Stevendongge的博客 785

基于51单片机的电子时钟设计

1、从DS1302中读取时间显示2、一共4个按键,按键1按下进入修改时间模式,再按下切换修改的时间变量,这个时候第2和3个按键就是修改时间变量的按键,修改完毕后,点击按键4确认修改3、不是修改模式下,按下按键2,可以切换时间和日期的显示4、修改模式下,对应修改的时间变量会闪烁仿真软件:Proteus 8.9代码编写:Keil5百度网盘链接:链接:https://pan.baidu.com/s/1RP_8MkZIqHt7WFPc6na3sQ 提取码:y2fn –来自百度网盘超级会员V4的分享Gitee链接:5

wan1234512的博客 2万+

电路方案分析(十二)USB Type-C PD 移动电源参考设计方案

TPD8S300为USB Type-C连接器的CC1,CC2,SBU1和SBU2引脚集成了四个通道的20v短到vbus和过压保护。TPD8S300集成了八个IEC61000-4-2ESD保护通道,用于USB Type-C连接器的CC1、CC2、SBU1、SBU2、DP_T (顶侧D-) 、DM_T (顶侧D-) 、DP_B (底侧D-) 引脚。当电源组是接收器并为其自身的电池充电时,该芯片会对电池充电,而在电源模式期间,该芯片充当DC-DC转换器以生成VBUS。

小幽余生不加糖 2万+

定时器中断方式

定时器中断介绍

m0_58749949的博客 1487

手把手教你用若依WMS搭建企业级仓库管理系统(Vue+Spring Boot实战)

本文提供了一份基于若依框架(RuoYi)快速搭建企业级仓库管理系统(WMS)的实战指南。详细介绍了从环境准备、项目初始化到核心功能模块(如入库流程、库存管理看板)深度定制的全过程,并涵盖Lodop打印集成、移动端PWA适配及生产环境Docker部署等高级主题,帮助开发者高效构建稳定可用的WMS系统。

weixin_29015899的博客 564

10天学会嵌入式技术之51单片机-day-1

手把手入行嵌入式之10天学会51单片机day-1

2301_80748708的博客 1332

数据库实验报告--MySQL

数据库完整版报告--MySQL 包括数据库创建、表的创建、视图以及授权和触发器的创建等内容,全是精华!看完点赞加收藏O(∩_∩)O~。

Mortalz7 4924

昇腾AI处理器Ascend C编程:从C/C++基础到高性能算子开发实战

异构计算是提升AI算力效率的核心技术,通过在CPU之外引入专用处理器(如GPU、NPU)协同工作,实现大规模并行计算。其原理在于将计算密集型任务卸载到专用硬件,利用其高并行架构加速处理。技术价值在于突破传统CPU的算力瓶颈,为深度学习训练与推理提供强大动力,广泛应用于模型部署、科学计算和高性能计算场景。本文聚焦昇腾AI处理器的原生编程语言Ascend C,它基于C/C++标准扩展,通过显式内存管理和任务并行模型,充分发挥达芬奇架构中Cube与Vector单元的性能。针对CANN算子开发,文章详解了从环境搭建

weixin_34411563的博客 366

10天学会嵌入式技术之51单片机-day-8

手把手入行嵌入式之10天学会51单片机day-8

2301_80748708的博客 2210

合成生物学中试:花钱只是开始,烧钱才是常态

2026年合成生物学行业面临严峻产业化挑战:多家企业终止发酵项目或延期投产,显示从实验室到工厂的转化困境。核心问题并非基因合成成本,而是工艺放大难题——67%项目在中试阶段因工艺问题失败。AI辅助无法替代工程经验,菌株-配方-工艺的三元适配需要长期数据积累。中试成本惊人,涉及设备折旧、原料消耗和稀缺工艺人才,而行业普遍回避讨论这些工程现实,导致认知偏差。建议创业者提前布局中试,将其视为核心竞争力而非简单成本项。合成生物学的真正瓶颈在于工程化能力,这需要时间沉淀而非技术叙事。

AIexander的博客 942

10天学会嵌入式技术之51单片机-day-7

手把手入行嵌入式之10天学会51单片机day-7

2301_80748708的博客 1339

基于Arduino与Velostat的智能鞋垫:DIY足底压力监测系统全解析

压力传感器是物联网和健康监测领域的基础元件,其核心原理是将物理压力转换为可测量的电信号。通过压阻效应,材料的电阻值随压力变化,从而实现压力感知。这项技术为低成本、定制化的健康监测方案提供了可能,尤其在运动分析和康复训练中具有重要价值。本文聚焦于利用Velostat压敏材料和Arduino平台,详细解析如何从传感器制作、信号调理到无线数据传输,构建一套完整的足底压力监测系统。文中深入探讨了传感器阵列构建、信号滤波等关键技术,并针对常见问题提供了实用的解决方案,为创客和开发者实现可穿戴健康监测设备提供了清晰的工

weixin_32818781的博客 402

SAP_ABAP_SD_BAPI清单案例教程——销售订单开票_BAPI_BILLINGDOC_CREATEMULTIPLE_VF01_S4版本

SAP BAPI(Business Application Programming Interface)是SAP系统中的一组规范和标准,用于从SAP系统中获取数据、输入数据和更新数据。这些API允许开发者以编程方式与SAP系统交互,而无需编写大量的自定义代码。2.1 Copy代码 直接可使用。2.2 VF01开票。

java_zhong1990的专栏 2214

10天学会嵌入式技术之51单片机-day-3

手把手入行嵌入式之10天学会51单片机day-3

2301_80748708的博客 1393

开关电源和线性电源Multisim电路仿真实验汇总——硬件工程师笔记

本文系统介绍了稳压电源的基础知识与应用实验。首先阐述了稳压电源的定义与类型,包括线性稳压电源(如LM7805/7905)和开关稳压电源(降压/升压/升降压式)的工作原理、参数特点及优劣势。随后详细讲解了各类稳压电源的实验设计,如线性稳压电源的电路实现、开关稳压电源的PWM控制方法等。最后汇总了硬件工程师相关的笔试面试资源,涵盖器件知识、电路仿真、企业真题等内容。全文结合理论分析与Multisim仿真,为电子工程学习者提供了稳压电源的实用技术参考。

XU157303764的博客 1640

十天学会嵌入式技术之51单片机—day-10

手把手入行嵌入式之10天学会51单片机day-10

2301_80748708的博客 2477

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

10天学会嵌入式技术之51单片机-day-2

手把手入行嵌入式之10天学会51单片机day-2

2301_80748708的博客 705

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

十天学会嵌入式技术之51单片机—day-9

手把手入行嵌入式之10天学会51单片机day-9

2301_80748708的博客 1148

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

嵌入式—51单片机day2

通用输入输出,是与外界交互最基本的形式,可以独立的将 引脚配置为输入模式/输出模式输出模式:控制引脚输出高电平低电平(给定控制信号)开漏输出推挽输出复用开漏复用推挽输入模式:检测引脚的电平(接收外部信号)上拉输入下拉输入浮空输入模拟输入独立按键原理图工作原理:当按键未被按下时,引脚会呈现高电平,当按键被按下时,会造成引脚和GND短路到一起,此时对应的引脚会呈现低电平。判断按键是否被按下,只需要判断引脚是否为低电平即可中断概念当CPU。

2301_77373031的博客 898

自学嵌入式 day40 51单片机

51单片机、MCU、CPU、MPU、位运算、keil程序编写流程

2301_81142331的博客 1366

嵌入式软件--51单片机 DAY 2

我们可以通过阴极控制显示的位置,通过阳极控制显示的内容。两个数码管共有8个阴极引脚和16和阳极引脚,如果所有引脚都直接接入MCU,会造成MCU引脚的极大浪费。为了节省MCU的引脚,我们可以将两个数码管的阳极接在一起。如此我们就有了8个阴极,8个阳极16个引脚。我们只需通过8个GPIO引脚就能控制这8位数码管的显示内容了。既然是八位,我们很快想到了38译码器,通过三位二进制数字的输入控制八种结果。

zx18831955136的博客 1919

51单片机学习记录(Day1-Day2)

51单片机学习记录

weixin_43240212的博客 764

嵌入式开发学习日志(硬件学习——51单片机Day1)

在数字电路中,用来存放二进制数据或代码的电路称为寄存器。

qq_63203532的博客 1038
上一篇: 10天学会嵌入式技术之51单片机-day-4
下一篇: 10天学会嵌入式技术之51单片机-day-6
昊昊昊昊昊明
博客等级 码龄3年 285粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值