公告

非常抱歉,由于我们的服务器提供商硬盘出错,数据丢失,网站重建中...
I am so sorry, because of our server's hard disk error, data lost, the website reconstructioning
QQ:512000523
MSN : funchip@hotmail.com

 
首页 arrow 技术文章 arrow setp arrow AVR起步教程-3:从51到AVR编程篇
AVR起步教程-3:从51到AVR编程篇 Recommend to my friend via E-mail(推荐给朋友)
作者: Administrator   
2007-11-14

一、DPTR的处理
在51系统中,DPTR是十分重要的,51可以通过DPTR寻址,临时储存16位数据等等,下面仅仅先介绍2种51到AVR程序移植中DPTR的处理:
(1)DPTR直接寻址
    例子: 51程序如下:
         MOV DPTR,#8000H;
         MOVX A,@DPTR;

       这个移植起来就比较简单了,我们现在选用Z寄存器(R30,R31)作为DPTR,这个里不考虑实际地址的偏移,地址设为0x1100对应0x8000
         ldi r30,0x00
         ldi r31,0x11
         ld r24,z
(2)DPTR变址寻址
 类似的,51的变址寻址也是一样的
         MOV DPTR,#8000H
         MOV A,#05H
         MOVX A,@A+DPTR
 AVR中可以移植成:
         ldi r30,0x00
         ldi r31,0x11
         adiw r30,0x05
         ld r24,z
  
(3)DPTR与P2结合
 这种寻址方式在51中也较为常用
         MOV DPTR,#8100H
         MOV P2,#81H
         MOV R0,#10H
         MOVX A,@R0
         INC R0
         MOVX A,@R0
 这种寻址方式的时候,寻址的范围限制在了0x8100到0x81FF之间

    AVR中可以移植如下:
         ldi r31,0x11
         ldi r30,0X10
         lz r24,z
         inc r30
         lz r24,z

二、DA的处理
DA是十进制调整指令,具体的功能是对BCD码加法运算的结果进行有条件的修正,操作依据为:
 若(A)3~0>9∨(AC)=1,则A3~0←(A)3~0+6
 若(A)7~4>9∨(C)=1,则A7~4←(A)7~4+6
 若(A)7~4=9∧(A)3~0>9,则A7~4←(A)7~4+6
举例子来说,如果DA的数字是0A,那么就给这个数字加上0x06,使之成为0x10,现在的0x10就代表了十进制的10了,
 
         #define u08 unsigned char
         u08 A,C
         void DA(void)
         {
                  u08 tmp;
                  tmp = A & 0x0F;
                  if( tmp > 0x09 C & 0x20)
                  A += 0x06;
                  tmp = A & 0xF0;
                  if( tmp > 0x90 C & 0x01)
                  {
                           A += 0x60;
                           asm("sec");
                           C = SREG;
                  }
                   tmp = A & 0xF0;
                  if( tmp == 0x90)
                  {
                           tmp = A & 0x0F;
                           if(tmp>0x09)
                           {
                                    A += 0x60;
                                    asm("sec");
                                    C = SREG;
                           }
                  }
         }
 
 代码中的C就是SREG寄存器中的内容

三、PSW中P的处理
51中,如果A中1的个数为奇数,则P置位,反之则置0。在一些老的程序中,特别是有使用一种模拟老式纸带传输的程序,P就用来检测数据传输的正确于否!
在AVR中,我们可以用3中方式来做:
(1)、查表:
 我们可以把0到255中的数字的做个表,然后去查表确定A中的数字1的P值,显然,不管做偶数表或者奇数的表,内存的消耗和时钟的消耗是难以让人忍受的
