《AVR单片机420100326.ppt》由会员分享,可在线阅读,更多相关《AVR单片机420100326.ppt(35页珍藏版)》请在三一文库上搜索。
1、AVR单片机原理及应用,陈渊睿 Tel: 13002086301 E-mail: 华南理工大学电力学院,第四章,汇编语言程序设计,4.1 汇编语言基础,汇编语言源文件是由汇编语言代码和汇编程序指令所组成的ASCII 字符文件。 汇编语言源文件包括指令助记符、标号和伪指令。指令助记符和伪指令常带操作数 4.1.1 汇编语句格式 程序输入行有下列种形式: 【标号】伪指令【操作数】【注释】。 【标号】指令【操作数】【注释】。 注释。 空行。,例子: Label: .EQU Var1=100 ;置Var1 等于100 伪指令 .EQU Var2=200 ;置Var2 等于200 test: rjmp
2、 test ;无限循环指令 ;纯注释行 注意:不限制有关标号伪指令注释或指令的列位置,4.1.2汇编器伪指令,伪指令并不直接转换成操作数,而是用于调整存储器中程序的位置,定义宏,初始化存储器等,表达式 汇编器的表达式由操作数、运算符和函数组成。所有的表达式内部为32位(二进制) 操作数 (1)用户定义的标号,该标号给出了放置标号位置的定位计数器的值 (2)用户用SET伪指令定义的变量 (3)用户用EQU伪指令定义的常数 (4)整数常数,包括下列几种形式 十进制缺省值10 255 十六进制数二进制表示法0x0a,$0a,0xff.$ff 二进制数0b00001010,0b11111111 (5)
3、PC, 程序存储器定位计数器的当前值,汇编器的函数(而非单片机内的函数) 有LOW、HIGH、BYTE2、BYTE3 汇编器所认的运算符,4.2 简单与分支程序设计,4.2.1 简单程序设计 也称顺序程序或直接程序 .include “m8def.inc” ldi xl,$61 ldi xh,$00 lds r16,$0060 mov r17,r16 andi r16,$0f ori r16,$30 st x+,r16,swap r17 andi r17,$0f ori r17,$30 st x+,r17 here: rjmp here .exit,4.2.1 分支程序设计 又称散转程序 .i
4、nclude “m8def.inc” .SET VAR=0X0070 .SET FUNC=0X0071 .ORG $000 RJMP MAIN .ORG 0X0013 MAIN:LDS R16,VAR TST R16 BREQ DONE BRPL POSI LDI R16,$FF ;R16-1 RJMP DONE,POSI:LDI R16,$01 DONE:STS FUNC,R16 HERE: RJMP HERE .EXIT,4.3 循环与查表程序设计,4.3.1 循环程序设计 例4.9:已知SRAM ADDR($0062)为起始地址的数据块的数据是无符号数,块长在LEN($0061)单元。求
5、最大值并存入MAX($0060)单元 .include “m8def.inc” .SET LEN=$0061 .SET ADDR=$0062 .SET MAX=$0060 .ORG $000 RJMP START .ORG 0X0013 START:LDS R20,LEN CLR R16 LDI XL,LOW(ADDR) LDI XH,HIGH(ADDR) LOOP: LD R18,X+ CP R18,R16,BRCS NEXT ;BRLO MOV R16,R18 NEXT: DEC R20 BRNE LOOP STS MAX,R16 here: rjmp here .exit,例4.9:已知
6、SRAM ADDR($0062)为起始地址的数据块的数据是符号数,块长在LEN($0061)单元。求最大值并存入MAX($0060)单元 .include “m8def.inc” .SET LEN=$0061 .SET ADDR=$0062 .SET MAX=$0060 .ORG $000 RJMP START .ORG 0X0013 START:LDS R20,LEN LDI R16,$80 LDI XL,LOW(ADDR) LDI XH,HIGH(ADDR) LOOP: LD R18,X+ CP R18,R16,BRLT NEXT MOV R16,R18 NEXT: DEC R20 BRN
7、E LOOP STS MAX,R16 here: rjmp here .exit,4.3.2 查表程序设计 用于不便于计算的函数(如平方、立方、三角函数)、固定的编码(如ASCII码、数码管显示)等,表格存于FLASH中,用LPM指令来取出对应项的值 例:设SRAM的0x60开始的40个单元字节存放有40个取值为09的二进制整数。将它们求平方值后存放到SRAM的0x100开始的存储区。 .include “m8def.inc” rjmp Main Tab: .db 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 Main: ldi yl, 0x00 ;SRAM存储基址 l
8、di yh, 0x01 ldi xl, 0x60 ;SRAM取数基址 ldi xh, 0x00 ldi r18, 40 ;计数用 loop: ld r16, x+ ;从SRAM取数,地址增1,ldi zl, low(Tab*2) ldi zh, high(Tab*2) clr r17 add zl, r16 adc zh,r17 lpm ;查平方值 st y+, r0 ;保存到SRAM并且地址增1 dec r18 ;计数减1 brne loop ;未查完,循环 HERE: RJMP HERE .EXIT,例4.13:已知SRAM中起始地址为BLOCK1的数据块(其长度存放在LEN单元),每个存
9、储单元中高、低4位为两个十六进制数,将它们转换为ASCII码后存放在BLOCK2开始的连续存储单元。 .include “m8def.inc” .SET LEN=$0060 .SET BLOCK1=$0061 .SET BLOCK2=$0168 .ORG $000 RJMP MAIN .ORG 0X0013 MAIN: LDS R25,LEN LDI XL,LOW(BLOCK1) LDI XH,HIGH(BLOCK1) LDI YL,LOW(BLOCK2) LDI YH,HIGH(BLOCK2) LOOP: LDI ZL,LOW(ASTAB*2) LDI ZH,HIGH(ASTAB*2) CL
10、R R18 LD R17,X,ANDI R17,$0F ADD ZL,R17 ADC ZH,R18 LPM R17,Z ST Y+,R17 LD R17,X+ ANDI R17,$F0 SWAP R17 LDI ZL,LOW(ASTAB*2) LDI ZH,HIGH(ASTAB*2) ADD ZL,R17 ADC ZH,R18 LPM R17,Z ST Y+,R17 DEC R25 BRNE LOOP HERE:RJMP HERE ASCTAB:.DB $30,$31,$39 .DB $41,$42,$46,4.4 代码转换与子程序设计,4.4.1 子程序设计 子程序:完成确定任务、反复调用
11、入口地址(第一条指令地址,常用标号) 返回(RET) 状态保护(如SREG等) 参数传递(R0R31,或者堆栈方式) 例4.15 SRAM中HEX单元的两个十六进制数,分别转成ASCII码存入ASC和ASC+1单元 .INCLUDE “M8DEF.INC” .SET HEX=$0060 .SET ASC=$0061 LDI R17,LOW(RAMEND) OUT SPL,R17 LDI R17,HIGH(RAMEND) OUT SPH,R17,LDS R16,HEX PUSH R16 RCALL HASC POP R16 STS ASC,R16 LDS R16,HEX SWAP R16 PUS
12、H R16 RCALL HASC POP R16 STS ASC+1,R16 HERE:RJMP HERE,HASC:POP R16 POP R16 POP R16 ANDI R16,$0F LDI ZL,LOW(ASCTAB*2) LDI,ZH,HIGH(ASCTAB*2) ADD ZL,R16 LPM R16,Z PUSH R16 IN R16,SPL SBCI R16,2 OUT SPL,R16 RET ASCTAB:.DB $30,$31,$39 .DB $41,$42,$46,4.4.2代码转换子程序,BCD码(Binary-Coded Decimal),用二进制编码的十进制代码。这
13、种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷地进行。这种编码技巧,最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用 最常用的BCD编码,就是使用“0”至“9”这十个数值的二进码来表示。常称之为“8421码”。,补充知识,1、 16位二进制数转换成BCD码,程序功能: 将(r17:r16) 中16位二进制转换成 BCD 码, 个、十、百、千和万位分别存放于 r16, r17, r1
14、8, r19和r20中 程序思想: (r17:r16)10000 够减 X 次, 则万位为 X; 差值1000 够减 Y 次; 则千位为 Y;差值100 够减 Z 次; 则百位为 Y;差值10 够减 U 次; 则十位为 U;最后的差值为个位,程序清单: b16td5: ser r20 ;r20 先送 -1 loop1: inc r20 ;r20 增 1 subi r16,low(10000) ;(r17:r16)10000 sbci r17,high(10000) brcc loop1 ;够减则返回 loop1 subi r16,low(-10000) ;不够减,加10000 恢复余数 sbc
15、i r17,high(-10000),程序清单: ;(Continued) ser r19 ;r19 先送 -1 loop2: inc r19 ;r19 增 1 subi r16,low(1000) ;(r17:r16)1000 sbci r17,high(1000) brcc loop2 ;够减则返回 loop2 subi r16,low(-1000) ;不够减,加1000 恢复余数 sbci r17,high(-1000),程序清单: ;(Continued) ser r18 ;r18 先送 -1 loop3: inc r18 ;r18 增 1 subi r16,low(100) ;(r1
16、7:r16)100 sbci r17,high(100) brcc loop3 ;够减则返回 loop3 subi r16,low(-100) ;不够减,加100 恢复余数 sbci r17,high(-100),程序清单: ;(Continued) ser r17 ;r17 先送 -1 loop4: inc r17 ;r17 增 1 subi r16,10 ;(r17:r16)10 brcc loop4 ;够减则返回 loop4 subi r16,-10 ;不够减,加10 恢复余数 ret ;至此,r16即为个位,2、 5位BCD码转换成16位二进制数,程序功能: 将个、十、百、千和万位分别
17、放在r16, r17, r18, r19和r20中的5位BCD 码(r16r20高4位为0000)转换成16位二进制, 存放于(r17:r16) 中 转换公式为: (r17:r16)= r16+10*r17+100*r18+1000*r19+10000*r20,程序清单: d5tb16: tst r17 ;测试 r17 rjmp d5tb16_2 d5tb16_1: subi r16,-10 ;r16 加 10,不会发生进位 dec r17 ;r17 减 1 d5tb16_2: brne d5tb16_1 ;非 0 转 d5tb16_1,程序清单: ;(Continued) tst r18 ;
18、测试 r18 rjmp d5tb16_4 d5tb16_3: subi r16,low(-100) ;(r17:r16)加 100 sbci r17,high(-100) dec r18 ;r18 减 1 d5tb16_4: brne d5tb16_3 ;非 0 转 d5tb16_3,程序清单: ;(Continued) tst r19 ;测试 r19 rjmp d5tb16_6 d5tb16_5: subi r16,low(-1000) ;(r17:r16)加 1000 sbci r17,high(-1000) dec r19 ;r19 减 1 d5tb16_6: brne d5tb16_5
19、 ;非 0 转 d5tb16_5,程序清单: ;(Continued) tst r20 ;测试 r20 rjmp d5tb16_8 d5tb16_7: subi r16,low(-10000) ;(r17:r16)加 10000 sbci r17,high(-10000) dec r20 ;r20 减 1 d5tb16_8: brne d5tb16_7 ;非 0 转 d5tb16_7 ret,3、 5位压缩BCD码转换成16位二进制数,压缩BCD码与非压缩BCD码的区别:压缩BCD码的每一位用4位二进制表示,一个字节表示两位十进制数。例如10010110B表示十进制数96D;非压缩BCD码用1
20、个字节表示一位十进制数,高四位总是0000,低4位的00001001表示09.例如00001000B表示十进制数8 程序功能:将五位压缩BCD码转换为16位二进制。五位压缩BCD码存于r18:r17:r16 (r18 高四位为 0), 二进制存放于(r17:r16) 程序思想: 先将压缩 BCD 码转换为 BCD 码, 放到 r16(个)、r17(十)、r18(百)、r19(千)、r20(万) 5个字节中, 再调用d5tb16子程序即可,程序清单: yd5tb16: mov r20,r18 ;取出万位 mov r19,r17 ;令 r19=r17 mov r18,r17 ;令 r18=r17
21、mov r17,r16 ;令 r17=r16 andi r16,$0f ;取出个位 andi r17,$f0 swap r17 ;取出十位 andi r18,$0f ;取出百位 andi r19,$f0 swap r19 ;取出千位 rcall d5tb16 ;调用d5tb16五位BCD到16位二进制的转换 ret,4.5 运算程序设计,4.5.1 加减运算程序设计 1、无符号多字节加减运算程序 16位加法 add16: add r16,r18 ; r17:r16+r19:r18r17:r16 adc r17,r19 ret 16 位带立即数加法 addi16: subi r16,low(-a
22、ddi2) ;无立即数(字节)加法 ; r17:r16+addi2 r17:r16 sbci r17,high(-addi2) ;addi2 为 16 位立即数 ret,16位减法 sub16: sub r16,r18 ; r17:r16-r19:r18r17:r16 sbc r17,r19 ret 16 位带立即数减法 subi16: subi r16,low(subi2) ; r17:r16-subi2 r17:r16 sbci r17,high(subi2) ;subi2 为 16 位立即数 ret,16位比较 cp16: cp r16,r18 ; r17:r16 与 r19:r18 相
23、比较 cpc r17,r19 ret 16 位带立即数比较 cpi16: cpi r16,low(cp2) ; r17:r16 与 16 位立即数 cp2 相比较 ldi r18, high(cp2) cpc r17,r18 ret,16位取补程序 (求补码方法:取反后再加1) beg16: com r16 ;r17:r16 取补并回存 (先取反) com r17 subi r16,low(-1) ;再加1(通过减去-1实现) sbci r17,high(-1) ret 32位加法程序 ADD32: ;32 位加法程序 ADD R16,R20 ADC R17,R21 ADC R18,R22 A
24、DC R19,R23 ret,32位带立即数加法程序 SUBI32: ; SUBI R16,low(-data) SBCI R17,high (-data) SBCI R18,byte3 (-data) SBCI R19,byte4 (-data) ret 32位减法程序 SUB32: ;32 位减法程序 SUB R16,R20 SBC R17,R21 SBC R18,R22 SBC R19,R23 ret,2、带符号加减运算程序 例:16位二进制符号数(补码表示)加法 R17:R16 + R20:R19 R18:R17:R16 思路:先扩展为3字节,再加 SADD16: TST R17 BRMI NT1 CLR R18 RJMP NEXT1 NT1:LDI R18,$FF,NEXT1:TST R20 BRMI NT2 CLR R21 RJMP NEXT2 NT2: SER R21 NEXT2:ADD R16,R19 ADC R17,R20 ADC R18,R21 RET,