mingqiang 发表于 2012-8-29 15:09:59

Atmege16中断方式写eeprom的汇编程序

; Target : ATMega16
; Crystal: 4.0000Mhz
; 以中断的方式写Eeeprom。特别要注意的是中断处理程序中要关就绪中断,在写eeprom程序中再打开就绪中断
;
.include "m16def.inc"
;-------------------工作寄存器定义----------
.def temp0          =r16   ;
.def temp1          =r17
.def temp2          =r18
.def temp_int       =r19   ;临时寄存器(中断中使用)
.def ee_flag      =r20   ;eeprom准备就绪标志
.def data_count   =r21   ;数据计数器
;-------------------常数定义----------

.org $0000
jmp reset      ;复位

reti         ;IRQ0 中断向量
nop            
reti         ;IRQ1 中断向量
nop            
reti         ;Time2 比较中断向量
nop
reti         ;Time2 溢出中断向量
nop
reti         ;Time1 捕捉中断向量
nop
reti         ;Time1 比较A中断向量      
nop
reti         ;Time1 比较B中断向量
nop
reti         ;Time1 溢出中断向量
nop
reti         ;Time0 溢出中断向量
nop   
reti         ;SPI 传输结束中断向量
nop
reti         ;USART RX结束中断向量
nop
reti         ;UDR 空中断向量
nop
reti         ;USART TX结束中断向量
nop
reti         ;ADC 转换结束中断向量
nop

jmp ee_rdy   ;EEPROM就绪

reti         ;模拟比较器中断向量
nop
reti         ;两线串行接口中断向量
nop
reti         ;IRQ2 中断向量
nop
reti         ;Time0 比较中断向量
nop
reti         ;SPM 就绪中断向量
nop

.org $002A
reset:
ldi temp0,low(ramend)       ;设置堆栈指针
out spl,temp0
ldi temp0,high(ramend)
out sph,temp0

ldi temp0,25         ;usart初始化,波特率9600
ldi temp1,0
rcall usart_init
            
clr ee_flag
clr data_count

sbi eecr,eerie       ;eeprom就绪中断使能
sei                  ;全局中断使能

rcall delay_100ms         
rcall delay_100ms    ;延时200ms,等待电压稳定以后再写eeprom,否则可能出错


write:               ;在1地址写1,2地址写2,一直到20地址写20
cpi ee_flag,1
brne start
clr ee_flag
ldi temp1,1
add temp1,data_count
clr temp2
ldi temp0,1
add temp0,data_count
rcall eeprom_write
inc data_count
cpi data_count,20
brlo write

main:                ;从1地址读到20地址,读一个通过串口上传一个,循环这个过程               
clr temp1
clr temp2
read:
push temp1
push temp2
rcall delay_100ms   
rcall delay_100ms    ;这个延时是为了传的慢一点,方便验证数据是否正确
pop temp2
pop temp1

inc temp1
clr temp2
rcall eeprom_read
rcall usart_transmit
cp temp1,data_count
brlo read
rjmp main

ee_rdy:
in temp_int,sreg         ;保护状态寄存器
push temp_int
ldi ee_flag,1            ;eeprom就绪中断标志置位
cbi eecr,eerie         ;关eeprom就绪中断
pop temp_int             ;恢复状态寄存器
out sreg,temp_int
reti

eeprom_write:            ;数据存temp0,地址存temp1:temp2
out eearl,temp1          ;送地址到地址寄存器
out eearh,temp2         
out eedr,temp0         ;将数据写入到数据寄存器
cli                      ;关全局中断
sbi eecr,eemwe         ;置位主机写使能
sbi eecr,eewe            ;置位写使能
sbi eecr,eerie         ;eeprom就绪中断使能
sei                      ;全局中断使能
ret

eeprom_read:             ;数据存temp0,地址存temp1:temp2
out eearl,temp1          ;送地址到地址寄存器
out eearh,temp2
cli
sbi eecr,eere            ;置位读使能
sei
in temp0,eedr            ;从数据寄存器读出数据到temp0   
ret

usart_init:
out ubrrh,temp1                           ;设置波特率
out ubrrl,temp0
ldi temp0,(1<<rxen)|(1<<txen)|(1<<rxcie)    ;接收器与发送器使能,接收中断开
out ucsrb,temp0
ldi temp0,(1<<ursel)|(1<<usbs)|(3<<ucsz0)   ;设置帧格式: 8 个数据位, 2 个停止位
out ucsrc,temp0
ret


usart_transmit:
sbis ucsra,udre          ;等待发送缓冲器为空
rjmp usart_transmit
out udr,temp0            ;将数据放入缓冲器,发送数据
ret

;**************延时100ms子程序,用到了temp0,temp1,temp2****************
delay_100ms:                ;
ldi temp0,1
ldi temp1,0
delay1:
subi temp0,255            ;加1操作
sbci temp1,255
cpi temp0,0x37            ;0x37
ldi temp2,0xdf            ;0xdf37
cpc temp1,temp2
brlo delay1               ;未达0xdf37继续
ret

mingqiang 发表于 2012-8-29 15:12:55

实现的功能很无聊,就是为了验证读写程序以及eeprom就绪中断程序正确。
页: [1]
查看完整版本: Atmege16中断方式写eeprom的汇编程序