欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
avr單片機匯編參考程序
[打印本頁]
作者:
51黑fan
時間:
2016-1-31 20:37
標題:
avr單片機匯編參考程序
該AVR的匯編程序選自《M128》,程序中體現了AVR匯編的基本特點,僅供大家參考。
該應用系統為一個帶1/100秒的簡易24小時制時鐘,它在上電后能夠自動從11時59分55秒00開始計時和顯示時間。下圖為簡易時鐘系統硬件電路圖。
圖 簡易24小時時鐘硬件原理圖
系統使用8個LED數碼管顯示時、分、秒、1/100秒4個時段的數字,每個時段占用2個LED。顯示方式采用動態掃描方式,ATmega128的PA口輸出顯示數字的7段碼(注意:圖中省缺了PA口連接到LED各段的8個限流電阻,阻值800歐左右),PC口用于控制8個LED的位選。ATmega128使用外部16MHz晶振(圖中未畫出)。
系統還使用ATmega128片內的計數/定時器T1,設計T1工作在定時溢出中斷方式,定時間隔為2ms,即T1每2ms產生一次中斷。5次中斷得到10ms的時間間隔,此時時鐘的1/100秒加1,并相應進行時、分、秒的調整。
LED動態掃描方式的設計如下:在每2ms的時間中,點亮8個LED中的一個,顯示其相應的數字(PC口的輸出只有一位為低電平,選通一個LED,保持2ms)。因此PC口的輸出值為0b11111110,每隔2ms循環右移,到0b01111111時8個LED各點亮一次,時間為16ms。在1秒鐘內,循環8個LED的次數為62.5(1000/16),是人眼的滯留時間(25次/秒)的2.5倍,保證了LED顯示亮度均勻,無閃爍。在程序設計中,在各個LED轉換和7段碼輸出時,關閉位選信號(PC輸出0b11111111),消除了顯示的拖尾現象(消影功能)。
T1的設計:T1為16位定時器,系統時鐘為16M,采用其64分頻后的時鐘作為T1的計數信號(寄存器TCCR1B = 0x03),一個計數周期為4us,2ms需要計500個(0x01F4)。由于T1溢出中斷發生在0xFFFF后下一個T1計數脈沖的到來(參見第二章關于定時器原理部分),因此T1的計數初始值為0xFE0C = 0xFFFF – 0x01F3(65535-499),即寄存器TCNT1的初值為0xFE0C。
3.8.2 AVR匯編源代碼
該系統的匯編源代碼如下,開發軟件平臺使用AVR Studio 4.08。
;********************************************************
;AVR匯編程序實例
;簡易帶1/100秒的24小時制時鐘
;********************************************************
.include "m128def.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空間$0000-$0045
.org $0000
jmp reset ;復位處理
reti ;IRQ0 Handler
nop
reti ;IRQ1 Handler
nop
reti ;IRQ2 Handler
nop
reti ;IRQ3 Handler
nop
reti ;IRQ4 Handler
nop
reti ;IRQ5 Handler
nop
reti ;IRQ6 Handler
nop
reti ;IRQ7 Handler
nop
reti ;Timer2 Compare Handler
nop
reti ;Timer2 Overflow Handler
nop
reti ;Timer1 Capture Handler
nop
reti ;Timer1 CompareA Handler
nop
reti ;Timer1 CompareB Handler
nop
jmp time1_ovf ;Timer1 Overflow Handler
reti ;Timer0 Compare Handler
nop
reti ;Timer0 Overflow Handler
nop
reti ;SPI Transfer Complete Handler
nop
reti ;USART0 RX Complete Handler
nop
reti ;USART0 UDR Empty Handler
nop
reti ;USART0 TX Complete Handler
nop
reti ;ADC Conversion Complete Handler
nop
reti ;E2PROM Ready Handler
nop
reti ;Analog Comparator Handler
nop
reti ;Timer1 CompareC Handler
nop
reti ;Timer3 Capture Handler
nop
reti ;Timer3 CompareA Handler
nop
reti ;Timer3 CompareB Handler
nop
reti ;Timer3 CompareC Handler
nop
reti ;Timer Overflow Handler
nop
reti ;USART1 RX Complete Handler
nop
reti ;USART1 UDR Empty Handler
nop
reti ;USART1 TX Complete Handler
nop
reti ;Two-wire Serial Interface Handler
nop
reti ;SPM Ready Handler
nop
;程序開始
.org $0046
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,0xfe ;T1初始化,每隔2ms中斷一次
out tcnt1h,temp
ldi temp,0x0c
out tcnt1l,temp
clr temp
out tccr1a,temp
ldi temp,0x03 ;16M,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,0xfe ;T1初始值設定,2ms中斷一次
out tcnt1h,temp_int
ldi temp_int,0x0c
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 $0100
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 $0108
time_buff: ;時鐘數據緩沖區,4個字節
.BYTE 0x00 ;1/100s單元
.BYTE 0x00 ;秒單元
.BYTE 0x00 ;分單元
.BYTE 0x00 ;時單元
復制代碼
該程序實例采用規范標準的設計理念和風格,程序中已給出比較詳細的注解。關于程序如何具體完成和實現系統的功能請讀者仔細閱讀程序,用心體會。下面僅對編寫ATmega128匯編程序時,在結構和語句使用上一些需要注意的方面加以介紹。
1.將程序中操作最頻繁以及需要特殊位處理的變量定義在AVR的32個工作寄存器空間,因為MCU對R0-R31的操作僅需要一個時鐘周期,而且功能強大。由于R0-R31的功能有不同,而且也僅有32個,所以程序員應認真考慮和規劃這32個工作寄存器的使用。如盡量不要將變量放置在R26-R31中,因為這6個寄存器構成3個16位的X、Y、Z地址指針寄存器,應保留用于各種尋址使用。
2.ATmega128有35個中斷源,Flash程序存儲器的低段空間為這35個中斷向量地址。由于ATmega128的程序存儲器空間為64K字,所以與其它AVR不同的是,ATmega128的一個向量地址空間為2個字長度,在中斷向量處應使用長轉移指令jmp轉移到中斷服務程序,而一般的AVR的一個向量地址空間為1個字長度,使用rjmp轉移指令。出于提高系統可靠性的設計,對于系統不使用的中斷向量,應填充2個中斷返回指令reti(每個reti占一個字)。在本程序中,為了程序的理解和閱讀方便,使用了reti和nop指令填充一個2個字長度的向量地址空間。
3.程序中使用X、Y、Z三個16位的地址指針寄存器,基于他們的一些指令有自動加(減)一的功能,以及先加(減)、后使用,和先使用、后加(減)的區別,在使用中應注意正確和靈活的使用。
4.由于LED的七段碼對照表是固定不變的,程序中將LED的七段碼表放置在Flash存儲器中。對于Flash存儲器的間址取數只能使用Z寄存器。由于程序存儲器的地址是以字(雙字節)為單位的,因此,16位地址指針寄存器Z的高15位為程序存儲器的字地址,最低位LSB為“0”時,指字的低字節;為“1”時,指字的高字節。程序中使用偽指令db定義的七段碼為一個字節,他保存在一個字的低字節處。如果定義字,應使用偽指令dw。
本例使用指令lpm讀取Flash中的一個字節,因此在取七段碼表的首地址時乘2(ldi zl,low(led_7 * 2)),將地址左移一位,Z寄存器的LSB為“0”,表示取該字的低位字節。
指令lpm能尋址的程序存儲器空間為低64K字節的頁(32k字),因此如果常量表的位置處在高64字節的頁中,請使用指令elpm。詳細的指令功能見3.4.3的內容。
5.中斷服務程序中,必須對MCU的標志寄存器SREG進行保護。在T1的溢出中斷服務程序中,還需要對TCNT1的初值進行設置,以保證下一次中斷仍為2ms。中斷服務程序應盡量短小,因此在中斷服務中,只將2ms標志置位和10ms加一計數,其它處理應盡量放在主程序中。
6.程序中定義了8個字節的顯示緩沖區和4個字節的時鐘數據緩沖區,分別存放8個LED所對應的顯示數字和4個時間段的時間值(BCD碼),這12個單元定義放置在ATmega128的RAM中。ATmega128的RAM單元應從0x0100開始,前面的地址分別對應的是32個工作寄存器、I/O寄存器、擴展I/O寄存器,因此不要把一般的數據單元定義在小于0x0100的空間(參見2.2.2,RAM空間分配)。
7.與使用db或dw偽指令在Flash空間定義常量不同的是,在RAM空間予留變量空間的定義應使用byte偽指令。byte偽指令的功能是定義變量的位置(予留空間),不能定義(填充)變量的值,變量具體的值是需要由程序在運行中寫入的。而偽指令db、dw具有數據位置和值定義(填充)的功能。
作者:
taotie
時間:
2020-8-14 21:31
325行com r0,錯誤改為:com r0 去掉逗點編譯通過。
作者:
taotie
時間:
2020-8-16 14:21
Proteus 8仿真avr單片機匯編參考程序
屏幕截圖(37).png
(153.73 KB, 下載次數: 52)
下載附件
2020-8-16 14:21 上傳
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1