微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > AVR起步教程:从51到AVR编程篇

AVR起步教程:从51到AVR编程篇

时间:10-07 来源:互联网 点击:

本文介绍了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" "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"

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top