C51中精确的延时与计算的实现

发布者:EnigmaticCharm最新更新时间:2016-08-18 来源: eefocus关键字:C51  精确  延时 手机看文章 扫描二维码
随时随地手机看文章
        C51由于其可读性和可移植性很强,在单片机中得到广泛的应用,但在某些时候由于C51编写的程序对在有精确时间要求下,可能就得要用汇编语言来编写,但在C51是否也能实现时间的精确控制呢?答案是肯定的。 

在C51中要实现对时间的精确延时有以下几种方法 
其一:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒,就插入个这样的函数。 
其二:对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。 
在选择C51中循环语句时,要注意以下几个问题 
第一、定义的C51中循环变量,尽量采用无符号字符型变量。 
第二、在FOR循环语句中,尽量采用变量减减来做循环。 
第三、在do…while,while语句中,循环体内变量也采用减减方法。 
这因为在C51编译器中,对不同的循环方法,采用不同的指令来完成的。下面举例说明: 
unsigned char I; 
for(i=0;i<255;i++); 
  
unsigned char I; 
for(i=255;i>0;i--); 
其中,第二个循环语句C51编译后,就用DJNZ指令来完成,相当于如下指令: 
MOV 09H,#0FFH 
LOOP:            DJNZ 09H,LOOP 
指令相当简洁,也很好计算精确的延时时间。 
同样对do…while,while循环语句中,也是如此 
例: 
unsigned char n; 
n=255; 
do{n--} 
while(n); 
或 
n=255; 
while(n) 
{n--}; 
这两个循环语句经过C51编译之后,形成DJNZ来完成的方法,故其精确时间的计算也很方便。 
其三:对于要求精确延时时间更长,这时就要采用循环嵌套的方法来实现,因此,循环嵌套的方法常用于达到ms级的延时。 
对于循环语句同样可以采用for,do…while,while结构来完成,每个循环体内的变量仍然采用无符号字符变量。 
unsigned char i,j 
for(i=255;i>0;i--) 
for(j=255;j>0;j--); 
或 
unsigned char i,j 
i=255; 
do{j=255; 
    do{j--} 
    while(j); 
    i--; 
    } 
