📄 mywork.asm
字号:
;By Laoliu
;利用定时中断,每秒钟LED数码管显示数字减1,
;For mega16,未经优化
;定时/计数器实现中断控制
;头文件及变量定义
.include "m16def.inc"
.def temp=r23
.def res=r24
.def T_flag=r25
.def T=r22
.def De=r17
.def p_temp=r20
.def position=r19
.def dis_num1=r18
.def dis_num=r21
.def T_coun=r16
;#######################################
;**************中断向量区***************
;#######################################
;如果对应的中断功能没用到,则用reti和nop填充(双字),可提高抗干扰性能
.org $000
jmp RESET ;复位处理
reti ;IRQ0中断向量
nop
reti ;IRQ1中断向量
nop
reti ;Timer2 比较中断向量
nop
reti ;Timer2 溢出中断向量
nop
reti ;Timer1捕捉中断向量
nop
reti ;Timer1比较A中断向量
nop
reti ;TIMER1比较B中断向量
nop
reti ;TIMER1溢出中断向量
nop
jmp Time_process ;TIMER0溢出中断向量
reti ;SPI传输结束中断向量
nop
reti ;USART RX结束中断向量
nop
reti ;UDR空中断向量
nop
reti ;USART TX结束中断向量
nop
reti ;ADC转换结束中断向量
nop
reti ;EEPROM就绪中断向量
nop
reti ;模拟比较器中断向量
nop
reti ;两线串行连接口中断向量
nop
reti ;IRQ2中断向量
nop
reti ;定时器0比较中断向量
nop
reti ;SPM就绪
nop
;################################################
;*******************代码区***********************
;################################################
.org $02a ;代码区起始地址0x002a,0x0000--0x0029是中断向量区
;\\\\\\\\\\\\\\\\\\\\\\
;\\\复位中断服务程序\\\
;\\\\\\\\\\\\\\\\\\\\\\
RESET:
ldi r16,high(RAMEND) ;堆栈指针指向ram终端
out SPH,r16
LDI r16,low(RAMEND) ;
out SPL,r16
clr temp ;初始化I/O端口
clr res
ldi temp,0x0f
ldi res,0x00
out ddrc,temp
out portc,res
ldi temp,0xff
ldi res,0x00
out ddrd,res
out ddrb,temp
out ddra,temp
out portb,temp
out porta,temp
out portd,temp
ldi temp,0xaa
ldi res,0x7c
ldi dis_num,0xff
mov r15,dis_num
mov r1,res
mov r5,temp
ldi temp,0x00 ;时钟:4MHz,分频系数:64,溢出中断周期:4ms
out tcnt0,temp
ldi temp,0x01 ;禁止输出比较匹配,开T/C0溢出中断
out timsk,temp
ldi temp,0x03 ;普通模式,PB3为普通I/O口,时钟源来自预分频1/64
out tccr0,temp
ldi De,96
ldi zl,low(led_7) ;SRAM首地址低8位
ldi zh,high(led_7) ;SRAM首地址高八位
ldi temp,0xc0 ;对SRAM中的变量赋值:0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 (共阳)
st z+,temp
ldi temp,0xf9
st z+,temp
ldi temp,0xa4
st z+,temp
ldi temp,0xb0
st z+,temp
ldi temp,0x99
st z+,temp
ldi temp,0x92
st z+,temp
ldi temp,0x82
st z+,temp
ldi temp,0xf8
st z+,temp
ldi temp,0x80
st z+,temp
ldi temp,0x90
st z+,temp
ldi temp,0x05 ;dis_n
st z+,temp
ldi temp,0x00
st z+,temp
ldi temp,0x00
st z+,temp
ldi temp,0x00
st z+,temp
ldi temp,0x05 ;Time
ldi res,0x00
ldi dis_num,0x00
ldi dis_num1,0x00
ldi p_temp,0x08
ldi position,0x00
ldi zl,low(led_7)
ldi zh,high(led_7)
sei
;\\\\\\\\\\\\\\\\\\\\\\\\\\\
;主函数,注意死循环的实现\\\\
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
main_0:
cpi T_flag,0xff
brne main_0
clr T_flag
rcall display
;\\\\\\\\\\\\\\\\\\\\\\
;\\\\时间计数器\\\\\\\\
;\\\\\\\\\\\\\\\\\\\\\\
Time_sec:
cpi T_coun,0x7c
brne j
com r5
out portb,r5
j:
cpi T_coun,0xf9 ;250次中断=1s
brne main_0
com r15
out portb,r15
clr T_coun
rcall Time_dec ;call与rcall有区别:call将pc+2后的值压入堆栈,而rcall则将pc+1后的值压入堆栈
rcall T_save
rjmp main_0 ;死循环至此
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;\\\\\时钟调整\\\\\\\\\\\\\\\\\\\\
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Time_dec:
cpi temp,0x00
breq T_1
dec temp
ret
T_1:
ldi temp,0x09
cpi res,0x00
breq T_2
dec res
ret
T_2:
ldi res,0x09
cpi dis_num,0x00
breq T_3
dec dis_num
ret
T_3:
ldi dis_num,0x09
cpi dis_num1,0x00
breq T_cli
dec dis_num1
ret
T_cli:
clr temp
clr res
clr dis_num
clr dis_num1
out tccr0,temp ;turn off T_Ovf
call light
ret
light:
ldi temp,0xaa
ldi res,0x55
ldi dis_num,0x80
ldi dis_num1,0xff
out portc,dis_num
out portb,temp
call delay
out portc,dis_num1
com temp
out portb,temp
call delay
rjmp light
;\\\\\\\\\\\\\\\\\\\\\\\
;\\\\存储时间\\\\\\\\\\\
;\\\\\\\\\\\\\\\\\\\\\\\
T_save:
ldi yl,low(dis_n)
ldi yh,high(dis_n)
st y+,temp
st y+,res
st y+,dis_num
st y,dis_num1
ret
;\\\\\\\\\\\\\\\\\\\\\\\
;定时计数器0溢出中断处理
;\\\\\\\\\\\\\\\\\\\\\\\
Time_process:
push res
push temp
in res,sreg
push res
ldi temp,0x00
out tcnt0,temp
inc T_coun
ldi T_flag,0xff
pop res
out sreg,res
pop temp
pop res
reti
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;\\\\\\\\\汇编通用延时子程序\\\\\\\\\
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Delay:
push De
Del1:
push De
Del2:
push De
Del3:
dec De
brne Del3
pop De
dec De
brne Del2
pop De
dec De
brne Del1
pop De
ret
;\\\\\\\\\\\\\\\\\\\
;\\\\动态扫描函数\\\\
;\\\\\\\\\\\\\\\\\\\\\
display:
clr r0
push temp
ser temp
out portc,temp ;turn off led_7
ldi yl,low(dis_n)
ldi yh,high(dis_n) ;显示缓存地址
add yl,position
adc yh,r0
ld temp,y ;取出要显示的数字
clr r0 ;根据要显示的数字去led_7码表中去数码
ldi zl,low(led_7)
ldi zh,high(led_7)
add zl,temp
adc zh,r0
ld temp,z ;要显示的数字的代码送到temp中
out porta,temp
mov r0,p_temp
com r0
out portc,r0 ;输出控制位
inc position
lsr p_temp
cpi position,0x04
brne dis_exit
ldi position,0x00
ldi p_temp,0x08
dis_exit:
pop temp
ret
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;\\\\\\\定义SRAM的变量\\\\\\\
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\
.dseg ;数据段预留存放数据的空间但不能赋值!!!!只能用.byte定义,.byte只能出现在.dseg 段中
.org $0060
led_7: ;七段数码管
.byte 1 ;'0'
.byte 1 ;'1'
.byte 1 ;'2'
.byte 1 ;'3'
.byte 1 ;'4'
.byte 1 ;'5'
.byte 1 ;'6'
.byte 1 ;'7'
.byte 1 ;'8'
.byte 1 ;'9'
dis_n: ;待显示的数字(显示缓存)
.byte 1 ;v0
.byte 1 ;v1
.byte 1 ;v2
.byte 1 ;v3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -