网站公告列表     本站正式改版推出,欢迎大家光临!!  [dycxin  2008年8月20日]        
加入收藏
设为首页
联系站长
您现在的位置: AVR单片机开发工具网 >> 文章中心 >> 入门篇 >> 正文
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
马潮老师关于正确配置AV
用PonyProg2000 for Win
ATMEGA8单片机—AVR,AVR
AVR系列单片机简介—AVR
STK500使用说明操作步骤
AVR JTAGICE的详细使用说
AVR单片机从零开始—AVR
AVR Studio 调试快速入门
AVR 性能简介—AVR,AVR单
AVR芯片入门知识—AVR,A
  AVR起步教程3:从51到AVR编程篇—AVR,起步教程,AVR单片机,GCC,51到AVR           
AVR起步教程3:从51到AVR编程篇—AVR,起步教程,AVR单片机,GCC,51到AVR
作者:佚名 文章来源:不详 点击数: 更新时间:2008-8-22 9:35:55
本文介绍了51和AVR在汇编编程上的移植

一、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条指令。

文章录入:dycxin    责任编辑:dycxin 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      开发板精品推荐
     
    AVR单片机开发工具网--东营市荣燕商贸有限公司版权所有 站长:阿荣
    联系电话:0546-7870320,13371507828 电邮:51edacn@163.com
    山东东营西城济南路百祥电脑商城B302室 邮编:257000 鲁ICP备07018763号
    公司帐号:1615011209000037682 户名:东营市荣燕商贸有限公司 开户行:工行西城支行石油大学分理处