单片机教学课件-第10章--单片机的C语言编程.ppt_第1页
单片机教学课件-第10章--单片机的C语言编程.ppt_第2页
单片机教学课件-第10章--单片机的C语言编程.ppt_第3页
单片机教学课件-第10章--单片机的C语言编程.ppt_第4页
单片机教学课件-第10章--单片机的C语言编程.ppt_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第10章单片机的C语言编程,单片机原理、接口及应用,内容提要,C51程序结构C51的数据类型数据的存贮类型和存贮模式C51对SFR、可寻址位、存储器和I/O口的定义C51的运算符函数C语言编程实例单片机资源的C语言编程实例汇编语言和C语言的混合编程C语言函数库的管理与使用小结,51系列单片机支持三种高级语言,即PL/M,C和BASIC。8052单片机内固化有解释BASIC语言,BASIC语言适用于简单编程而对编程效率运行速度要求不高的场合;PL/M是一种结构化的语言,很象PASCAL,PL/M编译器好象汇编器一样产生紧凑的机器代码,可以说是高级汇编语言,但它不支持复杂的算术运算,无丰富库函数支持,学习PL/M无异于学习一种新的语言。C语言是一种通用的程序设计语言,其代码效率高,数据类型及运算符丰富,并具有良好的程序结构,适用于各种应用程序的设计,是目前使用较广的单片机编程语言。,单片机的C语言采用C51编译器(简称C51)。由C51产生的目标代码短、运行速度高、所需存储空间小、符合C语言的ANSI标准,生成的代码遵循Intel目标文件格式,而且可与A51汇编语言或PL/M51语言目标代码混和使用。,应用C51编程具有以下优点:(1)由C51管理内部寄存器和存贮器的分配,编程时,无需考虑不同存储器的寻址和数据类型等细节问题;()程序由若干函数组成,具有良好的模块化结构;()有丰富的子程序库可直接引用,从而大大减少用户编程的工作量。()C语言和汇编语言可以交叉使用.汇编语言程序代码短、运行速度快、但复杂运算编程耗时。如果用汇编语言编写与硬件有关的部分程序,用C语言编写与硬件无关的运算部分程序,充分发挥两种语言的长处,可以提高开发效率。,10.1C51程序结构,同标准C一样,C51的程序由一个个函数组成,这里的函数和其它语言的“子程序”或“过程”具有相同的意义。其中必须有一个主函数main(),程序的执行从main()函数开始,调用其它函数后返回主函数main(),最后在主函数中结束整个程序而不管函数的排列顺序如何。,C语言程序的组成结构如下所示:,全局变量说明/*可被各函数引用*/main()/*主函数*/局部变量说明/*只在本函数引用*/执行语句(包括函数调用语句)fun1(形式参数表)/*函数1*/形式参数说明,局部变量说明执行语句(包括调用其他函数语句)funn(形式参数表)/*函数n*/形式参数说明局部变量说明执行语句,C语言的语法规则:1.每个变量必须先说明后引用,变量名英文大小写是有差别的。2.C语言程序一行可以书写多条语句,但每个语句必须以“;”结尾,一个语句也可以多行书写。3.C语言的注释用/*/表示。4.“”花括号必须成对,位置随意,可紧挨函数名之后,也可另起一行,多个花括号可以同行书写,也可逐行书写,为层次分明,增加可读性,同一层的“”花括号对齐,采用逐层缩进方式书写。,10.2C51的数据类型,C51的数据有常量和变量之分。常量在程序运行中其值不变的量,可以为字符,十进制数或十六进制数(用0 x表示)。常量分为数值型常量和符号型常量,如果是符号型常量,需用宏定义指令(#define)对其进行定义(相当于汇编语言中的“EQU”伪指令)如:#definePI3.1415那么,程序中只要出现PI的地方,编译程序都将其翻译为3.1415。变量在程序运行中其值可以改变的量。一个变量由变量名和变量值构成,变量名即存贮单元地址的符号表示,而变量的值就是该单元存放的内容。定义一个变量,编译系统就会自动为它安排一个存贮单元,具体的地址值用户不必在意。,10.2.1C51变量的数据类型,无论哪种数据都是存放在存贮单元中的,每一个数据究竟要占用几个单元(即数据的长度)都要提供给编译系统,正如汇编语言中存放数据的单元要用DB或DW伪指令进行定义一样,编译系统以此为根据预留存贮单元,这就是定义数据类型的意义.C51编译器支持数据类型见表10.1。,表10-1C51的数据类型,对表10.1作如下说明:1.字符型(char)、整型(int)和长整型(long)均有符号型(signed)和无符号型(unsigned)两种,如果不是必须,尽可能选择unsigned型,这将会使编译器省却符号位的检测,使生成的程序代码比signed类型短得多。2.程序编译时,C51编译器会自动进行类型转换,例如将一个位变量赋值给一个整型变量时,位型值自动转换为整型值;当运算符两边为不同类型的数据时,编译器先将低级的数据类型转换为较高级的数据类型,运算后,运算结果为高级数据类型。3.51单片机内部数据存贮器的可寻址位(20H2FH)定义为bit型,而特殊功能寄存器的可寻址位(即地址为X0H和X8H的SFR的各位)只能定义为sbit类型。,10.2.2关于指针型数据,(1)关于指针型变量在汇编语言程序中,要取存贮单元m的内容可用直接寻址方式,也可用寄存器间接寻址方式,如果用R1寄存器指示m的地址,用R1取m单元的内容。相对应的在C语言中用变量名表示取变量的值(相当于直接寻址),也可用另一个变量(如P)存放m的地址,P就相当于R1寄存器。用*P取得m单元的内容(相当于汇编的间接寻址方式),这里的P即为指针型变量。下面表格表示两种语言将m单元的内容送n单元的对照语句。,注:上表省略了汇编语言程序中对符号地址n和m用EQU伪指令进行具体地址定义的语句以及C语言对变量n、m和指针变量P进行类型定义的语句,实际程序设计中,此步是不可缺少的。表中=(相等);!=(不相等)优先级:前四个高,后二个(“=”和“!=”)级别低。,4C51的逻辑运算符有三种:逻辑表达式和关系表达式的值相同,以0代表假,以1代表真。以上三种运算的优先级见图10.1。5C51的按位操作的运算符有六种:intc;c=a+b;return(c);main()intd,0u=3,v=2;d=2*fun(u,v);上例被调函数在主调函数前,不用说明。,intfun1(a,b);main()intd,u=3,v=2;d=2*fun1(u,v);intfun1(a,b)inta,b;intc;c=a+b;return(c);上例中被调函数在主调函数后,在前面应对被调函数进行说明。,10.7C语言编程实例,为了使C语言的编程方法和汇编语言的编程方法有一个对比,本节采用3.1节的例题。由于C51编译器是针对单片机的,因此ANSIC中的scanf和printf等对PC电脑的键盘和监视器的输入、输出语句无效。运算的数据可以通过变量置入或取出,这时C51会自动安排使用的存贮单元。当然用户也可以自行通过具体的内存地址置入数据或从特定地址取出数据,这就少不了要去观察具体地址的内容或改变其地址的内容,C语言的编程上机调试见本教材的实验部分。下面通过一个例子说明C语言程序编译后生成的机器代码及对应的反汇编程序,从中引出一些道理。,10.7.1顺序程序的设计,例105完成1980524503的编程分析:两个乘数都比较大,其积更大,采用unsignedlong类型,设乘积存放在外部数据存储器0号开始的单元。程序如下:main()unsignedlongxdata*p;/*设定指针p指向类型为unsignedlong的外部RAM区,每个变量占4字节*/unsignedlonga=19805;/*设置a为unsignedlong类型,并赋初值*/unsignedlongb=24503,c;/*设置b和c(积)为unsignedlong类型,并赋初值*/p=0;/*使指针指向0号单元*/c=a*b;*p=c;/*积存入外部RAM0号单元*/,上机通过WAVE软件仿真调试,在变量观察窗口看到运算结果c=485281915,即为乘积的十进制数。观察XDATA区(外部RAM)的0000H0003H单元分别为1CECD07B,即存放的为乘积的十六进制数。观察DATA区(内部RAM区):地址0405060708090A0B0C0D0E0F1CECD07B00004D5D00005FB7C变量(积)a变量b变量可见定义为unsignedlong类型,给每个变量分配四个单元,如果定义类型不对,将得不到正确的结果。对于复杂的运算通常采用查表的方法。如同汇编程序设计一样,在程序存贮器建立一张表,在C语言中表格定义为数组,表内数据(元素)的偏移量表现为下标。数组的使用如同变量一样,要先进行定义,如说明数组名、维数、数据类型和存贮类型。在定义数组的同时,还可以给数组各元素赋初值。通过下例说明C51数组的定义方法和用C语言编写查表程序的方法。,例106片内RAM20H单元存放着一个00H05H的数,用查表法,求出该数的平方值放入内部RAM21H单元。main()charx,*p;charcodetab6=0,1,4,9,16,25;p=0 x20;x=tab*p;p+;*p=x;/*把x赋给指针变量p所指向的那个变量*/,10.7.2循环程序的设计,C语言的循环语句有以下几种形式1.while(表达式)语句;其中,表达式为循环条件,语句为循环体,当表达式值为真(值为非0),重复执行“语句”。语句可以只有一条,以“;”结尾;也可以多条组成复合语句,复合语句必须用括起;也可以没有语句,通常用于等待中断,或查询。表达式为假,执行下一条语句。2.do语句;while(表达式);表达式为真,执行循环体“语句”,直至表达式为假,退出循环,执行下一条语句。3.for(表达式1;表达式2;表达式3)语句;其中,语句为循环体。(执行过程是:执行表达式1,求解表达式2,如表达式2为假,执行下一条语句;如表达式2为真,执行循环体,求解表达式3,再求解表达式2)语句中的表达式可以省略其中任一项甚至全部,但二个分号不可省,如“for(;);”为无限循环;for(i=4;i+)语句,i从4开始无限循环;“for(;i100;);”相当于“while(i100);”。,例10-7while(P1i=10;i+)sum+=i;,10.7.3分支程序的设计,C语言的分支选择语句有以下几种形式:1.if(表达式)语句;若表达式为真,执行语句,否则执行下一条语句。当花括号中的语句多于一条时,花括号不能省。2.if(表达式)语句1;else语句2;若表达式为真,执行语句1,否则,执行语句2。该语句无论哪种情况,执行完后都会执行下一条语句。if语句可以嵌套3.switch(表达式)case常量表达式1:语句1;break;case常量表达式2:语句2;break;case常量表达式n:语句n;break;default:语句n+1;,说明:语句先进行表达式的运算,当表达式的值与某一case后面的常量表达式相等,就执行它后面的语句。当case语句后有break语句时,执行完这一case语句后,跳出switch语句,当case后面无break语句,程序将执行下一条case语句。如果case中常量表达式值和表达式的值都不匹配,就执行default后面的语句。如果无default语句就退出switch语句。default的次序不影响执行的结果,也可无此语句。case语句适于多分支转移的情况下使用。,例10-10片内RAM的20H单元存放一个有符号数x,函数y与x有如下关系式:xx0y=20Hx=0 x+5x0设y存放于21H单元,程序如下main()charx,*p,*y;p=0 x20;y=0 x21;for(;)x=*p;if(x0)*y=x;if(x0)*y=x+5;if(x=0)*y=0 x20;程序中为观察不同数的执行结果,采用了死循环语句for(;),上机调试时,欲退出死循环可用Ctrl+C。,例10-11有两个数a和b,根据R3的内容转向不同的处理子程序:r3=0,执行子程序pr0(完成两数相加)r3=1,执行子程序pr1(完成两数相减)r3=2,执行子程序pr2(完成两数相乘)r3=3,执行子程序pr3(完成两数相除)分析:C语言中的子程序即为函数,因此需编四个处理函数,如果主函数在前,须对子函数进行说明;如果子函数在前,无须对子函数说明,但是无论子、主函数的顺序如何,程序总是从主函数开始执行,执行到调用子函数就会转到子函数执行.在C51编译器中通过头文件reg51.h可以识别特殊功能寄存器,如IE、TMOD、SCON等,但不能识别R0R7通用寄存器,因此R0R7只有通过绝对地址访问识别,程序如下:,#include#definer3DBYTE0 x03intc,c1,a,b;pr0()c=a+b;pr1()c=a-b;pr2()c=a*b;pr3()c=a/b;main()a=90;b=30;,for(;)switch(r3)case0:pr0();break;case1:pr1();break;case2:pr2();break;case3:pr3();break;c1=56;,在上述程序中,为便于调试观察,加了C1=56语句,并使用了死循环语句for(;),用Ctrl+C可退出死循环。,10.8单片机资源的C语言编程实例,例10-12在3.1节曾用汇编语言完成了外部RAM的000EH单元和000FH单元的内容交换,现改用C语言编程。C语言对地址的指示方法可以采用指针变量,也可以引用absacc.h头文件作绝对地址访问,下面采用绝对地址访问方法。#includemain()charc;for(;)c=XBYTE14;XBYTE14=XBYTE15;XBYTE15=c;,程序中为方便反复观察,使用了死循环语句for(;),只要用Ctrl+C即可退出死循环。上面程序通过编译,生成的机器代码和反汇编程序如下:,0000020014LJMP0014H000390000EMOVDPTR,#000EH0006E0MOVXA,DPTR0007FFMOVR7,A0008A3INCDPTR0009E0MOVXA,DPTR000A90000EMOVDPTR,#000EH000DF0MOVXDPTR,A000EA3INCDPTR000FEFMOVA,R70010F0MOVXDPTR,A,001180F0SJMP0003H001322RET0014787FMOVR0,#7FH0016E4CLRA0017F6MOVR0,A0018D8FDDJNZR0,0017H001A758107MOVSP,#07H001D020003LJMP0003H,例中可见:一进入C语言程序,首先执行初始化,将内部RAM的07FH128个单元清零,然后置SP为07H(视变量多少不同,SP置不同值,依程序而定),因此如果要对内部RAM置初值,一定要在执行了一条C语言语句后进行。C语言程序设定的变量,C51自行安排寄存器或存贮器作参数传递区,通常在R0R7(一组或两组,视参数多少定),因此,如果对具体地址置数据,应避开这些R0R7的地址。如果不特别指定变量的存贮类型,通常被安排在内部RAM中。,10.8.2并行口及键盘的C语言编程,例10-13用P1.0输出1KHz和500Hz的音频信号驱动扬声器,作报警信号,要求1KHz信号响100ms,500Hz信号响200ms,交替进行,P1.7接一开关进行控制,当开关合上,响报警信号,当开关断开,报警信号停止,编出程序.分析500Hz信号周期为2ms,信号电平为每1ms变反一次.1KHz信号周期为1ms,信号电平每500s变反一次。用C语言编程如下:,#includesbitP10=P10;sbitP17=P17;main()unsignedchari,j;while(1)while(P17=0)for(i=1;i=200;i+)/*控制音响时间(1KHz)*/P10=P10;for(j=0;j=50;j+);/*延时500us*/for(i=1;i=200;i+)/*控制音响时间(500Hz)*/P10=P10;for(j=0;j=100;j+);/*延时1000us(1ms)*/,例10-14在下图中8XX51接有五个共阴极数码管的动态显示接口电路,开关打向位置“1”时,显示“12345”字样,当开关打向“2”时,显示HELLO字样,C语言编程程序清单如下。,图10-7接五个共阴极数码管的动态显示接口,用C语言完成上述功能编程#include#defineuintunsignedint#defineucharunsignedcharSbitP17=P17;main()ucharcodetab15=0 x86,0 xdb,0 xcf,0 xe6,0 xed;/*“15”的字形码,因P1.7接的开关,最高位送的“1”,以保证输入正确*/ucharcodetab25=0 xf8,0 xf9,0 xb8,0 xb8,0 x,bf;/*“HELLO”的段码,因P1.7接的开关,最高位送的“1”,以保证输入正确*/uchari;uintj;While(1)p3=0 x01;for(i=0;i5;i+)if(p17=1)P1=tab1i;elseP1=tab2i;for(j=0;j=25000;j+);P30;i-),图10-844矩阵键盘,ucharkbscan(void)/*键盘扫描函数*/ucharsccode,recode;P1=0 xf0;/*P1.0P1.3发全0,P1.4P1.7输入*/if(P1,10.8.3C51中断程序的编制,C51使用户能编写高效的中断服务程序,编译器在规定的中断源的矢量地址中放入无条件转移指令,使CPU响应中断后自动地从矢量地址跳转到中断服务程序的实际地址,而无需用户去安排。中断服务程序定义为函数,函数的完整定义如下:返回值类型函数名(参数)模式再入interruptnusingm其中interruptn为必选项,它表示将函数声明为中断服务函数,n为中断源编号,可以是031间的整数,不允许是带运算符的表达式,n通常取以下值:0外部中断0;1定时器/计数器0溢出中断2外部中断1;3定时器/计数器1溢出中断4串行口发送与接收中断5定时器/计数器2中断,各可选项的意义如下:usingm定义函数使用的当前工作寄存器组,m的取值范围为03,可缺省。它对目标代码的影响是:中断函数入口处将当前寄存器保存,使用m所指定的寄存器组,函数退出时原寄存器组恢复。选不同的工作寄存器组,可方便实现寄存器组的现场保护。再入属性关键字reentrant将函数定义为再入的,在C51中,普通函数(非再入的)不能递归调用,只有再入函数才可被递归调用。中断服务函数不允许用于外部函数,它对目标代码影响如下:当调用函数时,SFR中的ACC、B、DPH、DPL和PSW当需要时入栈。如果不使用寄存器组切换,中断函数所需的所有工作寄存器Rn都入栈。函数退出前,所有工作寄存器都出栈。函数由“RETI”指令终止。下面示例说明C语言中断程序的编程方法。,例10-15对10.2.3的例10-4(见图)要求每中断一次,发光二极管显示开关状态用C语言编程#includeint0()interrupt0/*INT0中断函数*/P1=0 x0f;/*输入端先置1,灯灭*/P1=4;/*读入开关状态,并左移四位,使开关状态反映在发光二极管上*/main()EA=1;/*开中断总开关*/EX0=1;/*允许INT0中断*/IT0=1;/*下降沿产生中断*/while(1);/*等待中断*/,例10-16记录并显示中断次数。用C语言编程时,可有两种编程方法。法1:在主程序中判断中断次数,程序如下:#includechari;codechartab16=0 x3f,0 x06,0 x5b,0 x4F,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71;int()interrupt2i+;/*计中断次数*/P1=tabi;/*查表,次数送显示*/main()EA=1;EX1=1;/*开INT1中断*/IT1=1;/*下降沿触发*/ap5:P1=0 x3f;/*显示“0”*/for(i=0;i16;);/*当i小于16,等待中断*/gotoap5;/*当i=16重复下一轮计16次中断*/,法2:在中断程序中判断中断次数:#includechari;codechartab16=0 x3f,0 x06,0 x5b,0 x4F,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71;int()interrupt2i+;if(i16)P1=tabi;/*若i16,显示中断次数*/elsei=0;P1=0 x3f;/*否则,重新开始计数*/main()EA=1;EX1=1;IT1=1;i=0;P1=0 x3f;/*显示数字0*/while(1);/*等待中断*/,10.8.4定时/计数器的C语言编程,例10-13在P1.7端接一个发光二极管LED,要求利用定时控制使LED亮一秒灭一秒,周而复始,设fosc=6MHz。分析T0定时100ms初值=100103/2=50000,即初值为-50000。T1计数5个脉冲工作于方式2,计数初值为-5,T0和T1均采用中断方式。程序如下:#includereg51.hsbitP1_0=P10;sbitP1_7=P17;timer0()interrupt1using1/*T0中断服务程序*/P1_0=!P1_0;/*100ms到,P1.0反相*/TH0=-50000/256;/*重载计数初值*/TL0=-50000%256;timerl()interrupt3using2/*T1中断服务程序*/P1_7=!P1_7;/*1s到,灯改变状态*/,main()P1_7=1;/*置灯初始灭*/P1_0=1;/*保证第一次下降沿便开始计数*/TMOD=0 x61;/*T0方式1定时,T1方式2计数*/TH0=-50000/256;/*预置计数初值*/TL0=-50000%256;/*-50000=10000H-50000*/TH1=-5;/*-5=100H-5*/TL1=-5;IP=0 x08;/*置优先级;T1高级,T0低级*/EA=1;ET0=1;ET1=1;/*开CPU、T0、T1中断*/TR0=1;TR1=1;/*启动定时/计数器工作*/for(;)/*等待中断*/10.8.5串行通信的C语言编程,例10-14在内部数据存贮器20H3FH单元中共有32个数据,要求采用方式1串行发送出去,传送速率为1200波特,设fosc12MHZ。方法:T1工作于方式2作波特率发生器,取SMOD0,T1的时间常数计算如下:波特率(2SMOD/32)fosc/(12(256-x))1200(1/32)(12106)/(12(256-x)x230E6H(1)查询方式时的C语言编程:发送程序:#includemain()unsingnedchari;char*p;TMOD=0 x20;TH1=0 xe6;TL1=0 xe6;TR1=1;,SCON=0 x40;/*串口方式1,接收禁止*/p=0 x20;for(i=0;i=32;i+)SBUF=*p;/*发送数据*/p+;while(!TI);/*TI=0,死循环*/TI=0;,接收程序:#includemain()unsingnedchari;char*p;TMOD=0 x20;TH1=0 xe6;TL1=0 xe6;TR1=1;SCON=0 x50;p=0 x20;for(i=0;i=32;i+)while(!RI);/*RI=0,死循环*/RI=0;*p=SBUF;/*接收数据*/p+,(2)中断方式时的C语言编程请同学们考虑。重点注意几个方面:,10.8.6外扩并行I/O口的C语言编程,例10-15用8155作6位共阴极LED显示器接口,PB口经驱动器7407接LED的段选,PA0PA5位反相驱动器7406接位选,待显示字符依次存于dis-buf数组,从右向左顺序显示。8155命令字03,table为段码表,动态显示6个字符。8155和8XX51的接口见图10.12。,图10.128155和8XX51单片机的接口电路,各口的地址:A口7FF1HB口7FF2HC口7FF3H命令/状态口7FF0HC语言程序如下:#include#include#defineucharunsignedchar#defineCOM8155XBYTE0 x7ff0#definePA8155XBYTE0 x7ff1#definePB8155XBYTE0 x7ff2#definePC8155XBYTE0 x7ff3ucharidatadis6=2,4,6,8,10,12;/*存放显示字符2、4、6、8、A,C*/ucharcodetable18=0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71,0 x40,0 x00;,voiddisplay(ucharidata*p)ucharsel,i,j;COM8155=0 x03;scl=0 x01;/*送命令字,选最右边的LED*/for(i=0;i6;i+)PB8155=table*p;PA8155=sel;/*送段码和位码*/for(j=400;j0;j-);/*延时*/p-;/*地址指针下移位*/sel=sel0;i-)/*汇编函数执行完后返回于此*/total+=bufi-1;/*50个数累加*/total=total/50;/*求平均*/dis0=total%10;/*求个位,并存入显示缓冲区*/total=total/10;dis1=total%10;/*求十位,并存入显示缓冲区*/dis2=total/10;/*求百位,并存入显

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论