有很多有过一定嵌入式开发工作经验的朋友在从事嵌入式开发的过程当中,主要在嵌入式软件,界面等方向做的研究较多,但经常也会用串口进行调试程序,只知道串口是用来传输数据用的。但串口具体怎么用来传输数据却不太清楚,对串口的工作原理也是一知半解。接下来分享下串口具体是怎么用来传输数据的。
串行通信的基本概念
•在通信领域内,有两种数据通信方式:并行通信和串行通信
•串行通信:
•计算机与I/O设备之间数据传输的各位是按顺序依次进行传送,通常数据在一根数据线上或者一对差分线上传输。
•并行通信:
•计算机与I/O设备之间通过多条传输线交换数据,数据的各位同时传送。
•串行速度慢,但是传输设备成本低,可利用现有的通信手段和通信设备进行远程通信。并行通信速度快,但是传输设备成本高,适合近距离数据传送。需要注意:一些差分串行通信总线(RS485,RS422,USB等)他们传输距离远,且抗干扰能力强,速度也比较快。
1.1.1 数据的串行和并行通信方式
串行通信好比是一列纵队,每个数据元素依次纵向排列。如图2-57所示,传输时一个比特一个比特的串行传输,每个时钟周期传输一个比特,这种传输方式相对比较简单,速度较慢,但是使用总线数较少,通常一根接收线,一根发送线即可实现串行通信。它的缺点是要增加额外的数据来控制一个数据帧的开始和结束。
并行通信好比一排横队,齐头并进同时传输。这种通信方式每个时钟周期传输的数据量和其总线宽度成正比,但是实现较为复杂。UART通信采用的是串行方式进行通信的。
图为串行数据通信与并行数据通信
•串口的数据传输是以串行方式进行的。串口在数据通信中,一次只传输一个比特的数据。串行数据的传输速度用bps或波特率来描述。
注意:
码元:在数字通信中常常用时间间隔相同的符号来表示数字。这样的时间间隔内的信号称为码元,这个间隔称为码元长度
比特率:是信息量传送速率单位,即每秒传输二进制代码位数。bit/s
所谓差分传输,就是发送端在两条信号线上传输幅值相等相位相反的电信号,接收端对接受的两条线信号作减法运算,这样获得幅值翻倍的信号。
串行通信涉及的常用术语
•单工、半双工和全双工
•单工(Simplex)
o特点:仅能进行一个方向的数据传送
•半双工(Half Duplex)
o特点:数据可以在两个方向上进行传送,但是这种传送绝不能同时进行。[双向,但不同时]
•全双工(Full Duplex)
o特点:能够在两个方向同时进行数据传送
•数据传输率
•每秒传输的二进制位数,单位为bps(bit per second)也称比特率。
•异步方式与同步方式
•同步通信方式(Synchronous)所用的数据格式没有起始位、停止位,一次传送的字符个数可变。在传送前,先按照一定的格式将各种信息装配成一个包,该包包括供接收方识别用的同步字符一个或两个,其后紧跟着要传送的n个字符,再后就是校验字符。
•异步方式(Asynchronous):也称“起止同步式”。
•
奇偶校验位
奇偶校验位 (Parity)是指偶数或者奇数或甚至对一个数字的性质。多被应用于计算机硬件的错误检测中。
奇偶校验位是一个表示给定位数的二进制数中 1 的个数是奇数还是偶数的二进制数。奇偶校验位是最简单的错误检测码。奇偶校验位有两种类型:偶校验位与奇校验位。
1.1.2 异步通信和同步通信
图2-56同步信号与异步信号
同步通信技术
在发送数据信号的时候,会同时送出一根同步时钟信号,用来同步发送方和接收方的数据采样频率。如图2-56所示,同步通信时,信号线1是一根同步时钟信号线,以固定的频率进行电平的切换,其频率周期为t,在每个电平的上升沿之后进行对同步送出的数据信号线2进行采样(高电平代表1,低电平代表0),根据采样数据电平高低取得输出数据信息。如果双方没有同步时钟的话,那么接收方就不知道采样周期,也就不能正常的取得数据信息。
图2-56同步信号与异步信号
同步通信技术
在发送数据信号的时候,会同时送出一根同步时钟信号,用来同步发送方和接收方的数据采样频率。如图2-56所示,同步通信时,信号线1是一根同步时钟信号线,以固定的频率进行电平的切换,其频率周期为t,在每个电平的上升沿之后进行对同步送出的数据信号线2进行采样(高电平代表1,低电平代表0),根据采样数据电平高低取得输出数据信息。如果双方没有同步时钟的话,那么接收方就不知道采样周期,也就不能正常的取得数据信息。
异步通信技术
在异步通信技术中,数据发送方和数据接收方没有同步时钟,只有数据信号线,只不过发送端和接收端会按照协商好的协议(固定频率)来进行数据采样。数据发送方以每秒钟57600bits的速度发送数据,接收方也以57600bits的速度去接收数据,这样就可以保证数据的有效和正确。通常异步通信中使用波特率(Baud-Rate)来规定双方传输速度,其单位为bps(bits per second每秒传输位数)。
1.1.3 数据通信传输模式
在数据通信过程中,发送方和接收方为了实现数据的正确发送和接收,通常会有一个状态寄存器来描述当前数据接收和发送状态,当发送方有数据发送时,会查看发送状态寄存器,看是否允许发送数据(如果上一次数据还没有发送完毕,不允许继续数据发送),在发送允许情况下再送出新数据。同样,接收端通过查看接收状态寄存器,确定是否有新数据到达,如果有数据到达,将去接收数据缓冲区读取数据。
(1)轮询模式
通过程序执行流,不停的检测状态寄存器的结果,如果当前可发送或接收,则发送或接收数据。其过程可以用下面伪代码来表示。
轮询方式实现数据发送伪代码
Send()
{
While(1)
{
if(发送状态 == 可发送) // 检查寄存器的值
执行数据发送操作;
}
}
轮询方式实现数据接收伪代码
Receive()
{
While(1)
{
if(接收状态 == 有数据到达)
执行数据接收操作;
}
}
由程序可知,这种方式实现简单,但在进行数据接收和发送时都要进入循环检查状态寄存器的值,当没有数据到达或数据不可发送时,CPU会一直空转,其它程序又得不到CPU的执行权,很影响系统的效率。
(2)中断模式
中断方式是指,当数据到达或数据可发送时,产生中断,通知CPU去发送或接收数据,这种方式将通信硬件和CPU独立出来,通信硬件只有在发送或接收条件准备好之后中,才通知CPU去处理数据,在通信条件没有准备好的时候,CPU去处理其它程序,显然这种方式更合理,这种方式要求通信硬件要求比较高,需要支持产生中断信号。
(3)DMA模式
通常实现数据的转移或拷贝时,CPU将从源地址处复制数据到寄存器,然后将寄存器数据再写入目的地址处,该复制过程需要CPU来执行。FS4412支持DMA方式传输串口通信数据,DMA传输是指在CPU不干涉的情况下,DMA硬件自动实现数据的转移和复制,在DMA传输过程中,CPU几乎不用干涉,这样可以让CPU安心的去做自己的事情。虽然如此,但是DMA在传输数据过程中要占用总线,在大批数据传输时,系统总线会被DMA通道占用,也会影响系统的效率。
1.1 UART串口
通用异步接收器和发送器(Universal Asynchronous Receiver and Transmitter) 简称UART。通常是嵌入式设备中默认都会配置的通信接口。
为什么使用串口?
这是因为,很多嵌入式设备没有显示屏,无法获得嵌入式设备实时数据信息,通过UART串口和超级终端相连,打印嵌入式设备输出信息。并且在对嵌入式系统进行跟踪和调试时,UART串口是必要的通信手段。
举例:
比如:网络路由器,交换机等都要通过串口来进行配置。UART串口还是许多硬件数据输出的主要接口,如GPS接收器就是通过UART串口输出GPS接收数据的。
fs4412的特点:
1)4组收发通道,同时支持中断模式和DMA操作
2)通道0,1,2及带红外3通道都支持64字节FIFO
3)通道1和3支持高速操作模式
4)支持握手模式的发送和接收
1.1.4 UART控制器
UART控制器,提供了三个独立的异步串行I/O端口,每个端口都可以在中断模式或DMA模式下工作,换而言之,UART可以生成中断或DMA请求用于CPU和UART之间的数据传输。UART串口挂接在APB总线上,APB总线最高可以达到50MHz工作频率,在使用APB时钟频率时可以达到最高115.2Kbps波特率的通信速度。如果UART串口接收外部设备提供UEXTCLK(外部时钟),UART可以在更高的速度下工作。每个UART串口在接收装置和发送装置里分别包含一个64Byte的FIFO缓冲区,用于缓存发送数据和接收数据。
由于UART是串行异步通信方式,因此在UART通信过程中每次只能传输1位(bit),若干位组成一个数据帧(frame),帧是UART通信中最基本单元,它主要包含:开始位,数据位,校验位(如果开启了数据校验,要包含校验位),和停止位。
UART在通信之前要在发送端和接收端约定好帧结构,也就是约定好传输数据帧格式。
l 开始位:必须包含在数据帧中,表示一个帧的开始。
l 数据位:可选5,6,7,8位,该位长度可由编程人员指定。
l 校验位:如果在开启了数据校验时,该位必须指定。
l 停止位:可选1,2位,该位长度可由编程人员指定。
通信双方约定好帧格式后,指定同一波特率,以保证双方数据传输的同步。
1.1.5 UART串口工作原理
每个UART包含一个波特率产生器,发送器,接收器和一个控制单元,如下图所示:
•下面列出Exynos4412 UART相关的控制寄存器,具体位含义见Exynos4412芯片手册
•UART行控制器ULCONn
•UART模式控制寄存器UCONn
•UART FIFO控制寄存器UFCONn
•UART MODEM控制寄存器UMCONn
•发送寄存器UTXH和接收寄存器URXH
•波特率分频寄存器UBRp2和UFRACVAL2
•UART硬件结构
•UART是以异步方式实现通信的,其采样速度由波特率决定,波特率产生器的工作频率可以由PCLK(外围设备频率),FCLK/n(CPU工作频率的分频),UEXTCLK(外部输入时钟)三个时钟作为输入频率,波特率设置寄存器是可编程的,用户可以设置其波特率决定发送和接收的频率。发送器和接收器包含了64Byte的FIFO和数据移位器。UART通信是面向字节流的,待发送数据写到FIFO之后,被拷贝到数据移位器(1字节大小)里,数据通过发送数据管脚TXDn发出。同样道理,接收数据通过RXDn管脚来接收数据(1字节大小)到接收移位器,然后将其拷贝到FIFO接收缓冲区里。
•(1)数据发送
•发送的数据帧可编程的,它的一个帧长度是用户指定的,它包括一个开始位,5~8个数据位,一个可选的奇偶校验位和1~2个停止位,数据帧格式可以通过设置ULCONn寄存器来设置。发送器也可以产生一个终止信号,它是由一个全部为0的数据帧组成。在当前发送数据被完全传输完以后,该模块发送一个终止信号。在终止信号发送后,它可以继续通过FIFO(FIFO)或发送保持寄存器(NON-FIFO)发送数据。
•(2)数据接收
•同样接收端的数据也是可编程的,接收器可以侦测到溢出错误奇偶校验错误,帧错误和终止条件,每个错误都可以设置一个错误标志。
•l 溢出错误是指在旧数据被读取到之前,新数据覆盖了旧数据
•l 奇偶校验错误是指接收器侦测到了接收数据校验结果失败,接收数据无效
•l 帧错误是指接收到的数据没有一个有效的停止位,无法判定数据帧结束
•l 终止条件是指RxDn接收到保持逻辑0状态持续长于一个数据帧的传输时间
•(3)自动流控AFC(Auto Float Control)
•硬件流控使用串行电缆控制线上的电压信号来控制数据的发送和接收。
•串口通讯中的硬件流控有两种方式:DTR/DSR方式和RTS/CTS方式。
•自动流控制可以看成是串口的开关,uart2不带有AFC功能
•UART0和UART1支持有nRTS和nCTS的自动流控,UART2不支持流控。在AFC情况下,通信双方nRTS和nCTS管脚分别连接对方的nCTS和nRTS管脚。通过软件控制数据帧的发送和接收。
•在开启AFC时,发送端接收发送前要判断nCTS信号状态,当接收到nCTS激活信号时,发送数据帧。该nCTS管脚连接对方nRTS管脚。接收端在准备接收数据帧前,其接收器FIFO有大于32个字节的空闲空间,nRTS管脚会发送激活信号,当其接收FIFO小于32个字节的空闲空间,nRTS必须置非激活状态。如图2-60所示。
•RTS (Require ToSend,发送请求)为输出信号,用于指示本设备准备好可接收数据,低电平有效,低电平说明本设备可以接收数据。
•CTS (Clear ToSend,发送允许)为输入信号,用于判断是否可以向对方发送数据,低电平有效,低电平说明本设备可以向对方发送数据。
•此处有人将CTS翻译为发送允许。因为CTS是对方的RTS控制己方的CTS是否允许发送的功能。
图2-60自动流控数据传输
(4)波特率
在UART中波特率发生器为发送器和接收器提供工作时钟。波特率发生器的时钟源可以选择FS4412的内部系统时钟(PCLK,FCLK/n)或UEXTCLK(外部时钟源),可以通过设置UCONn寄存器来设置波特率发生器的输入时钟源。通常我们选择使用PCLK作为UART工作时钟。
UART控制器中没有对波特率进行设置的寄存器,而是通过设置一个除数因子,来决定其波特率。其计算公式如下:
UART除数(UBRpn) = (int)(CLK/(buad rate * 16 )) - 1
其中:UBRpn的取值范围应该为1~2^16-1。例如:波特率为115200bps,PCLK时钟为其工作频率,采用50MHz,UBRpn为:
UBRpn = (int)(50M / (115200 x 16)) - 1 = 26
在系统时钟未初始化时,PCLK = 12MHz,如果波特率采用57600bps,那么UBRpn为:
UBRpn = (int)(12M / (57600 x 16)) - 1 = 12
当使用外部时钟源时,如果外部时钟小于PCLK时钟,则UEXTCLK应该设置为0。
.比特率
在数字信道中,比特率是数字信号的传输速率,它用单位时间内传输的二进制代码的有效位(bit)数来表示,其单位为每秒比特数bit/s(bps)、每秒千比特数(Kbps)或每秒兆比特数(Mbps)来表示(此处K和M分别为1000和1000000,而不是涉及计算机存储器容量时的1024和1048576)。
.波特率
波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,其单位为波特(Baud)。 波特率与比特率的关系为:比特率=波特率X单个调制状态对应的二进制位数。
如何区分两者?
显然,两相调制(单个调制状态对应1个二进制位)的比特率等于波特率;四相调制(单个调制状态对应2个二进制位)的比特率为波特率的两倍;八相调制(单个调制状态对应3个二进制位)的比特率为波特率的三倍;依次类推。
图2-61 开发板串口硬件图
UART的接口
图2-61为Cortex-A9开发板引出UART串口接线图,它采用DB9接口公头(有接线柱的端口,只有接线孔的为母头),其有9根信号线,UART通信过程中用到了信号线2 RSTXD0(数据发送管脚)它和串口线母头TXDx信号线相接(x代表0号,1号,2号串口),信号3 RSRXD0(数据接收管脚)和串口线母头RXDx相接(x代表0号,1号,2号串口),信号线5(接地管脚),信号线7 RSCTS0(数据发送流控制管脚)和串口线母头nCTSx相接,信号线8 RSRTS0(数据接收流控制管脚)和串口线母头nRTSx相接。如果UART中没有开启AFC流控的话,只要用到信号线2,信号线3和信号线5。
UART寄存器配置
UART0串行控制寄存器(ULCON0)
寄存器名地址是否读写描述复位默认值
ULCON00x50000000R/W串口0串行控制寄存器0x00
ULCON0位描述初始值
保留[7]0
红外模式[6]选择串口0是否使用红外模式:
0 = 正常通信模式
1 = 红外通信模式0
校验模式[5:3]设置串口0在数据接收和发送时采用的校验方式:
0xx = 无校验
100 = 奇校验
101 = 偶校验
110 = 强制校验/检测是否为1
111 = 强制校验/检测是否为0000
停止位[2]设置串口0停止位数:
0 = 每个数据帧一个停止位
1 = 每个数据帧二个停止位0
数据位[1:0]设置串口0数据位数:
00 = 5个数据位 01 = 6个数据位
10 = 7个数据位 11 = 8个数据位00
通过设置ULCON0来设置UART0通信方式,ULCON0[6]选择通信方式为一般通信模式或红外通信模式,ULCON0[5:3]设置串口0校验方式,ULCON0[2]设置串口0停止位数,ULCON0[1:0] 设置串口0的数据位数。
我们选择一般通信模式,无校验位,1个停止位,8个数据位的数据通信方式。因此:
ULCON0 = 0x03;
表2-26 UART0串口控制寄存器(UCON0)
寄存器名地址是否读写描述复位默认值
UCON00x50000004R/W串口0控制寄存器0x00
UART0串行控制寄存器(ULCON0)
寄存器名地址是否读写描述复位默认值
ULCON00x50000000R/W串口0串行控制寄存器0x00
ULCON0位描述初始值
保留[7]0
红外模式[6]选择串口0是否使用红外模式:
0 = 正常通信模式
1 = 红外通信模式0
校验模式[5:3]设置串口0在数据接收和发送时采用的校验方式:
0xx = 无校验
100 = 奇校验
101 = 偶校验
110 = 强制校验/检测是否为1
111 = 强制校验/检测是否为0000
停止位[2]设置串口0停止位数:
0 = 每个数据帧一个停止位
1 = 每个数据帧二个停止位0
数据位[1:0]设置串口0数据位数:
00 = 5个数据位 01 = 6个数据位
10 = 7个数据位 11 = 8个数据位00
通过设置ULCON0来设置UART0通信方式,ULCON0[6]选择通信方式为一般通信模式或红外通信模式,ULCON0[5:3]设置串口0校验方式,ULCON0[2]设置串口0停止位数,ULCON0[1:0] 设置串口0的数据位数。
我们选择一般通信模式,无校验位,1个停止位,8个数据位的数据通信方式。因此:
ULCON0 = 0x03;
表2-26 UART0串口控制寄存器(UCON0)
寄存器名地址是否读写描述复位默认值
UCON00x50000004R/W串口0控制寄存器0x00
UCON0位描述初始值
FCLK分频因子[15:12]当UART0选择FCLK作为时钟源时,设置其FCLK的分频因子
UART0 工作时钟频率 = FCLK/FCLK分频因子 + 60000
UART时钟源选择[11:10]选择UART0的工作时钟PCLK,UEXTCLK,FCLK/n:
00,10 = PCLK
01 = UEXTCLK
11 = FCLK/n
当选择FCLK/n作为UART0工作时钟时还要做其它设置,具体请读者自行查看硬件手册00
发送数据中断
产生类型[9]设置UART0中断请求类型,在非FIFO传输模式下,一旦发送数据缓冲区为空,立即产生中断信号,在FIFO传输模式下达到发送数据触发条件时立即产生中断信号:
0 = 脉冲触发
1 = 电平触发0
接收数据中断
产生类型[8]设置UART0中断请求类型,在非FIFO传输模式下,一旦接收到数据,立即产生中断信号,在FIFO传输模式下达到接收数据触发条件时立即产生中断信号:
0 = 脉冲触发
1 = 电平触发0
接收数据超时[7]设置当接收数据时,如果数据超时,是否产生接收中断:
0 = 不开启超时中断 1 = 开启超时中断
10 = 7个数据位 11 = 8个数据位0
接收数据错误中断[6]设置当接收数据时,如果产生异常,如传输中止,帧错误,校验错误时,是否产生接收状态中断信号:
0 = 不产生错误状态中断 1 = 产生错误状态中断0
回送模式[5]设置该位时UART会进入回送模式,该模式仅用于测试
0 = 正常模式 1 = 回送模式0
发送终止信号[4]设置该位时,UART会发送一个帧长度的终止信号,发送完毕后,该位自动恢复为0
0 = 正常传输 1 = 发送终止信号0
发送模式[3:2]设置采用哪个方式执行数据写入发送缓冲区
00 = 无效
01 = 中断请求或查询模式
10 = DMA0请求00
接收模式[1:0]设置采用哪个方式执行数据写入接收缓冲区
00 = 无效
01 = 中断请求或查询模式
10 = DMA0请求00
通常UART串口采用PCLK作为输入工作时钟,采用简单的轮询方式进行数据接收和发送,不开启数据接收超时,数据产生错误时不产生错误状态中断,因此:
UCON0 = 0x05;
表2-27 UART FIFO控制寄存器(UFCON0)
寄存器名地址是否读写描述复位默认值
UFCON00x50000008R/W串口0 FIFO控制寄存器0x00
UFCON0位描述初始值
发送数据
触发级别[7:6]设置FIFO发送模式的触发级别:
00 = FIFO为空触发 01 = 16字节触发
10 = 32字节触发 11 = 48字节触发00
接收数据
触发级别[5:4]设置FIFO接收模式的触发级别:
00 = FIFO为空触发 01 = 16字节触发
10 = 32字节触发 11 = 48字节触发00
保留[3]0
发送FIFO重置[2]在重置FIFO后自动清除发送缓冲区
0 = 正常模式 1 = 自动清除0
接收FIFO重置[1]在重置FIFO后自动清除接收缓冲区
0 = 正常模式 1 = 自动清除0
启用FIFO[0]0 = 不启用FIFO 1 = 启用FIFO0
表2-28 UART MODEM控制寄存器(UMCON0)
寄存器名地址是否读写描述复位默认值
UMCON00x5000000CR/W串口0 MODEM控制寄存器0x00
UMCON0位描述初始值
保留[7:5]必须全部置0000
AFC自动流控[4]0 = 不开启流控 1 = 开启流控0
保留[3:1]必须全部置0000
请求发送[0]如果启用AFC,该位无效,S3C2440会自动控 制nRTS,如果不启用AFC,nRTS必须由软件控制
0 = 高电平激活nRTS 1 = 低电平激活nRTS0
表2-29 UART 发送/接收状态寄存器(UTRSTAT0)
寄存器名地址是否读写描述复位默认值
UTRSTAT00x50000010R/W串口0发送/接收状态寄存器0x06
UTRSTAT0位描述初始值
发送器为空[2]当发送缓存寄存器中没有数据要发送且发送移位寄存器为空时,自动置1
0 = 非空
1 = 发送器为空(发送缓存和移位寄存器)1
发送缓存寄存器为空[1]当发送缓存寄存器为空时,自动置1
0 = 发送缓存寄存器非空
1 = 发送缓存寄存器为空1
接收缓存寄存器为空[0]当接收缓存寄存器有数据到达时,自动置1
0 = 接收缓存寄存器为空
1 = 缓存寄存器接收数据0
表2-30 UART 发送缓存寄存器(UTXH0)
寄存器名地址是否读写描述复位默认值
UTXH00x50000020(L)
0x50000023(B)W串口0发送缓存寄存器-
表2-31 UART 接收缓存寄存器(URXH0)
寄存器名地址是否读写描述复位默认值
URXH00x50000024(L)
0x50000027(B)R串口0接收缓存寄存器-
表2-32 UART 波特率除数寄存器(UBRp0)
寄存器名地址是否读写描述复位默认值
UBRp00x50000028R/W串口0波特率除数寄存器-
UBRp0位描述初始值
波特率除数[15:0]设置波特率除数(大于0)使用外部输入时钟时可以置0-
上述寄存器是是和UART通信相关寄存器,使用简单的无FIFO,无自动流控AFC时,设置如下:
UFCON0 = 0x00; // 不使用FIFO
UMCON0 = 0x00; // 不使用流控
UBRp0 = 26; // 波特率为115200,PCLK=50Mhz
UBRp0 = 53; // 波特率为57600,PCLK=50Mhz
UBRp0 = 12; // 波特率为57600,PCLK=12Mhz
UTXH0和URXH0分别是数据发送和接收寄存器,发送数据时通过轮询方式判断发送状态寄存器的状态,当可以发送数据时,执行UTXH0寄存器写入操作,接收数据时,以轮询方式检测接收状态寄存器状态,当有数据到达时,读取URXH0寄存器里的数据即可取得串口数据。
可能不同的开发板,不同厂家生产设计的开发板有所不同,里面的寄存器的配置也会略有区别,原理是一样的。
11月13日,嵌入式开发就业班
11月13日,Android开发就业班
11月13日,HTML5高端就业班
11月13日,JavaEE精英就业班
巴适的很哦~
1.《串口基本原理详解》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《串口基本原理详解》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/yule/13254.html