新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > AVR起步教程:從51到AVR編程篇

        AVR起步教程:從51到AVR編程篇

        作者: 時間:2016-10-07 來源:網絡 收藏

          本文介紹了在匯編編程上的移植

        本文引用地址:http://www.104case.com/article/201610/310916.htm

          一、DPTR的處理

          在系統中,DPTR是十分重要的,可以通過DPTR尋址,臨時儲存16位數據等等,下面僅僅先介紹2種51到程序移植中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

          中可以移植成:

          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" "nt" //保存A

          "clc" "nt" //清C標志

          "eor r1,r1" "nt"

          "mov %1,r1" "nt"

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第一位

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第二位

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第三位

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第四位

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第五位

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第六位

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第七位

          "lsr %0" "nt"

          "adc %1,r1" "nt" //算了第八位

          "andi %1,0x01" "nt" //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""nt" //tmp1 = 0xA1 1010 0001

          "swap %1""nt" //tmp1 = 0x1A 0001 1010

          "eor %1,%0""nt" //tmp1 = 0xBB 1011 1011

          "andi %1,0x0f""nt" //tmp1 = 0x0B 0000 1011

          "mov %2,%1""nt" //tmp2 = 0x0B

          "andi %2,0x03""nt" //tmp2 = 0x03 0000 0011

          "lsl %1""nt"

          "lsl %1""nt" //tmp1 = 0x02 0000 0010

          "eor %1,%2""nt" //tmp1 = 0x01 0000 0001

          "mov %2,%1""nt" //tmp2 = 0x01

          "andi %2,0x01 ""nt" //tmp2 = 0x01 0000 0001

          "lsl %1""nt" //tmp1 = 0x00 0000 0000

          "eor %1,%2 ""nt" //tmp1 = 0x00 0000 0001

          "andi %1,0x0f""nt" //tmp1 = 0x01

          : "=d" (Data),"=d" (tmp1),"=d" (tmp2)

          : "0" (Data),"1" (tmp1),"2" (tmp2)

          );

          return tmp1;

          }

          這個方法中,我們加上return共花了15條指令,比方法2來講,又省了7條指令。



        關鍵詞: 51 AVR

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 东莞市| 上虞市| 张家口市| 永胜县| 中江县| 柳州市| 清河县| 金乡县| 白山市| 大荔县| 合阳县| 天气| 尚志市| 大兴区| 疏附县| 黄龙县| 丽江市| 雷州市| 莆田市| 保德县| 陇西县| 永顺县| 华安县| 包头市| 白河县| 诸暨市| 柞水县| 黄浦区| 抚宁县| 大港区| 汝城县| 称多县| 梅河口市| 尼木县| 新民市| 蓬莱市| 金阳县| 蒲城县| 平利县| 玛多县| 莎车县|