while(i); 
或 
unsigned char i,j 
i=255; 
while(i) 
{j=255; 
while(j) 
{j--}; 
i--; 

这三种方法都是用DJNZ指令嵌套实现循环的,由C51编译器用下面的指令组合来完成的 
MOV R7,#0FFH 
LOOP2:        MOV R6,#0FFH 
LOOP1:        DJNZ R6,LOOP1 
DJNZ R7,LOOP2 
这些指令的组合在汇编语言中采用DJNZ指令来做延时用,因此它的时间精确计算也是很简单,假上面变量i的初值为m,变量j的初值为n,则总延时时间为:m×(n×T+T),其中T为DJNZ指令执行时间。 
同样对于更长时间的延时,可以采用多重循环来完成。只要在程序设计循环语句时注意以上几个问题。 
下面给出有关在C51中延时子程序设计时要注意的问题 
1、在C51中进行精确的延时子程序设计时,尽量不要或少在延时子程序中定义局部变量,所有的延时子程序中变量通过有参函数传递。 
2、在延时子程序设计时,采用do…while,结构做循环体要比for结构做循环体好。 
3、在延时子程序设计时,要进行循环体嵌套时,采用先内循环,再减减比先减减,再内循环要好。 
unsigned char delay(unsigned char i,unsigned char j,unsigned char k) 
{unsigned char b,c; 
    b=j; 
    c=k; 
    do{ 
do{ 
    do{k--}; 
    while(k); 
    k=c; 
    j--;}; 
while(j); 
j=b; 
i--;}; 
    while(i); 

这精确延时子程序就被C51编译为有下面的指令组合完成 
delay延时子程序如下: 
                MOV      R6,05H 
                MOV      R4,03H 
C0012:        DJNZ      R3, C0012 
                MOV      R3,04H 
                DJNZ      R5, C0012 
                MOV      R5,06H 
                DJNZ      R7, C0012 
                RET    
假设参数变量i的初值为m,参数变量j的初值为n,参数变量k的初值为l,则总延时时间为:l×(n×(m×T+2T)+2T)+3T,其中T为DJNZ和MOV指令执行的时间。当m=n=l时,精确延时为9T,最短;当m=n=l=256时,精确延时到16908803T,最长。 
  
采用软件定时的计算方法

利用指令执行周期设定,以下为一段延时程序:      
指令            周期  
MOV            1
DJNZ            2
NOP            1
采用循环方式定时,有程序:
            MOV      R5,#TIME2          ;周期1
LOOP1:      MOV      R6,#TIME1          ; 1
LOOP2:      NOP                        ; 1
      NOP                        ; 1
      DJNZ    R6,LOOP2              ; 2
            DJNZ      R5,LOOP1            ; 2
定时数=(TIME1*4+2+1)*TIM2*2+4 

==============================================================================

[转帖]Keil C51 延时程序的两次研究 
51单片机 Keil C 延时程序的简单研究

      应用单片机的时候,经常会遇到需要短时间延时的情况。需要的延时时间很短,一般都是几十到几百(us)。有时候还需要很高的精度,比如用单片机驱动DS18B20的时候,误差容许的范围在十几us以内,不然很容易出错。这种情况下,用计时器往往有点小题大做。而在极端的情况下,计时器甚至已经全部派上了别的用途。这时就需要我们另想别的办法了。 以前用汇编语言写单片机程序的时候,这个问题还是相对容易解决的。比如用的是12MHz晶振的51,打算延时20us,只要用下面的代码,就可以满足一般的需要:
mov r0, #09h loop:
djnz r0, loop 
51单片机的指令周期是晶振频率的1/12,也就是1us一个周期。mov r0, #09h需要2个极其周期,djnz也需要2个极其周期。那么存在r0里的数就是(20-2)/2。用这种方法,可以非常方便的实现256us以下时间的延时。如果需要更长时间,可以使用两层嵌套。而且精度可以达到2us,一般来说,这已经足够了。 现在,应用更广泛的毫无疑问是Keil的C编译器。相对汇编来说,C固然有很多优点,比如程序易维护,便于理解,适合大的项目。但缺点(我觉得这是C的唯一一个缺点了)就是实时性没有保证,无法预测代码执行的指令周期。因而在实时性要求高的场合,还需要汇编和C的联合应用。但是是不是这样一个延时程序,也需要用汇编来实现呢?为了找到这个答案,我做了一个实验。
用C语言实现延时程序,首先想到的就是C常用的循环语句。下面这段代码是我经常在网上看到的:
void delay2(unsigned char i) 
{ for(; i != 0; i--); } 
到底这段代码能达到多高的精度呢?为了直接衡量这段代码的效果,我把 Keil C 根据这段代码产生的汇编代码找了出来:
FUNCTION _delay2 (BEGIN) 
SOURCE LINE # 18 
---- Variable 'i' assigned to Register 'R7' ---- 
SOURCE LINE # 19 
SOURCE LINE # 20 
0000 ?C0007: 
0000 EF MOV A,R7 
0001 6003 JZ ?C0010 
0003 1F DEC R7 
0004 80FA SJMP ?C0007 
SOURCE LINE # 21 
0006 ?C0010: 
0006 22 RET 
FUNCTION _delay2 (END) 
真是不看不知道~~~一看才知道这个延时程序是多么的不准点~~~光看主要的那四条语句,就需要6个机器周期。也就是说,它的精度顶多也就是6us而已,这还没算上一条 lcall 和一条 ret。如果我们把调用函数时赋的i值根延时长度列一个表的话,就是:
i delay time/us 
0 6 
1 12 
2 18
... 
因为函数的调用需要2个时钟周期的lcall,所以delay time比从函数代码的执行时间多2。顺便提一下,有的朋友写的是这样的代码:
void delay2(unsigned char i) 

unsigned char a; 
for(a = i; a != 0; a--);

可能有人认为这会生成更长的汇编代码来,但是事实证明:
FUNCTION _delay2 (BEGIN) 
SOURCE LINE # 18 
---- Variable 'i' assigned to Register 'R7' ---- 
SOURCE LINE # 19 
SOURCE LINE # 21 
---- Variable 'a' assigned to Register 'R7' ----
0000 ?C0007: 
0000 EF MOV A,R7 
0001 6003 JZ ?C0010 
0003 1F DEC R7 
0004 80FA SJMP ?C0007 
SOURCE LINE # 22 
0006 ?C0010: 
0006 22 RET 
FUNCTION _delay2 (END) 
其生成的代码是一样的。不过这的确不是什么好的习惯。因为这里实在没有必要再引入多余的变量。我们继续讨论正题。有的朋友为了得当更长的延时,甚至用了这样的代码:
void delay2(unsigned long i) 

for(; i != 0; i--); 

这段代码产生的汇编代码是什么样子的?其实不用想也知道它是如何恐怖的$#^%&%$......让我们看一看:
FUNCTION _delay2 (BEGIN) 
SOURCE LINE # 18
0000 8F00 R 
MOV i+03H,R7 
0002 8E00 R 
MOV i+02H,R6 
0004 8D00 R 
MOV i+01H,R5 
0006 8C00 R 
MOV i,R4 
SOURCE LINE # 19 
SOURCE LINE # 20 
0008 ?C0007: 
0008 E4 CLR A 
0009 FF MOV R7,A
000A FE MOV R6,A 
000B FD MOV R5,A 
000C FC MOV R4,A 
000D AB00 R MOV R3,i+03H 
000F AA00 R MOV R2,i+02H 
0011 A900 R MOV R1,i+01H 
0013 A800 R MOV R0,i 
0015 C3 CLR C 
0016 120000 E LCALL ?C?ULCMP 
0019 601A JZ ?C0010 
001B E500 R MOV A,i+03H 
001D 24FF ADD A,#0FFH 
001F F500 R MOV i+03H,A 
0021 E500 R MOV A,i+02H 
0023 34FF ADDC A,#0FFH 
0025 F500 R MOV i+02H,A 
0027 E500 R MOV A,i+01H 
0029 34FF ADDC A,#0FFH 
002B F500 R MOV i+01H,A 
002D E500 R MOV A,i 
002F 34FF ADDC A,#0FFH 
0031 F500 R MOV i,A 
0033 80D3 SJMP ?C0007 
SOURCE LINE # 21
0035 ?C0010: 
0035 22 RET 
FUNCTION _delay2 (END)
呵呵,这倒是的确可以延迟很长时间~~~但是毫无精度可言了。 那么,用C到底能不能实现精确的延时呢?我把代码稍微改了一下:
void delay1(unsigned char i) 

while(i--);

因为根据经验,越简洁的C代码往往也能得出越简洁的机器代码。那这样结果如何呢?把它生成的汇编代码拿出来看一看就知道了。满怀希望的我按下了“Build target”键,结果打击是巨大的:
FUNCTION _delay1 (BEGIN) 
SOURCE LINE # 13 
---- Variable 'i' assigned to Register 'R7' ---- 
SOURCE LINE # 14 
0000 ?C0004: 
SOURCE LINE # 15 
0000 AE07 MOV R6,AR7 
0002 1F DEC R7 
0003 EE MOV A,R6 
0004 70FA JNZ ?C0004 
SOURCE LINE # 16 
0006 ?C0006:
0006 22 RET 
FUNCTION _delay1 (END) 
虽说生成的代码跟用for语句是不大一样,不过我可以毫无疑问的说,这两种方法的效率是一样的。似乎到此为止了,因为我实在想不出来源程序还有什么简化的余地。看来我就要得出来这个结论了:“如果需要us级的延时精度,需要时用汇编语言。”但是真的是这样吗?我还是不甘心。因为我不相信大名鼎鼎的 Keil C 编译器居然连 djnz 都不会用???因为实际上程序体里只需要一句 loop: djnz r7, loop。近乎绝望之际(往往人在这种情况下确可以爆发出来,哦呵呵呵~~~),我随手改了一下:
void delay1(unsigned char i) 
{
while(--i); 

心不在焉的编译,看源码: 
FUNCTION _delay1 (BEGIN) 
SOURCE LINE # 13 
---- Variable 'i' assigned to Register 'R7' ---- 
SOURCE LINE # 14 
0000 ?C0004: 
SOURCE LINE # 15 
0000 DFFE DJNZ R7,?C0004 
SOURCE LINE # 16 
0002 ?C0006: 
0002 22 RET 
FUNCTION _delay1 (END) 
天~~~奇迹出现了......我想这个程序应该已经可以满足一般情况下的需要了。如果列个表格的话:
i delay time/us 
1 5 
2 7 
3 9 ... 
计算延时时间时,已经算上了调用函数的lcall语句所花的2个时钟周期的时间。 终于,结果已经明了了。只要合理的运用,C还是可以达到意想不到的效果。很多朋友抱怨C效率比汇编差了很多,其实如果对Keil C的编译原理有一个较深入的理解,是可以通过恰当的语法运用,让生成的C代码达到最优化。即使这看起来不大可能,但还是有一些简单的原则可循的:
1.尽量使用unsigned型的数据结构。
2.尽量使用char型,实在不够用再用int,然后才是long。
3.如果有可能,不要用浮点型。
4.使用简洁的代码,因为按照经验,简洁的C代码往往可以生成简洁的目标代码(虽说不是在所有的情况下都成立)。
5...想不起来了,哦呵呵呵~~~ 
===============================================================================

C51精确延时程序

C51精确延时程序再抛砖
//我看到的地方也是从别的地方转贴,所以我不知道原作者是谁,但相信这么成熟的东西转一下他也不会见意。

看到了个好帖,我在此在它得基础上再抛抛砖!

有个好帖,从精度考虑,它得研究结果是:
void delay2(unsigned char i) 
        {
          while(--i); 
          } 
为最佳方法。


分析:假设外挂12M(之后都是在这基础上讨论)
我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay2(0):延时518us          518-2*256=6
delay2(1):延时7us(原帖写“5us”是错的,^_^)
delay2(10):延时25us            25-20=5
delay2(20):延时45us            45-40=5
delay2(100):延时205us          205-200=5
delay2(200):延时405us          405-400=5

见上可得可调度为2us,而最大误差为6us。
精度是很高了!

但这个程序的最大延时是为518us 显然不
能满足实际需要,因为很多时候需要延迟比较长的时间。


那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。

void delay8(uint t)
{
while(--t);
}
我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay8(0):延时524551us          524551-8*65536=263
delay8(1):延时15us
delay8(10):延时85us              85-80=5  
delay8(100):延时806us            806-800=6
delay8(1000):延时8009us          8009-8000=9
delay8(10000):延时80045us        80045-8000=45
delay8(65535):延时524542us      524542-524280=262

如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要求的,因为延时最大为524.551ms。

那么用ulong t呢?
一定很恐怖,不用看编译后的汇编代码了。。。

 


那么如何得到比较小的可调度,可调范围大,并占用比较少得RAM呢?请看下面的程序:

/*--------------------------------------------------------------------
程序名称:50us 延时
注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振
例子提示:调用delay_50us(20),得到1ms延时
全局变量:无
返回:      无
--------------------------------------------------------------------*/
void delay_50us(uint t)
{
uchar j;  
for(;t>0;t--)  
    for(j=19;j>0;j--) 
    ;
}

我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay_50us(1):延时63us              63-50=13
delay_50us(10):延时513us            503-500=13  
delay_50us(100):延时5013us          5013-5000=13
delay_50us(1000):延时50022us        50022-50000=22

赫赫,延时50ms,误差仅仅22us,作为C语言已经是可以接受了。再说要求再精确的话,就算是用汇编也得改用定时器了。

/*--------------------------------------------------------------------
程序名称:50ms 延时
注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振
例子提示:调用delay_50ms(20),得到1s延时
全局变量:无
返回:      无
--------------------------------------------------------------------*/
void delay_50ms(uint t)
{
uint j;  
/****
可以在此加少许延时补偿,以祢补大数值传递时(如delay_50ms(1000))造成的误差,
但付出的代价是造成传递小数值(delay_50ms(1))造成更大的误差。
因为实际应用更多时候是传递小数值,所以补建议加补偿!
****/
for(;t>0;t--) 
    for(j=6245;j>0;j--) 
          ;
}
我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay_50ms(1):延时50 010            10us
delay_50ms(10):延时499 983          17us
delay_50ms(100):延时4 999 713        287us
delay_50ms(1000):延时4 997 022      2.978ms

赫赫,延时50s,误差仅仅2.978ms,可以接受!

上面程序没有才用long,也没采用3层以上的循环,而是将延时分拆为两个程序以提高精度。应该是比较好的做法了。

关键字:C51  精确  延时 引用地址:C51中精确的延时与计算的实现

上一篇:基于单片机控制的铁道口报警
下一篇:一个51产生PWM的演示程序

推荐阅读最新更新时间:2024-03-16 15:05

C51单片机学习笔记(二)——花样流水灯的实现
1.单片机引脚、晶振、复位的作用 复位电路:,复位是单片机的初始化操作。单片机启动时都需要先付薇,其作用是“清零”,也就是CPU和其他部件处于一个确定的初始状态,并从这个初始状态开始。 复位实质上是单片机的复位脚保持很短时间的高电平,按键复位就是通过按键接高电平(按一下的时间已经足够) 时钟电路(晶振):产生时间信号,使单片机按照一定的时间规律进行指令,晶振频率越高,时钟信号的周期就小,单片机运行也就越快。 32个I/O口 P1.0 ~ P1.7 对应1 ~ 8 号引脚 P2.0 ~ P2.7 对应21 ~ 28 号引脚 P3.0 ~ P3.7 对应10 ~ 17 号引脚 P0.0 ~ P0.7 对应39
[单片机]
<font color='red'>C51</font>单片机学习笔记(二)——花样流水灯的实现
单片机的延时与中断问题及解决方法
延时与中断出错,是单片机新手在单片机开发应用过程中,经常会遇到的问题,本文汇总整理了包含了MCS-51系列单片机、MSP430单片机、C51单片机、8051F的单片机、avr单片机、STC89C52、PIC单片机 ..在内的各种单片机常见的延时与中断问题及解决方法,希望对单片机新手们,有所帮助! 一、单片机延时问题20问 1、单片机延时程序的延时时间怎么算的? 答:如果用循环语句实现的循环,没法计算,但是可以通过软件仿真看到具体时间,但是一般精精确延时是没法用循环语句实现的。 如果想精确延时,一般需要用到定时器,延时时间与晶振有关系,单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种
[单片机]
第十六课 C51指针的使用
指针就是指变量或数据所在的存储区地址。如一个字符型的变量 STR 存放在内存单元DATA 区的 51H 这个地址中,那么 DATA 区的 51H 地址就是变量 STR 的指针。在 C 语言中 指针是一个很重要的概念,正确有效的使用指针类型的数据,能更有效的表达复杂的数据 结构,能更有效的使用数组或变量,能方便直接的处理内存或其它存储区。指针之所以 能这么有效的操作数据,是因为无论程序的指令、常量、变量或特殊寄存器都要存放在内 存单元或相应的存储区中,这些存储区是按字节来划分的,每一个存储单元都能用唯一的 编号去读或写数据,这个编号就是常说的存储单元的地址,而读写这个编号的动作就叫做寻 址,通过寻址就能访问到存储区中的任一个能访问的
[单片机]
第十六课 <font color='red'>C51</font>指针的使用
电磁流量计典型的精确度包络线
一次装置 1.必备的数据 下列数据应印制在一次装置上或铭牌上: a)仪表型式和系列编号; b)额定压力和额定温度: c)供电电源:电压,频率和功率(独立电源时)。 2.任选的数据 可选择性地提供下列数据: a)外壳防护等级; b)公称通径; c)校准系数; d)衬里材料; e)电极材料。 注:如铭牌尺寸允许,如商标、装置重量、制造日期、流动方向箭头等等附加说明亦可包括在内。 二次装置 1.必备的数据 下列数据应印制在铭牌上· a)仪表型式和系列编号, b)供电电源:电压、频率和功率; c)输出信号; d)极限负载阻抗。 2.任选的数据 可选择性地提供下列数据: a)外壳防护等级。 注:若铭牌尺寸允许,如
[测试测量]
详谈如何有效精确测量电源纹波
  精确地测量 电源 纹波本身就是一门艺术。在图6.1所示的示例中,一名初级工程师完全错误地使用了一台示波器。他的第一个错误是使用了一支带长接地引线的示波器探针;第二个错误则是将探针形成的环路和接地引线均置于电源变压器和开关元件附近;最后一个错误是允许示波器探针和输出电容之间存在多余电感。该问题在纹波波形中表现为高频拾取。在电源中,存在大量可以很轻松地与探针耦合的高速、大信号电压和电流波形,其中包括耦合自电源变压器的磁场,耦合自开关节点的电场,以及由变压器互绕电容产生的共模电流。   利用正确的测量方法可以大大地改善测得纹波结果。首先,通常使用带宽限制来规定纹波,以防止拾取并非真正存在的高频噪声。我们应该为用于测量的示波器设定正
[电源管理]
详谈如何有效<font color='red'>精确</font>测量电源纹波
直流电流探头可以精确测得电流波形
  直流电流探头提供一种安全、成本效益、简单喝准确的途径测量电流。它们那个在不断开电路的情况下就可以测量电流。电流钳的钳口可以打开,包围住导体形成一个磁场环。进而测量电流大小。在实际应用当中电流探头也有许多的参数需要注意。   其工作原理是当共模电流远小于差模电流时,采用正负双线测量共模电流存在一定的误差;当测量大电流旁边的小电流导线时也存在一定的误差。因此必须改进电流探头的设计,提高测量精度,才能发挥分流测量的作用。   直流电流探头可以精确测得电流波形,方法是采用电流互感器输入,信号电流磁通经互感变压器变换成电压,再由探头内的放大器放大后送到示波器。电流探头基本上又分成两类, 交流电流探头和交直流探头,交流电流探头通常
[测试测量]
新品翻车:用户吐槽大疆Mavic Air 2 8K延时摄影存严重BUG
4月下旬,大疆发布新款便携可折叠无人机Mavic Air 2,定价4999元,虽然体积略有增加,但续航从21分钟提高到34分钟、换装1/2英寸CMOS(最大4800万像素)、支持4K/60FPS视频录制、HDR视频拍摄、240帧慢动作、10公里图传、智能避障3.0等,升级幅度不小。 然而,国外飞手深度使用后发现,Mavic Air 2的8K Hyperlapse存在影响使用的严重BUG。所谓Hyperlapse,最早出现于Mavic 2,它可以理解为Timelapse(延时摄影)的进阶版,即大范围移动延时摄影。顾名思义,镜头和画面不再局限于静止的某一处,而是多视角、多场景拼接延时画面。 不过,外媒实测以及从Redditd大疆话题专
[机器人]
基于单片机+CPLD的多路精确延时控制系统
1 引言 现代控制系统中控制对象可能是复杂、分散的,而且往往是并行、独立工作的,但整体上它们是相互关联的有机组合。因此,控制信号的时序逻辑则要求更加精确。CPLD单片机为控制系统提供了技术支持,由CPLD和单片机组成的多机系统具有逻辑控制方便,时序精确,并行工作,人机接口友好等优点。因此,本文提出了一种基于CPLD与单片机控制的多路精确延时控制系统的设计方案。 2 设计指标与系统原理 2.1 设计指标 输出多路脉宽为10 ms正脉冲信号; 脉冲输出时间独立调节、显示; 时间调整范围与精度为微秒级的调整范围为l~199μs,调节精度为lμs;毫秒级的调整范围为1~199 ms,调整精度为1
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved