⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demo_5_3.asm

📁 AVR单片机嵌入式系统原理与应用实践例码
💻 ASM
字号:
;******************************************************** 
;AVR汇编程序实例:Demo_5_3.asm 
;简易带1/100秒的24小时制时钟 
;Mega16  4MHz 
;********************************************************
 
.include "m16def.inc"				;引用器件I/O配置文件 

;定义程序中使用的变量名(在寄存器空间)
.def count		=	r18				;循环计数单元 
.def position   =	r19				;LED显示位指针,取值为0-7 
.def p_temp		=	r20				;LED显示位选,其值取反由PC口输出 
.def count_10ms	=	r21				;10ms计数单元 
.def flag_2ms	=	r22				;2ms到标志 
.def temp		=	r23				;临时变量 
.def temp1		=	r24				;临时变量 
.def temp_int	=	r25				;临时变量(在中断中使用) 

;中断向量区定义,flash程序空间$000-$029 
.org $000 
   rjmp reset		;跳转到上电复位处理 
   nop 
   reti      ;IRQ0 Handler 
   nop 
   reti      ;IRQ1 Handler 
   nop 
   reti      ;Timer2 Compare Handler 
   nop 
   reti      ;Timer2 Overflow Handler 
   nop 
   reti      ;Timer1 Capture Handler 
   nop 
   reti      ;Timer1 Compare-A Handler 
   nop 
   reti      ;Timer1 Compare-B Handler 
   nop 
   rjmp time1_ovf   ;跳转到Timer1溢出中断服务 
   nop 
   reti      ;Timer0 Overflow Handler 
   nop 
   reti      ;SPI Transfer Complete Handler 
   nop 
   reti      ;USART RX Complete Handler 
   nop 
   reti      ;USART UDR Empty Handler 
   nop 
   reti      ;USART TX Complete Handler 
   nop 
   reti      ;ADC Conversion Complete Handler 
   nop 
   reti      ;E2PROM Ready Handler 
   nop 
   reti      ;Analog Comparator Handler 
   nop 
   reti      ;Two-wire Serial Interface Handler 
   nop 
   reti      ;IRQ2 Handler 
   nop 
   reti      ;Timer0 Compare Handler 
   nop 
   reti      ;SPM Ready Handler 
   nop       

;程序开始 
.org $02A 
reset:  
   ldi r16,high(RAMEND)		;设置堆栈指针高位 
   out sph,r16 
   ldi r16,low(RAMEND)		;设置堆栈指针低位 
   out spl,r16 
    
   ser temp          
   out ddra,temp			;设置PORTA为输出,段码输出 
   out ddrc,temp			;设置PORTC为输出,位码控制 
   out portc,temp			;PORTC输出$FF, 无显示 

   ldi position,0x00		;段位初始化为1/100秒低位 
   ldi p_temp,0x01			;LED第1位亮 

;初始化时钟时间为11:59:55:00 
   ldi xl,low(time_buff)	; 
   ldi xh,high(time_buff)	;X寄存器取得时钟单元首指针 
   ldi temp,0x00 
   st  x+,temp      		;1/100秒 = 00 
   ldi temp,0x55 
   st  x+,temp      		;秒 = 55 
   ldi temp,0x59 
   st  x+,temp    			;分 = 59 
   ldi temp,0x11 
   st  x,temp				;时 = 11 

   ldi temp,0xff			;T1初始化,每隔2ms中断一次 
   out tcnt1h,temp 
   ldi temp,0x83 
   out tcnt1l,temp 
   clr temp 
   out tccr1a,temp 
   ldi temp,0x03			;4M,64分频 2ms 
   out tccr1b,temp 
   ldi temp,0x04 
   out timsk,temp			;允许T1溢出中断 
   sei						;全局中断允许 

;主程序 
main: 
   cpi flag_2ms,0x01		;判2ms到否 
   brne main				;No,转main循环 
   clr flag_2ms				;到,请2ms标志 
   rcall display			;调用LED显示时间(动态扫描显示一位) 
d_10ms_ok: 
   cpi count_10ms,0x05		;判10ms到否 
   brne main				;No,转main循环 
   clr count_10ms			;10ms到,清零10ms计数器 
   rcall time_add			;调用时间加10ms调整 
   rcall put_t2d			;将新时间值放入显示缓冲单元 
   rjmp main				;转main循环 

;LED动态扫描显示子程序,2ms执行一次,一次点亮一位,8位循环 
display: 
   clr r0 
   ser temp						;temp = 0x11111111 
   out portc,temp				;关显示,去消影和拖尾作用 
   ldi yl,low(display_buff) 
   ldi yh,high(display_buff)	;Y寄存器取得显示缓冲单元首指针 
   add yl,position				;加上要显示的位值 
   adc yh,r0					;加上低位进位 
   ld temp,y					;temp中为要显示的数字 

   clr r0 
   ldi zl,low(led_7 * 2) 
   ldi zh,high(led_7 * 2)		;Z寄存器取得7段码组的首指针 
   add zl,temp					;加上要显示的数字 
   adc zh,r0					;加上低位进位    
   lpm							;读对应七段码到R0中 
   out porta,r0					;LED段码输出 

   mov r0,p_temp 
   com r0 
   out portc,r0      ;输出位控制字,完成LED一位的显示 
    
   inc position      ;调整到下一次显示位 
   lsl p_temp 
   cpi position,0x08 
   brne display_ret 
   ldi position,0x00 
   ldi p_temp,0x01 
display_ret: 
   ret 

;时钟时间调整,加0.01秒 
time_add: 
   ldi xl,low(time_buff)	; 
   ldi xh,high(time_buff)	;X寄存器为时钟单元首指针 
   rcall dhm3				;ms单元加1调整 
   cpi temp,0x99        	; 
   brne time_add_ret		;未到99ms返回 
   rcall dhm				;秒单元加1调整 
   cpi temp,0x60 
   brne time_add_ret		;未到60秒返回 
   rcall dhm				;分单元加1调整 
   cpi temp,0x60 
   brne time_add_ret		;未到60分返回 
   rcall dhm				;时单元加1调整 
   cpi temp,0x24 
   brne time_add_ret		;未到24时返回 
   clr temp 
   st x,temp				;到24时,时单元清另 
time_add_ret: 
   ret 

;低段时间清零,高段时间加1,BCD调整 
dhm:  clr temp				;当前时段清零 
dhm1: st  x+,temp			;当前时段清零,X寄存器指针加一 
dhm3: ld  temp,x			;取出新时段数据 
      inc temp				;加一 
      cpi temp,0x0A    		;若个位数码未到$0A(10) 
      brhs dhm2				;例如$58+1=$59,不须调整; 
      subi temp,0xFA		;否则做减$FA调整:例如$49+1-$FA=$50 
dhm2: st x,temp				;并将调整结果送回 
      ret 

;将时钟单元数据送LED显示缓冲单元中 
put_t2d: 
   ldi xl,low(time_buff)		; 
   ldi xh,high(time_buff)		;X寄存器时钟单元首指针 
   ldi yl,low(display_buff) 	
   ldi yh,high(display_buff)	;Y寄存器显示缓冲单元首指针 
   ldi count,4 					;循环次数 = 4 
loop: 
   ld   temp,x+					;读一个时间单元 
   mov   temp1,temp 
   swap temp1 
   andi temp1,0x0f				;高位BCD码 
   andi temp,0x0f				;低位BCD码 
   st y+,temp					;写入2个显示单元 
   st y+,temp1					;低位BCD码在前,高位在后 
   dec   count
   brne loop					;4个时间单元->8个显示单元 
   ret 

;T1时钟溢出中断服务 
time1_ovf: 
   in temp_int,sreg 
   push temp_int			;保护状态寄存器 
    
   ldi temp_int,0xff		;T1初始值设定,2ms中断一次 
   out tcnt1h,temp_int
   ldi temp_int,0x83
   out tcnt1l,temp_int
    
   inc count_10ms			;10ms计数器加一 
   ldi flag_2ms,0x01		;置2ms标志到 
    
    pop temp_int 
   out sreg,temp_int		;恢复状态寄存器 
   reti						;中断返回       
    
.CSEG		;LED七段码表,定义在Flash程序空间 
led_7:      ;7段码表 
.db 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07 
.db 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71    

;字 PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 共阴极 共阳极 
;    h   g   f   E   d   c   b   a       
;0   0   0   1   1   1   1   1   1   3FH  C0H 
;1   0   0   0   0   0   1   1   0   06H  F9H 
;2   0   1   0   1   1   0   1   1   5BH  A4H 
;3   0   1   0   0   1   1   1   1   4FH  B0H 
;4   0   1   1   0   0   1   1   0   66H  99H 
;5   0   1   1   0   1   1   0   1   6DH  92H 
;6   0   1   1   1   1   1   0   1   7DH  82H 
;7   0   0   0   0   0   1   1   1   07H  F8H 
;8   0   1   1   1   1   1   1   1   7FH  80H 
;9   0   1   1   0   1   1   1   1   6FH  90H 
;A   0   1   1   1   0   1   1   1   77H  88H 
;b   0   1   1   1   1   1   0   0   7CH  83H 
;C   0   0   1   1   1   0   0   1   39H  C6H 
;d   0   1   0   1   1   1   1   0   5EH  A1H 
;E   0   1   1   1   1   0   0   1   79H  86H 
;F   0   1   1   1   0   0   0   1   71H  8EH 

.DSEG		;定义程序中使用的变量位置(在RAM空间) 
.ORG     $0060 
display_buff:        ;LED显示缓冲区,8个字节 
.BYTE   0x00         ;LED 1 位显示内容 
.BYTE   0x00         ;LED 2 位显示内容 
.BYTE   0x00         ;LED 3 位显示内容 
.BYTE   0x00         ;LED 4 位显示内容 
.BYTE   0x00         ;LED 5 位显示内容 
.BYTE   0x00         ;LED 6 位显示内容 
.BYTE   0x00         ;LED 7 位显示内容 
.BYTE   0x00         ;LED 8 位显示内容

.org   $0068
time_buff:           ;时钟数据缓冲区,4个字节
.BYTE   0x00         ;1/100s单元
.BYTE   0x00         ;秒单元
.BYTE   0x00         ;分单元
.BYTE   0x00         ;时单元

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -