ImageVerifierCode 换一换
格式:DOCX , 页数:22 ,大小:21.84KB ,
资源ID:7777192      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7777192.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(AVR程序释疑.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

AVR程序释疑.docx

1、AVR程序释疑把寄存器R0R29置$FF,把SRAM $0060 $006F单元清0, 把$0070$007F单元置$FF, 把$0080$008F单元分别设置为0F.includem8def.inc;包含m8def.inc文件.org $0000 ;代码起始端定位rjmp MAIN ;跳转到主程序.equ data1=$00ff ;设置符号项等于一个表达式.org $0013 ;代码段定位,跳过中断向量区MAIN:;初始化堆栈指针,对所有带SRAM的AVR单片机,堆栈指针必须设置在SRAM最后的地址ldi r16,high(RAMEND) ;取 RAMEND 的高位字节到r16out SPH

2、,r16 ;将RAMEND的高位送堆栈寄存器SP高位字节中 ldi r16,low(RAMEND) ;取 RAMEND 的低位字节到r16out SPL,r16 ;将RAMEND的低位送堆栈寄存器SP低位字节中 ;把寄存器R0R29置0xFFLdi r16,low(data1) ;取data1的低位字节到r16part1:st z+,r16 ;加载间接寻址数据,然后地址加一,即(Z) Rr, Z Z + 1。Z的初始指向是R0cp r29,r16 ;比较,r29-r16brne part1 ; 如果不相等,转到part1;把SRAM 0x60 0x6F单元清0。为什么这里的X寄存器需要分高位和

3、低位?.set datad=$0060 ;设置一个与表达式值相等的符号,能在后面的程序中重新改变设置.set datau=$006fldi r30,high(data1) ;取data1的高位字节到r30,r30是Z寄存器低字节 ldi xl,low(datad) ;取datad低位字节到X寄存器低字节,就是r26ldi xh,high(datad) ;取datad高位字节到X寄存器高字节,就是r27ldi r16,low(datau) ;取datau的低位字节到r16part2:cp xl,r16 ;比较xl和r16st x+,r30 ;以间接寻址方式存储数据,然后地址加一,(X) Rr,

4、X X + 1brne part2 ;如果不相等转到part2;把0x700x7F单元置0xFF.set datad=$0070.set datau=$007fldi r31,low(data1) ;R31是Z寄存器高字节,纯粹用作数据寄存,因为R0R29已被设置了ldi yl,low(datad)ldi yh,high(datad)ldi r17,low(datau)part3:cp yl,r17st y+,r31brne part3;nop;0x800x8F单元分别设置为0F .set datad=$0080.set datau=$0090Ldi r16,$00 ldi zl,low(da

5、tad)ldi zh,high(datad)ldi r17,low(datau)part4:st z+,r16 ;加载间接寻址数据,然后地址加一,即(Z)Rr, Z Z + 1。Z的初始地址是R0inc r16 ;r16r16+1cp zl,r17brne part4;nophere: rjmp here把SRAM地址为$0060开始的256个单元内容依次复制到地址为$0100开始的单元(注意两数据区有部分重叠)includem8def.inc.org $0000rjmp MAIN.set srm1=$0160 ;注意这是十六进制.set srm2=$0200.org $0013MAIN:;初

6、始化堆栈指针ldi r16,low(ramend)out spl,r16ldi r16,high(ramend)out sph,r16;设置指针地址ldi zl,low(srm1)ldi zh,high(srm1)ldi xl,low(srm2)ldi xh,high(srm2)ldi r16,-1 ;因为立即数最大只能设255,要复制256个数据,只能初始设为-1rcall subroutinehere: rjmp here;调用子程序完成复制subroutine:ld r0,-z ;地址减一后加载间接寻址数据Z Z - 1, R0 (Z).;为什么减一呢,因为复制的数据有重叠,为了完整复制

7、,就从末尾往前,避免遗失数据。st -x,r0 ;地址减一后以间接寻址方式存储数据X X - 1, (X) R0inc r16cpi r16,255brne subroutineret把Flash程序存储器中地址为0x003开始的10个字单元内容传送到SRAM(先低字节,后高字节)。.includem8def.inc.org $0000rjmp MAIN.set flh=$0003.set srm=$0070.org $0013MAIN:Ldi r16,low(ramend)out spl,r16ldi r16,high(ramend)out sph,r16;设置Z指针对应于flash地址的值

8、ldi zl,low(flh*2) ; 一个单位的flash存储位置,其实占用两个位置的地址栏ldi zh,high(flh*2)ldi xl,low(srm)ldi xh,high(srm)ldi r16,0subroutine:lpm r0,z+ ;加载程序空间的数据,然后地址加一R0 (Z), Z Z+1lpm r1,z+ ; 正因为是16位,每次的赋值只能赋8位,所以要赋2次才能完成8+8=16的赋值过程st x+,r0 ; 因为atmega系列的单片机不支持内存to内存的赋值方式,所以要用寄存器做中继,可以看到,不管是从flash到reg,还是reg到sram,每一个值都用了两步st

9、 x+,r1inc r16cpi r16,10brne subroutinehere: rjmp here用I/O引脚驱动若干个LED,编写跑马灯程序.includem8def.inc.org $0000.set left=1;left = 1就是left=0b00000001,也就是八个led灯仅有最右一个是高电平,我估计你们那块板子的灯是高电平点亮的,这样的话如果让left生效则点亮最右一盏灯,这样往后向左一步步循环嘛.set right=0b10000000;同上,这就是点亮最左一盏灯,这样向右才能做rjmp MAIN.org $0013MAIN:ldi r16,low(ramend);

10、设置堆栈地址out spl,r16ldi r16,high(ramend)out sph,r16;设置D端口为输出ldi r19,$ff out ddrd,r19ldi r21,rightldi r20,left;实现LED灯从左到右依次闪烁part1:out portd,r20rcall delay;延时,避免移太快,眼睛有视觉延迟,太快了看上去就是全亮的lsl r20;这条命令是r20循环左移一位,换一个灯brcc part1; 实现LED灯从右到左依次闪烁part2:out portd,r21rcall delaylsr r21;这就是循环右移一位,其他的和part1一样,你看两条命令就

11、很明显l代表left,r代表rightbrcc part2;初始化寄存器状态并循环ldi r21,right;赋值,把right变量的赋给r21,left赋给20ldi r20,left;初始化寄存器状态并循环ldi r21,rightldi r20,lefthere: rjmp part1;延时程序delay:ldi r16,0x00;赋值ldi r17,0x00ldi r18,0x00delay1:inc r16 ;delay1做到的就是进来的时候,r16是00.先做一步自增一,变成01,然后每次和r18相比(00),如果不同则继续循环delay1,这就意味着r16要从00自增到ff然后继

12、续自增1才会跳转到00,这不就执行了ff次的delay1么cp r16,r18brne delay1inc r17;做到了ff次的delay1的前三句之后,让r17自增1,然后同上,需要r17自增到ff再自增一次跳转到00才能结束延时程序,就是说要做ff*ff次的delay1前三句才能完成延时子程序噻这就是延时的真谛cp r17,r18brne delay1clc ;清零C标志位ret把Flash中地址为$013开始的20个字单元内的数据代码作为20个16位二进制符号数,将它们分别取绝对值后存储到SRAM中起始地址为$0100的区域,要求低字节在前,高字节在后。.include m8def.i

13、nc.org $0000.equ flh=$013.equ srm=$100rjmp main.org $0013main:ldi r16,low(ramend);设置堆栈地址out spl,r16ldi r16,high(ramend)out sph,r16ldi zl,low(flh*2)ldi zh,high(flh*2)ldi xl,low(srm)ldi xh,high(srm)ldi r18,0part1:lpm r22,z+ ;取数后,Z加一lpm r23,z+rcall part2 ;调用取绝对值子程序store: st x+,r22;存数后,X加一st x+,r23inc r

14、18cpi r18,20brne part1here: rjmp herepart2: TST R23 ; 测寄存器为零或者负 BRPL store ;为正转移 SUBI R22,1;r22里面存的是负数的补码,补码是原码取反加一,所以要减去这个加上去的一,然后获得负数的原码 SBCI R23,0;这个是此负数的高八位,因为负数比较大所以需要两个寄存器存储 COM R22;对高位取反 COM R23;对低位取反,取反后得到负数的正数形式的原码,正数的补码即为其原码,所以得到绝对值Ret已知SRAM ADDR($0062)为起始地址的数据块的数据是无符号数,块长在LEN($0061)单元。求最大

15、值并存入MAX($0060)单元 .include m16def.inc.SET LEN=$0061.SET ADDR=$0062.SET MAX=$0060.ORG $000RJMP START.ORG 0X002ASTART:LDS R20,LEN ;r20存入数据块长CLR R16 ;r16清零LDI XL,LOW(ADDR) ;X指针指向数据起始LDI XH,HIGH(ADDR)LOOP: LD R18,X+ ;X件址取数后加一CP R18,R16 ;比较R18和R16,如果R18小于R16,则跳转到next,否则R18数据送到R16BRCS NEXT ;BRLO MOV R16,R1

16、8NEXT:DEC R20 ;r20减一,数据块长减一BRNE LOOP ;跳回loop,没有遍历所有数据则跳回loop继续STS MAX,R16 ;R16的数据送maxhere:rjmp here.exit无符号数求最小值.include m16def.inc.SET LEN=$0061.SET ADDR=$0062.SET MIN=$0060 .ORG $000RJMP START.ORG 0X002ASTART: LDS R20,LENSER R16 ;设置最大值,R16置为255,即11111111LDI XL,LOW(ADDR)LDI XH,HIGH(ADDR)LOOP: LD R1

17、8,X+CP R16,R18 BRCS NEXT ;比较R18和R16,如果R16大于R18,则R18送R16,否则跳转至next;够减则C位为1,BRCS是进位标志位C为1转移MOV R16,R18NEXT: DEC R20BRNE LOOPSTS MIN,R16 here:rjmp here.exit已知SRAM ADDR($0062)为起始地址的数据块的数据是符号数,块长在LEN($0061)单元。求最大值并存入MAX($0060)单元 .include m16def.inc.SET LEN=$0061.SET ADDR=$0062.SET MAX=$0060.ORG $000RJMP

18、START.ORG 0X002ASTART:LDS R20,LENLDI R16,$80 ;八位有符号数的范围是-128+128,怎么判断我这里存入的比较数值是-128?LDI XL,LOW(ADDR)LDI XH,HIGH(ADDR)LOOP: LD R18,X+ CP R18,R16 BRLT NEXT ;如果R18小于R16,则跳转next,否则R18送R16MOV R16,R18NEXT:DEC R20BRNE LOOPSTS MAX,R16here:rjmp here.exit有符号数求最小值.include m8def.inc.SET LEN=$0061.SET ADDR=$006

19、2.SET MIN=$0060 RJMP START.ORG 0X002ASTART: LDS R20,LENLDI R16,$7F ;设置最大值,$7F=127LDI XL,LOW(ADDR)LDI XH,HIGH(ADDR)LOOP: LD R18,X+CP R16,R18 ;如果R18小于R16,则跳转next,否则R18送R16BRLT NEXT ;BRLT小于转移MOV R16,R18NEXT: DEC R20BRNE LOOPSTS MIN,R16 here:rjmp here.exit设SRAM中有个数据块(起始地址为$0061,块长放在$0060单元),数据块内每个字节单元含有

20、两个十六进制数(高4位和低4位),试分别求出这些十六进制数的ASCII码,并放在SRAM中以$0163为起始地址的区域,要求低4位数的ASCII码在前,高4位数的ASCII码在后。.include m8def.inc.SET LEN=$0060.SET BLOCK1=$0061.SET BLOCK2=$0163.ORG $000RJMP MAINASCTAB: .DB $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$41,$42,$43,$44,$45,$46.ORG 0X002A;十六进制和ASCII码的转换, 30H-39H 为 0-9 的 Ascii 码

21、,41H-46H 为 A-F 的 Ascii码,将十六进制对应地加上去就是了MAIN: ldi r16,low(ramend)out spl,r16ldi r16,high(ramend)out sph,r16LDS R25,LENLDI XL,LOW(BLOCK1)LDI XH,HIGH(BLOCK1)LDI YL,LOW(BLOCK2)LDI YH,HIGH(BLOCK2)LOOP: LDI ZL,LOW(ASCTAB*2)LDI ZH,HIGH(ASCTAB*2)CLR R18LD R17,XANDI R17,$0F ;取十六进制数低位;andi是与立即数,这个语句的目的就是把R17里面

22、的低位留下,高位清零,比如R17=$23,andi之后,R17=$03ADD ZL,R17 ;低位,无进位加法ADC ZH,R18 ;高位,带进位加法,其实R18就是0,这里是保险的做法 LPM R17,Z ;转换为ASCII码ST Y+,R17LD R17,X+ ANDI R17,$F0 ;取十六进制数高位SWAP R17 ;半字节交换,因为后面的加法运算不能直接跳过低位在高位运算,所以必须交换,而两个十六进制数(高4位和低4位),只需要转换后按照高低顺序存入新的区域便可,转换后的是ascii码要用8位来存,所以不存在交换的问题。LDI ZL,LOW(ASCTAB*2)LDI ZH,HIGH

23、(ASCTAB*2)ADD ZL,R17ADC ZH,R18LPM R17,ZST Y+,R17DEC R25BRNE LOOPHERE: RJMP HERE设SRAM中$0060和$0061单元存储的是一个16位二进制无符号数(高字节在前),试调用代码转换子程序和延时子程序,把这个数转换成十进制数(即BCD码),并把其万、千、百、十、个位用一个数码管轮流显示出来,每位显示时间约1秒钟.includem8def.inc.equ data=$0060.org $0000rjmp maintab1:.db $3f,$06,$5b,$4f,$66,$6d,$7d,$07,$7f,$6f .org $

24、0013main:ldi r16,low(ramend)out spl,r16ldi r16,high(ramend)out sph,r16ldi r16,$ffout ddrd,r16ldi r16,$64 ;预设数值为13412sts data,r16ldi r16,$34sts data+1,r16lds r16,datalds r17,data+1rcall b16td5;显示数字start:mov r18,r24rcall cqbrcall delaymov r18,r23rcall cqbrcall delaymov r18,r22rcall cqbrcall delaymov r

25、18,r21rcall cqbrcall delaymov r18,r20rcall cqbrcall delayhere:rjmp hereb16td5:ser r24 ;r24 先送 -1loop1:inc r24 ;r24 增 1subi r16,low(10000)sbci r17,high(10000) ;(r17:r16)10000brcc loop1 ;够减则返回 loop1subi r16,low(-10000)sbci r17,high(-10000) ;不够减,加10000恢复余数ser r23loop2:inc r23subi r16,low(1000)sbci r17,

26、high(1000)brcc loop2subi r16,low(-1000)sbci r17,high(-1000)ser r22loop3:inc r22subi r16,low(100)sbci r17,high(100)brcc loop3subi r16,low(-100)sbci r17,high(-100)ser r21loop4:inc r21subi r16,low(10)brcc loop4subi r16,low(-10)ser r20loop5:inc r20subi r16,low(1)brcc loop5subi r16,low(-1) ;其实个位可以直接送retc

27、qb:ldi zl,low(tab1*2)ldi zh,high(tab1*2)add zl,r18lpm out portd,r0ret;延迟0.5S,书上虽然这么说,但是个人认为延迟1.5s了delay1: ldi r16,100ldi r17,200ldi r25,200dec r25brne delay1+3dec r17brne delay1+2dec r16brne delay1+1ret;延迟1Sdelay:rcall delay1rcall delay1采用外部中断的方式对按键次数实现计数。计数值由一个共阴数码管来显示,初值为0。每按键一次,计数值增1计到F后,再按键一次则回0

28、。画出电路图。.include m8def.inc.def temp = r23 ;临时变量 .def counter = r24 ;计数变量 ;中断向量区配置,FLASH空间$000$028.org $000rjmp RESET ; 复位处理rjmp EXT_INT0 ;中断向量.org $02ARESET: ; 上电初始化程序 ldi r16, high(RAMEND) out SPH, r16 ldi r16, low(RAMEND) out SPL, r16 ; 设置堆栈指针为RAM 的顶部 ser temp out ddrb, temp ; 设置portb为输出,段码输出 out p

29、ortb,temp ; 设置portb输出全1 ldi temp, 0x0a out mcucr, temp ; INT0、INT1下降沿触发 ldi temp, 0xc0 out gicr, temp ; 允许INT0、INT1中断 out gifr, temp ; 清除INT0、INT1中断标志位cbi ddrd,2 clr counter sei ; 使能中断MAIN: clr r0 ldi zl, low(led_7 * 2) ldi zh, high(led_7 * 2) ; Z寄存器取得7段码组的首指针 add zl,counter ; 加上要显示的数字 adc zh,r0 ; 加上低位进位 lpm ; 读对应七段码到R0中 out portb, r0 ; LED段码输出 rjmp MAIN ; 循环显示EXT_INT0: in temp, sreg push temp ; 中断现场保护 inc counter ; 计数单元加1 cpi counter, 0x10 ; 与16比较 brne EXT_INT0_RET ; 小于16转中断返回 clr counter ; 计数单元清0 EXT_

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1