串口状态机,这东西很好用啊

以前并没有发现串口状态机的好处,以至于忘记了到底怎么用到底是干什么的,最近用到了这种指定格式的数据包解析,才发现这东西非常的好用,可以增加数据传输的鲁棒性,可以对串口的数据包进行过滤只解出符合协议的数据包。这个呢其实就是一种思想,不仅仅局限于串口之间的数据传输,我认为可以用在很多指定数据协议的数据包传输解析当中。大致代码思想写在下面,希望对大家有帮助。

/*
   主要的变量声明在这边
/* 串口状态机宏 */
#define DATA_HEAD  3
#define DATA_LEN   4
#define DATA_COM   5
#define DATA_NUM   6
#define DATA_CRC   7
#define DATA_TAIL  8
#define DATA_ADD   9

#define COMMAND_SIZE 20

int g_count = 0;             //状态机缓冲区下标
int g_uart_state = DATA_HEAD;//串口状态机状态标志
unsigned char data;          //串口数据
                             //状态机缓冲区
unsigned char command_buf[COMMAND_SIZE] = {0};
unsigned char *bufptr = &data;

while (1)
{
    /* 从串口中一次只读取一个字符 */
    retv = read(fd, bufptr, 1);
    if (-1 == retv)
    {
        printf("read error!\n");
        exit(1);
    }

    /* 
       ---------------- 串口状态机-----------------
       数据包格式
       BYTE     |  BYTE   |  BYTE  |  BYTE  |   BYTE
       包头          长度       命令       数据       包尾
    */
    switch (g_uart_state)
    {
        /* 查找包头状态 */
        case DATA_HEAD:
        {
            /* 找到包头 */
            if (data == 包头)
            {
                /* 将包头存入指令数组 */
                command_buf[g_count++] = data;
                /* 改变串口状态机状态为长度 */
                g_uart_state = DATA_LEN;
            }
            else
            {
                //包头匹配错误
                g_count = 0;
            }
            break;
        }
        /* 检查数据长度 */
        case DATA_LEN:
        {
            if (data == 长度)
            {
                //长度匹配
                command_buf[g_count++] = data;
                //改变状态机的状态为命令
                g_uart_state = DATA_COM;
            }
            else
            {
                //长度匹配错误
                g_count = 0;
                //改变状态机的状态为包头
                g_uart_state = DATA_HEAD;
            }
            break;
        }
        /* 检查命令是否合法 */
        case DATA_COM:
        {
            if (data == 命令)
            {
                //合法存入
                command_buf[g_count++] = data;
                //改变状态机的状态为数据
                g_uart_state = DATA_NUM;
            }
            else
            {
                //不合法改变状态机状态为包头
                g_count = 0;
                g_uart_state = DATA_HEAD;
            }
            break;
        }
        /* 检查数据是否合法 */
        case DATA_NUM:
        {
            if (data是合法的数据)
            {
                //合法存入
                command_buf[g_count++] = data;
                //改变状态机的状态为包尾
                g_uart_state = DATA_TAIL;
            }
            else
            {
                //不合法改变状态机状态为包头
                g_count = 0;
                g_uart_state = DATA_HEAD;
            }
            break;
        }
        /* 检查包尾*/
        case DATA_TAIL:
        {
            if (data == 包尾)
            {
                command_buf[g_count++] = data;
                //成功的解析到一个完整的符合传输协议的串口数据
            }
            /* 完成一次数据包的解析读取 */
	        g_count = 0;
	        g_uart_state = DATA_HEAD;
            break;
        }
        default:
        {
            g_count = 0;
            g_uart_state = DATA_HEAD;
            memset(command_buf, '\0', sizeof(command_buf));
        }
    }
}
  • 14
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
1.首先是蓝牙APP, 易安卓编的,说编其实我只是修改了其中的一些内容,主要的部分都是易锦老师视频里的那个软件,不过我已经懂得了那些命令,(后面有工程文件,如果不 懂,可以去找易锦老师的视频来看,如果找不到,我这存的有),两张界面和代码截图,非常简单,功能也很简单,程序前后修改了两次主要地方,主要原因是测试 的时候发现第一种程序出现错误,在单片机哪里仔细说明! 操作界面,很简单,打开之后打开蓝牙,然后点击搜索设备,找到你的模块名字,点击之后就可以连接了,连接之后下面显示蓝牙的名称和地址信息 2.单片机程序,这个程序也很简单,只要学过一些单片机程序的人应该都知道吧,串口通信,设置好通信的波特率,初始化工作做好,然后在串口中断程序里上你要做的事情就可 以了,这里虽然说11.0592的晶振定时器初值为fd,但是如果用12m的晶振也是可以的,差距不多,没有问题。(说的不怎么专业,我也不是很专业的 人,所以请大神误喷,见笑了!)这里是修改前后的程序不一样的地方,前面的程序是单片机没接收到数据之后读取前一次的IO状态,然后改变其状态,但是测试 的时候发现读取状态有错误,估计是我的电路有问题,第一个继电器可以正常工作,第二个和第三个都有问题,当第一个关闭的时候可以打开,但是当打开的了却不 能关闭,只能用关闭所有的命令来关闭,(找了一下午也没发现问题,元件换了几个都没找到,后来放弃了),后来就换了后面程序,直接发送状态命令,不用判断 当前的状态了,我觉得后面这种可能更好!而且实际测试的时候也可以,没有问题。(补充一下,我发现12M的晶振不能用11.0592M的数据,原因是定时 器计数产生的波特率与9600差距有点大,误差到达了8.5%左右,理论上误差要小于4%才能正常通信,所以通信有错误,虽然能通信,但是数据不对,后来 我把晶振换回来就可以了,看来要实践才知道真理。) 第 一、二张是修改之前的程序,有问题,最后一张是修改之后的,没有问题,后来仔细想了一下,后面一种才是正确的,前面一种的改变状态可能出现错误,就是手 机上显示的开关是关的,然而实际电路中的电路是开着的(这也是没有数据回传的原因吧,现在只是单向的手机发,模块接的形式,以后再研究)!,但是后面一种 不出现这个问题! 3.实物电路连接,我也是在测试,所以先用LED 等来代替继电器输出,然后才用到继电器上面。单片机直接放在我做的最小系统版上面,然后用导线来连接到蓝牙开关的小板子上,等测试无误之后再安装在上面, 不然不好程序上去。输出接的是一个小电机,用的一个12v蓄电池代替220V电源,如果要用220V的电源,要注意安全了!提醒一下,绝缘一定要做好, 毕竟不是开玩笑的。简单说一下电路连接,首先你得需要焊接一个51单片机最小系统板,(如果这个都不,那你需要先学习一下,不然肯定是没办法做的)然后是由三极管驱动继电器的电路,记得加二极管,不然三极管很有几率被击穿,最后是蓝牙模块与单片机的连接,电源接好,一般蓝牙模块都是宽电压的,所以直接接到5V电源上,与单片机共用电源,不用什么电压转换,很方便的,把蓝牙模块的TX与单片机的RX连接,就是P3.0那个引脚,RX接单片机的TX,就是P3.1那个引脚,至于继电器哪里你需要接成常开还是常闭的模式就你自己决定了,当然还要加一点录滤波的,因为继电器启动的一瞬间电流很大,担心是单片机死机!这些就是主要的东西了!) 前一张是之前测试用的,后面一张是后来直接把单片机装上去的,看着没有那么乱了,可以看到,当手机上的开关23打开时,电路板上的灯23也是两的,表明继电器已经被打开了。 4.打完收工,作品完成好 了至此最简单的蓝牙开关就做好了,可以躺在床上遥控在远处的风扇了(好吧你们都用的是空调,当我没说!),定时关机(这个功能没做,不过原理都一样,自由 发挥了),其他神马的!感兴趣的同学可以试一下,比如说高级一点的外网控制的,把电脑作为服务器,把蓝牙模块接好,和控制器连接起来,然后让手机与电脑通 过互联网通信,用手机给电脑发送指令,再通过电脑给蓝牙模块发送指令,比如提前开个空调什么的(提前开风扇没用,还是开你们的空调吧),然后其他什么的东 西就自己发挥了!我想这个应该是属于传说中的物联网吧,虽然没有那么高大上,但是原理是一样的。
很基础的东西,高手可以忽略了! 目 录 第1 章 计算机基础知识................................ 1 1.1 计算机发展概况.................................... 1 1.1.1 微处理器和微机的发展............. 1 1.1.2 微机的分类................................ 3 1.2 微机系统................................................ 4 1.2.1 微机硬件.................................... 5 1.2.2 微机软件.................................... 5 1.2.3 硬件与软件的关系..................... 7 1.3 计算机中的数制及其转换..................... 7 1.3.1 数与数制.................................... 7 1.3.2 数制转换.................................... 9 1.4 计算机中数的表示方法....................... 10 1.4.1 机器数与真值........................... 10 1.4.2 原码、反码、补码................... 11 1.4.3 补码的运算规则 与溢出判断 .............................. 12 1.4.4 计算机中常用的编码............... 13 1.5 微机的主要性能指标和应用............... 16 1.5.1 微机的主要性能指标............... 16 1.5.2 微机的应用.............................. 17 1.6 小结...................................................... 19 1.7 习题...................................................... 19 第 2 章 80X86 微处理器内部结构............ 21 2.1 微处理器的功能结构........................... 21 2.1.1 微处理器的典型结构............... 21 2.1.2 8086/8088 CPU 的内部结构.............................. 23 2.1.3 8086/8088 CPU 的寄存器结构........................... 24 2.2 8086/8088 存储器组织及其寻址......... 26 2.2.1 存储单元的地址和内容........... 26 2.2.2 存储器的结构及访问............... 26 2.2.3 存储器地址的分段................... 27 2.3 8086/8088 I/O 地址空间...................... 28 2.4 高档微处理器.......................................29 2.4.1 80286 微处理器........................29 2.4.2 80386 微处理器........................30 2.4.3 80486 微处理器........................31 2.4.4 Pentium 系列微处理器.............32 2.5 小结......................................................36 2.6 习题......................................................36 第 3 章 指令系统与寻址方式.....................38 3.1 寻址方式..............................................38 3.1.1 操作数类型...............................38 3.1.2 8086/8088 寻址方式.................38 3.2 指令系统..............................................44 3.2.1 数据传送指令.............
《单片机原理及应用》 课程设计报告 2010 — 2011 学年第 2 学期 题 目: 简易十字路口交通灯设计 专 业: 通信技术 班 级: 通信1102 学 号: 1007045149 学 号: 6 姓 名: 曾靖凯 指导教师: 卫兵哥 "2012 "年"12 "月"13-17 "日" 简易十字路口交通灯设计 一、设计目的 1.了解交通灯管理的基本工作原理 2.掌握80C31工作原理和应用编程 3.掌握80C31计算器/定时器的工作方式和应用编程外部中断的方式 4.掌握动态LED显示 二、设计内容 内容:设计一个十字路口交通灯控制器。初始态东西南北等全灭,程序开始运行先南 北通行30S、东西禁止;然后,南北转黄灯;接着,东西通行30S,南北禁止;最后,东 西转黄灯;依次循环。如果有意外发生,产生中断,红灯全亮,时间10S. 三、总体设计 本设计采以用单片机8051作为控制器,通行时间或等待时间通过数码管以倒计时方式 显示,同时单片机P1口控制交通灯(红灯、黄灯、绿灯)的正常的替换工作,如果有意 外发生(交通事故)就产生中断,东西南北红灯全亮。系统设计框图1如下: 图1 系统框图 四、硬件设计 因才用了PC机和单片机试验箱接口应用平台硬件电路相对简单,利用8031的P1口对 交通灯的控制、计数/定时器、中断和数码管显示构成的简易交通灯,实验电路连接如表 1所示。 表1 实验连接图 "连线 "连接孔1 "连接孔2 " "1 "P7 "L7(东西红灯)" "2 "P6 "L6(东西黄灯)" " 3 "P5 "L5 (东西绿灯) " "4 "P4 "L4 (南北红灯) " "5 "P3 "L3(南北黄灯)" "6 "P2 "L2(南北绿灯)" "7 "P3.2 "负脉冲 " "8 "KEY/LED_CS"CS0 " 五、软件设计 1.交通灯显示时序的理论分析 以下四图所示为红黄绿灯规则的状态图 图2 状态S1南北通行30S 东西禁止 图3 状态S2南北转黄灯 图4 状态S3南北禁止 东西通行30S 图5 状态S4东西绿灯转黄灯 共四种状态,分别设定为S1、S2、S3、S42,交通灯以这四种状态为一个周期,循环 执行如图6所示。如果有意外发生,去处理中断,红灯全亮,时间10S。 图6 交通灯状态循环 依据上述车辆行驶的状态图,可以列出各个路口灯的逻辑表如表1所示(其中逻辑值"1" 代表执行通行,逻辑值"0"代表禁止通行,逻辑值"L"代表绿灯转黄灯): 表2 状态逻辑表 "S1的状态 "E "S "W "N " "逻辑值 "0 "1 "0 "1 " "显示时间 "30S " "S2的状态 "E "S "W "N " "逻辑值 "0 "L "0 "L " "显示时间 "1S " "S3的状态 "E "S "W "N " "逻辑值 "1 "0 "1 "0 " "显示时间 "30S " "S4的状态 "E "S "W "N " "逻辑值 "L "0 "L "0 " "显示时间 "1S " 程序就是上述四种状态下循环转化的,一个周期四个状态,正常情况下共花费63S。 2交通灯显示的理论分析 2.1 倒计时显示的理论分析 利用MCS- 51内部的定时器/计数器进行,配合软件延时实现倒计时。在工作之前必须通过软件设定 它的工作方式,即对寄存器TMOD中每位进行设定,格式如表3所示。 表3 TMOD格式 D7 D6 D5 D4 D3 D2 D1 D0 "CATE"C/T "M1 "M0 "CATE "C/T "M1 "M0 " 其中,低四位用于决定T0的工作方式,高四位用于决定T1的工作方式,M1 和M0 工作方式控制位用以确定 4 种工作方式,如下表4所示: 表4 M1和M0控制4种工作方式 "M1 M0 "工作方式 "说明 " "0 0 "方式0 "13位计数器 " " 0 1 "方式1 "16位计数器 " "1 0 "方式2 "自动装载8位计数器 " "1 1 "方式3 "定时器0:分为两个8位计数器 " " " "定时器1:对外部停止计数 " 采用T0方式1,定时1S,系统时钟为6MHZ,所以时钟周期=(12*1/6)us=2us;采用每隔 100ms中断一次,中断10次为1S,使时间的计数值减1,实现了倒计时的功能。计算计数 初值X:(216-X)*2us=1s,所以X=15536=3CB0H,因此TH0=3CH,TL0=B0H。 2.2 状态灯显示的理论分析 南北通行,东西禁止时利用定时器中断倒计时30S;东西通行,南北禁止时利用定时 器中断倒计时30S。 2.3 中断理论分析 MCS- 51中断系统有5个中断源,分别是外部中断0、外部中断1、定时器/计数器T0溢出中断、 定时器/计数器T1溢出中断、串行口中断请求。 MCS- 51的
作者:祁星晨 概述《战争雷霆》提供了一个非常详细和个性化的载具驾驶体验,使玩家可以驾驶数千种不同型号的海陆空载具,在空战模式,模拟真实物理环境状态下的飞行参数是需要及时获取的,PC端界面的局限性,不便直观的查看,因此萌发了利用ART-PI制作一款可方便查看飞行时仪表数据外设的兴趣。 开发环境硬件:ART-PI和4.3寸800x480电容触摸屏 RT-Thread版本:RTT-nano 3.1.3 开发工具及版本:MDK v5.33 CubeMX v6.1.0 RT-Thread使用情况概述内核部分:调度器,互斥量。 调度器:创建多个线程来实现不同的工作。 互斥量:用来同步线程。 组件部分:无。 软件包部分:无 硬件框架ST-Link串口部分接收来自PC的数据,4.3寸显示TouchGFX UI。 软件框架说明 软件框图 软件流程图 WarThunder数据解析任务负责解析来自PC串口通信的飞行数据,TouchGFX UI任务负责显示数据,Main任务中循环blink板载LED 软件模块说明WarThunder数据解析任务 简单的string.h 解析,自定义格式帧 TouchGFX UI任务均由designer设计 演示效果视频观看: 比赛感悟纸上得来终觉浅,绝知此事要躬行。陆游的这首诗,完美的诠释了我在这次比赛中的收获。 时代的发展,MCU的性能也越来越强,万物互联的需求也愈加强烈,使用RTOS来实现物与网的链接,是时代发展的潮流,通过综合对比,我选择了国人自主的 RT-Thread。 首先要感谢RT-Thread和电路城,帮助我克服了没有时间做东西的困难,以及怎么样用最少的时间做出有意思的东西,结果不重要,比赛的deadline才重要,一定程度上克服了我拖拖拉拉的习惯,比赛过程中,学习到了一是必须要靠自己,靠自己,靠自己,二是多百度,多百度,多百度,三是要仔细,要仔细,要仔细,四是多尝试,多尝试,多尝试,重要的事说三遍。收获了晚上调试的快乐,收获了大佬们的赞,收获了玩游戏和比赛的双重快乐。 通过 RT-Thread官网上的文档中心,我学习了 多线程及其调度、信号量、邮箱、消息队列、内存管理、定时器等,学完之后,有种感觉就是看过了,我都懂,但是感觉把这些都融合不起来,通过这次比赛的项目实践,这些知识点已经全部融贯通,我对RTOS也有了全新的认识。 最后感谢主办方提供了这么好的一个平台,不仅能展示自我,也能学到很多知识,还要感谢论坛上那些解决我问题以及制作软件包的大佬,希望有朝一日我也能给开源社区贡献一份自己力量。
本文根据时下最火小游戏微信跳一跳,编的物理外挂,实现简单,具有DIY精神的都能迅速上手。废话不多说,先来点视频开开胃。 哈哈哈,是不是很爽很刺激,好了,不吊胃口了,还是整点干货吧。 准备1:手机一部,电脑端下载好投屏软件,苹果的airplay,安卓的忘了,自己找下,嘻嘻嘻。。。。 准备2:搞电子的才有,继电器模块一个,随便什么开发版一块,有串口就行,usb转串口模块一个。 准备3:电脑上装上我提供的“跳一跳物理外挂.exe",这个才是核心,后面我贴源码,low不low不要紧,关键好用,我花了一天时间学的,代码拙劣,慎看,/呲牙。 准备工作做完了,现在开始动工,先做物理部分。 首先拿出你的继电器模块,然后把继电器给削了(捂嘴笑)哈哈,我也不知道怎么告诉你怎么削,还是给个图吧。 哎吆我去,这图这么大的咧,将就看看。反正就是把继电器的壳子给拿掉。温馨提醒:用刀的时候注意点,手弄破没事,别把继电器线圈削了(幸灾乐祸的笑呵呵) 然后呢,找个导电的,有电容的,弹簧呀,电容笔呀,或者湿海绵呀。。。一切可以让手机触摸屏反应的材料都行,就是要小一点。 反正我是找了个弹簧,还把它焊在了继电器的活动片上。不的,看图,下面没图,还是上面那张。 硬件部分还差个单片机,这个你们都的,专业的嘛,随便整个单片机最下系统就行,带个串口,协议我告诉你简单。 帧头32位的最高8位后8位后8位后8位 ‘A’00000000 看到没,接收到串口数据后,把除了'A' 之外的四个8位的数据合并成一个32位的数据,这个合并后的数据,就是ms,是多少就是多少ms。 简单吧,单片机只要接收到这组串口数据,就可以进行操作了,(忘了说了波特率115200 ,8,0,1,我想大家都看得懂,不解释了。) 主程序代码如下: if(收到串口发来的数据) { 将4个字节接收到的数据转化为32位的数据; 继电器置1或者置0(看你电路了,让它按下去就行,模拟按下动作); 延时(xx ms);(这就是那个32的数据) 继电器置1或者置0(看你电路了,让它抬起来就行,模拟抬起动作); } 实在不的,也没事,我不是还有程序源码的嘛; 好了好了,硬件就到这了,整点软件的。软件c#的,高手的话,简单,随便你们喷,反正我也不熟,就学了一天,整成这样,自认为还行。 源码,我贴上去,别急。 操作部分。我是鼠标左键点击确定起点位置,鼠标右键点击确定终点位置。也就是说,你想跳,那就鼠标左键点起点,鼠标右键点终点。根据距离计算时间。软件上,有个系数,用来确定不同电脑,不同分辨率的,自己调试下, 一致就行。截图截图,看图看图。 先打开这个软件,苹果的airplay,然后打开手机,选择airplay镜像。然后将软件全屏。 打开我的那个"跳一跳物理外挂.exe", 选择串口后,就点连接,没啥问题是不有任何提示的。有问题就报错了。(哈哈哈,仰天长啸中) 下面这个框 3.5,这个就是系数了,要将我的这个软件和投上去的界面重合,这样才行。然后你试试鼠标左键,鼠标右键,看看你的继电器动。(不动就是你程序有问题,硬件有问题,电脑有问题,反正我的是好的,我不管,自己检查) 还有就是,这个软件是由两个窗体组成的,一个透明的,一个透明有边框的,别问我为什么,因为我不知道如何设置透明鼠标不穿透,你也不知道呀,哈哈哈(鬼畜中),的私信我,我学一下。所以,如果点击的时候触发这个软件后面的东西,那么请点击任务栏中,将窗体设置到最前,其实就是获取热点了,其实就是激活窗口啦,笨呢,点不到说明窗口不在激活状态嘛。 好了,不说了, 下面都是图了,你们自己玩吧。 啰嗦一句,把框框对齐哟,不然跳不准呢。
首先,我们需要定义串口的波特率、数据位、停止位和校验位等参数。然后,我们可以使用状态机来实现串口的收发功能。 以下是一个基于VHDL的串口状态机的实现: ```vhdl library ieee; use ieee.std_logic_1164.all; entity uart_rx is port ( clk: in std_logic; reset: in std_logic; rx: in std_logic; data: out std_logic_vector(7 downto 0); valid: out std_logic ); end entity; architecture rtl of uart_rx is -- 定义状态机的状态 type state_type is (IDLE, START, BITS, STOP, PARITY, VALID); signal state: state_type; -- 定义计数器和寄存器 signal cnt: integer range 0 to 15 := 0; signal reg: std_logic_vector(7 downto 0); begin -- 状态机的行为 process (clk, reset) begin if reset = '1' then state <= IDLE; cnt <= 0; reg <= (others => '0'); valid <= '0'; elsif rising_edge(clk) then case state is when IDLE => if rx = '0' then state <= START; cnt <= 0; reg <= (others => '0'); end if; when START => if cnt = 0 then if rx = '0' then cnt <= cnt + 1; else state <= IDLE; end if; else state <= BITS; end if; when BITS => if cnt < 8 then reg(cnt) <= rx; cnt <= cnt + 1; else state <= PARITY; end if; when PARITY => if cnt = 8 then cnt <= cnt + 1; else if cnt = 9 then state <= STOP; else if rx = '0' then reg(cnt-1) <= '1'; else reg(cnt-1) <= '0'; end if; cnt <= cnt + 1; end if; end if; when STOP => if cnt = 10 then state <= VALID; else state <= IDLE; end if; when VALID => data <= reg; valid <= '1'; state <= IDLE; end case; end if; end process; end architecture; ``` 该状态机包含以下状态: - IDLE:空闲状态,等待接收到起始位。 - START:接收到起始位后,开始接收数据位。 - BITS:接收数据位。 - PARITY:接收校验位。 - STOP:接收停止位。 - VALID:接收到完整的数据帧,输出数据和有效信号。 该状态机使用计数器和寄存器来存储接收到的数据。当接收到完整的数据帧时,将数据和有效信号输出。在接收过程中,如果接收到错误的数据,则重新回到空闲状态等待下一帧的接收。 需要注意的是,该状态机仅实现了串口的接收功能。如果需要实现串口的发送功能,可以采用类似的状态机设计,并在相应的状态下输出发送的数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zxnsirius

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

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

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

打赏作者

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

抵扣说明:

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

余额充值