(2)、数数:
 既然查表在大多时候不可取,那么让我们来数数,我们把A拆分开来,一位一位去数
 我们还是嵌入汇编去解决

          #define u08 unsigned char
         u08 A,B;

         u08 CalcP(void)
         {
                   asm volatile 
                  (
                           "mov %0,%2" "\n\t" //保存A
                           "clc" "\n\t"  //清C标志
                           "eor r1,r1" "\n\t"
                           "mov %1,r1" "\n\t"
  
                           "lsr %0" "\n\t" 
                            "adc %1,r1" "\n\t" //算了第一位

                            "lsr %0" "\n\t"
                           "adc %1,r1" "\n\t" //算了第二位

                           "lsr %0" "\n\t"
                            "adc %1,r1" "\n\t" //算了第三位

                            "lsr %0" "\n\t"
                            "adc %1,r1" "\n\t" //算了第四位 

                            "lsr %0" "\n\t"
                           "adc %1,r1" "\n\t" //算了第五位

                            "lsr %0" "\n\t" 
                           "adc %1,r1" "\n\t" //算了第六位

                           "lsr %0" "\n\t"
                            "adc %1,r1" "\n\t" //算了第七位

                           "lsr %0" "\n\t" 
                           "adc %1,r1" "\n\t" //算了第八位

                           "andi %1,0x01" "\n\t" //tmp &= 0x01
                            : "=d" (B),"=d" (tmp),"=d" (A)
                           : "0" (B),"1" (tmp),"2" (A)
                  );
                  return tmp;
         }
 
 这个方法中,我们加上return共花了22条指令,比起查表而言,已经是省了很多时钟和内存单元了。

(3)、算法:
 还有比数数还精简的代码吗?当然有,虽然精简的不多:)
我们知道,异或的法则是11为0,00为,10和01为1,这个方法的算法就是使用了异或来做的的,我们以0xA1这个数来做例子

          #define u08 unsigned char

         u08 AvrCalcP(u08 Data)
          {
                  u08 tmp1,tmp2;
 
                  asm volatile 
                  (
                           "mov %1,%0""\n\t"         //tmp1 = 0xA1  1010 0001
                           "swap %1""\n\t"             //tmp1 = 0x1A  0001 1010
                          "eor %1,%0""\n\t"           //tmp1 = 0xBB  1011 1011 
                          "andi %1,0x0f""\n\t"        //tmp1 = 0x0B  0000 1011
                          "mov %2,%1""\n\t"         //tmp2 = 0x0B
                           "andi %2,0x03""\n\t"     //tmp2 = 0x03  0000 0011
                          "lsl %1""\n\t"  
                           "lsl %1""\n\t"                  //tmp1 = 0x02  0000 0010
                          "eor %1,%2""\n\t"           //tmp1 = 0x01  0000 0001
                          "mov %2,%1""\n\t"         //tmp2 = 0x01
                          "andi %2,0x01 ""\n\t"     //tmp2 = 0x01  0000 0001
                          "lsl %1""\n\t"                   //tmp1 = 0x00  0000 0000
                          "eor %1,%2 ""\n\t"          //tmp1 = 0x00  0000 0001
                          "andi %1,0x0f""\n\t"       //tmp1 = 0x01 
                          : "=d" (Data),"=d" (tmp1),"=d" (tmp2)
                          : "0" (Data),"1" (tmp1),"2" (tmp2)
                  );
                    return tmp1;
           } 

 这个方法中,我们加上return共花了15条指令,比方法2来讲,又省了7条指令。

评论 (2)Add Comment
转载请注明出处
作者: fcdpj, 2007年 11月 17日 06小时 58分
谢谢
gf
作者: 测试, 2007年 11月 18日 17小时 51分
ghf

输入评论内容
quote
bold
italicize
underline
strike
url
image
quote
quote
Smiley
Smiley
Smiley
Smiley
Smiley
Smiley
Smiley
Smiley
Smiley
Smiley
Smiley
Smiley

security code
输入验证码


busy
最近更新 ( 2007-11-18 )
 
< 上一篇   下一篇 >

© 2009 杭州福芯电子 浙ICP备05040812号
Joomla!是基于GNU/GPL许可发行的免费软件.