找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5914|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

avr單片機(jī)匯編參考程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
該AVR的匯編程序選自《M128》,程序中體現(xiàn)了AVR匯編的基本特點(diǎn),僅供大家參考。

   該應(yīng)用系統(tǒng)為一個(gè)帶1/100秒的簡(jiǎn)易24小時(shí)制時(shí)鐘,它在上電后能夠自動(dòng)從11時(shí)59分55秒00開(kāi)始計(jì)時(shí)和顯示時(shí)間。下圖為簡(jiǎn)易時(shí)鐘系統(tǒng)硬件電路圖。



                           圖  簡(jiǎn)易24小時(shí)時(shí)鐘硬件原理圖



   系統(tǒng)使用8個(gè)LED數(shù)碼管顯示時(shí)、分、秒、1/100秒4個(gè)時(shí)段的數(shù)字,每個(gè)時(shí)段占用2個(gè)LED。顯示方式采用動(dòng)態(tài)掃描方式,ATmega128的PA口輸出顯示數(shù)字的7段碼(注意:圖中省缺了PA口連接到LED各段的8個(gè)限流電阻,阻值800歐左右),PC口用于控制8個(gè)LED的位選。ATmega128使用外部16MHz晶振(圖中未畫(huà)出)。

  系統(tǒng)還使用ATmega128片內(nèi)的計(jì)數(shù)/定時(shí)器T1,設(shè)計(jì)T1工作在定時(shí)溢出中斷方式,定時(shí)間隔為2ms,即T1每2ms產(chǎn)生一次中斷。5次中斷得到10ms的時(shí)間間隔,此時(shí)時(shí)鐘的1/100秒加1,并相應(yīng)進(jìn)行時(shí)、分、秒的調(diào)整。

  LED動(dòng)態(tài)掃描方式的設(shè)計(jì)如下:在每2ms的時(shí)間中,點(diǎn)亮8個(gè)LED中的一個(gè),顯示其相應(yīng)的數(shù)字(PC口的輸出只有一位為低電平,選通一個(gè)LED,保持2ms)。因此PC口的輸出值為0b11111110,每隔2ms循環(huán)右移,到0b01111111時(shí)8個(gè)LED各點(diǎn)亮一次,時(shí)間為16ms。在1秒鐘內(nèi),循環(huán)8個(gè)LED的次數(shù)為62.5(1000/16),是人眼的滯留時(shí)間(25次/秒)的2.5倍,保證了LED顯示亮度均勻,無(wú)閃爍。在程序設(shè)計(jì)中,在各個(gè)LED轉(zhuǎn)換和7段碼輸出時(shí),關(guān)閉位選信號(hào)(PC輸出0b11111111),消除了顯示的拖尾現(xiàn)象(消影功能)。

  T1的設(shè)計(jì):T1為16位定時(shí)器,系統(tǒng)時(shí)鐘為16M,采用其64分頻后的時(shí)鐘作為T(mén)1的計(jì)數(shù)信號(hào)(寄存器TCCR1B = 0x03),一個(gè)計(jì)數(shù)周期為4us,2ms需要計(jì)500個(gè)(0x01F4)。由于T1溢出中斷發(fā)生在0xFFFF后下一個(gè)T1計(jì)數(shù)脈沖的到來(lái)(參見(jiàn)第二章關(guān)于定時(shí)器原理部分),因此T1的計(jì)數(shù)初始值為0xFE0C = 0xFFFF – 0x01F3(65535-499),即寄存器TCNT1的初值為0xFE0C。



3.8.2  AVR匯編源代碼

  該系統(tǒng)的匯編源代碼如下,開(kāi)發(fā)軟件平臺(tái)使用AVR Studio 4.08。



  1. ;********************************************************

  2. ;AVR匯編程序?qū)嵗?br />

  3. ;簡(jiǎn)易帶1/100秒的24小時(shí)制時(shí)鐘

  4. ;********************************************************

  5. .include "m128def.inc"                ;引用器件I/O配置文件



  6. ;定義程序中使用的變量名(在寄存器空間)

  7. .def count                =        r18        ;循環(huán)計(jì)數(shù)單元

  8. .def position                =        r19        ;LED顯示位指針,取值為0-7

  9. .def p_temp                 =        r20        ;LED顯示位選,其值取反由PC口輸出

  10. .def count_10ms        =        r21                ;10ms計(jì)數(shù)單元

  11. .def flag_2ms                =        r22        ;2ms到標(biāo)志

  12. .def temp                        =        r23        ;臨時(shí)變量

  13. .def temp1                =        r24                ;臨時(shí)變量

  14. .def temp_int                =        r25        ;臨時(shí)變量(中斷中使用)



  15. ;中斷向量區(qū)定義,flash空間$0000-$0045

  16. .org $0000

  17.         jmp reset                ;復(fù)位處理

  18.         reti                        ;IRQ0 Handler

  19.         nop

  20.         reti                        ;IRQ1 Handler

  21.         nop

  22.         reti                        ;IRQ2 Handler

  23.         nop

  24.         reti                        ;IRQ3 Handler

  25.         nop

  26.         reti                        ;IRQ4 Handler

  27.         nop

  28.         reti                        ;IRQ5 Handler

  29.         nop

  30.         reti                        ;IRQ6 Handler

  31.         nop

  32.         reti                        ;IRQ7 Handler

  33.         nop

  34.         reti                        ;Timer2 Compare Handler

  35.         nop

  36.         reti                        ;Timer2 Overflow Handler

  37.         nop

  38.         reti                        ;Timer1 Capture Handler

  39.         nop

  40.         reti                        ;Timer1 CompareA Handler

  41.         nop

  42.         reti                        ;Timer1 CompareB Handler

  43.         nop

  44.         jmp time1_ovf ;Timer1 Overflow Handler

  45.         reti                        ;Timer0 Compare Handler

  46.         nop

  47.         reti                        ;Timer0 Overflow Handler

  48.         nop

  49.         reti                        ;SPI Transfer Complete Handler

  50.         nop

  51.         reti                        ;USART0 RX Complete Handler

  52.         nop

  53.         reti                        ;USART0 UDR Empty Handler

  54.         nop

  55.         reti                        ;USART0 TX Complete Handler

  56.         nop

  57.         reti                        ;ADC Conversion Complete Handler

  58.         nop

  59.         reti                        ;E2PROM Ready Handler

  60.         nop

  61.         reti                        ;Analog Comparator Handler

  62.         nop

  63.         reti                        ;Timer1 CompareC Handler

  64.         nop

  65.         reti                        ;Timer3 Capture Handler

  66.         nop

  67.         reti                        ;Timer3 CompareA Handler

  68.         nop

  69.         reti                        ;Timer3 CompareB Handler

  70.         nop

  71.         reti                        ;Timer3 CompareC Handler

  72.         nop

  73.         reti                        ;Timer Overflow Handler

  74.         nop

  75.         reti                        ;USART1 RX Complete Handler

  76.         nop

  77.         reti                          ;USART1 UDR Empty Handler

  78.         nop

  79.         reti                        ;USART1 TX Complete Handler

  80.         nop

  81.         reti                        ;Two-wire Serial Interface Handler

  82.         nop

  83.         reti                        ;SPM Ready Handler

  84.         nop               



  85. ;程序開(kāi)始

  86. .org $0046

  87. reset:

  88.         ldi r16,high(RAMEND)                ;設(shè)置堆棧指針高位

  89.         out sph,r16

  90.         ldi r16,low(RAMEND)                ;設(shè)置堆棧指針低位

  91.         out spl,r16

  92.         

  93.         ser temp                        

  94.         out ddra,temp                                ;設(shè)置PORTA為輸出,段碼輸出

  95.         out ddrc,temp                                ;設(shè)置PORTC為輸出,位碼控制

  96.         out portc,temp                        ;PORTC輸出$FF, 無(wú)顯示



  97.         ldi position,0x00                        ;段位初始化為1/100秒低位

  98.         ldi p_temp,0x01                        ;LED第1位亮



  99. ;初始化時(shí)鐘時(shí)間為11:59:55:00

  100.         ldi xl,low(time_buff)                ;

  101.         ldi xh,high(time_buff)                ;X寄存器取得時(shí)鐘單元首指針

  102.         ldi temp,0x00

  103.         st  x+,temp                                ;1/100秒 = 00

  104.         ldi temp,0x55

  105.         st  x+,temp                                ;秒 = 55

  106.         ldi temp,0x59

  107.         st  x+,temp                                ;分 = 59

  108.         ldi temp,0x11

  109.         st  x,temp                                ;時(shí) = 11



  110.         ldi temp,0xfe                                ;T1初始化,每隔2ms中斷一次

  111.         out tcnt1h,temp

  112.         ldi temp,0x0c

  113.         out tcnt1l,temp

  114.         clr temp

  115.         out tccr1a,temp

  116.         ldi temp,0x03                                ;16M,64分頻 2ms

  117.         out tccr1b,temp

  118.         ldi temp,0x04

  119.         out timsk,temp                        ;允許T1溢出中斷

  120.         sei                                                ;全局中斷允許



  121. ;主程序

  122. main:

  123.         cpi flag_2ms,0x01                        ;判2ms到否

  124.         brne main                                        ;No,轉(zhuǎn)main循環(huán)

  125.         clr flag_2ms                                ;到,請(qǐng)2ms標(biāo)志

  126.         rcall display                                ;調(diào)用LED顯示時(shí)間(動(dòng)態(tài)掃描顯示一位)

  127. d_10ms_ok:

  128.         cpi count_10ms,0x05                ;判10ms到否

  129.         brne main                                        ;No,轉(zhuǎn)main循環(huán)

  130.         clr count_10ms                        ;10ms到,清零10ms計(jì)數(shù)器

  131.         rcall time_add                        ;調(diào)用時(shí)間加10ms調(diào)整

  132.         rcall put_t2d                                ;將新時(shí)間值放入顯示緩沖單元

  133.         rjmp main                                        ;轉(zhuǎn)main循環(huán)



  134. ;LED動(dòng)態(tài)掃描顯示子程序,2ms執(zhí)行一次,一次點(diǎn)亮一位,8位循環(huán)

  135. display:

  136.         clr r0

  137.         ser temp                                        ;temp = 0x11111111

  138.         out portc,temp                        ;關(guān)顯示,去消影和拖尾作用

  139.         ldi yl,low(display_buff)

  140.         ldi yh,high(display_buff)        ;Y寄存器取得顯示緩沖單元首指針

  141.         add yl,position                        ;加上要顯示的位值

  142.         adc yh,r0                                        ;加上低位進(jìn)位

  143.         ld temp,y                                        ;temp中為要顯示的數(shù)字

  144.         

  145.         clr r0

  146.         ldi zl,low(led_7 * 2)

  147.         ldi zh,high(led_7 * 2)                ;Z寄存器取得7段碼組的首指針

  148.         add zl,temp                                ;加上要顯示的數(shù)字

  149.         adc zh,r0                                        ;加上低位進(jìn)位        

  150.         lpm                                        ;讀對(duì)應(yīng)七段碼到R0中

  151.         out porta,r0                                ;LED段碼輸出



  152.         mov r0,p_temp

  153.         com r0,

  154.         out portc,r0                        ;輸出位控制字,完成LED一位的顯示

  155.         

  156.         inc position                        ;調(diào)整到下一次顯示位

  157.         lsl p_temp

  158.         cpi position,0x08

  159.         brne display_ret

  160.         ldi position,0x00

  161.         ldi p_temp,0x01

  162. display_ret:

  163.         ret



  164. ;時(shí)鐘時(shí)間調(diào)整,加0.01秒

  165. time_add:

  166.         ldi xl,low(time_buff)        ;

  167.                 ldi xh,high(time_buff)        ;X寄存器為時(shí)鐘單元首指針

  168.                 rcall dhm3                        ;ms單元加1調(diào)整

  169.                 cpi temp,0x99                ;

  170.                 brne        time_add_ret        ;未到99ms返回

  171.                 rcall dhm                        ;秒單元加1調(diào)整

  172.                 cpi temp,0x60

  173.                 brne        time_add_ret        ;未到60秒返回

  174.                 rcall dhm                        ;分單元加1調(diào)整

  175.                 cpi temp,0x60

  176.                 brne time_add_ret                ;未到60分返回

  177.                 rcall dhm                        ;時(shí)單元加1調(diào)整

  178. cpi temp,0x24

  179.      brne time_add_ret                        ;未到24時(shí)返回

  180.         clr temp

  181.         st x,temp                                ;到24時(shí),時(shí)單元清另

  182. time_add_ret:

  183.         ret



  184. ;低段時(shí)間清零,高段時(shí)間加1,BCD調(diào)整

  185. dhm:  clr temp                        ;當(dāng)前時(shí)段清零

  186. dhm1: st  x+,temp                        ;當(dāng)前時(shí)段清零,X寄存器指針加一

  187. dhm3: ld  temp,x                        ;取出新時(shí)段數(shù)據(jù)

  188.       inc temp                  ;加一

  189.       cpi temp,0x0A                ;若個(gè)位數(shù)碼未到$0A(10)

  190.       brhs dhm2                        ;例如$58+1=$59,不須調(diào)整;

  191.       subi temp,0xFA                ;否則做減$FA調(diào)整:例如$49+1-$FA=$50

  192. dhm2: st x,temp                        ;并將調(diào)整結(jié)果送回

  193.       ret



  194. ;將時(shí)鐘單元數(shù)據(jù)送LED顯示緩沖單元中

  195. put_t2d:

  196.         ldi xl,low(time_buff)                ;

  197.         ldi xh,high(time_buff)                ;X寄存器時(shí)鐘單元首指針

  198.         ldi yl,low(display_buff)

  199.         ldi yh,high(display_buff)        ;Y寄存器顯示緩沖單元首指針

  200.         ldi count,4                                ;循環(huán)次數(shù) = 4

  201. loop:

  202.         ld        temp,x+                                ;讀一個(gè)時(shí)間單元

  203.         mov        temp1,temp

  204.         swap        temp1

  205.         andi        temp1,0x0f                        ;高位BCD碼

  206.         andi        temp,0x0f                                ;低位BCD碼

  207.         st y+,temp                                ;寫(xiě)入2個(gè)顯示單元

  208.         st y+,temp1                        ;低位BCD碼在前,高位在后

  209.         dec        count

  210.         brne        loop                        ;4個(gè)時(shí)間單元->8個(gè)顯示單元

  211.         ret



  212. ;T1時(shí)鐘溢出中斷服務(wù)

  213. time1_ovf:

  214.         in temp_int,sreg

  215.         push temp_int                                ;保護(hù)狀態(tài)寄存器

  216.         

  217.         ldi temp_int,0xfe                        ;T1初始值設(shè)定,2ms中斷一次

  218.         out tcnt1h,temp_int

  219.         ldi temp_int,0x0c

  220.         out tcnt1l,temp_int

  221.         

  222.         inc count_10ms                        ;10ms計(jì)數(shù)器加一

  223.         ldi flag_2ms,0x01                        ;置2ms標(biāo)志到

  224.         

  225. pop temp_int

  226.         out sreg,        temp_int                        ;恢復(fù)狀態(tài)寄存器

  227.         reti                                                ;中斷返回               

  228.         

  229. .CSEG                                        ;LED七段碼表,定義在Flash程序空間

  230. led_7:                                        ;7段碼表

  231. .db 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07

  232. .db 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71        



  233. ;字 PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 共陰極 共陽(yáng)極

  234. ;        h        g        f        E        d        c        b        a               

  235. ;0        0        0        1        1        1        1        1        1        3FH                C0H

  236. ;1        0        0        0        0        0        1        1        0        06H                F9H

  237. ;2        0        1        0        1        1        0        1        1        5BH                A4H

  238. ;3        0        1        0        0        1        1        1        1        4FH                B0H

  239. ;4        0        1        1        0        0        1        1        0        66H                99H

  240. ;5        0        1        1        0        1        1        0        1        6DH                92H

  241. ;6        0        1        1        1        1        1        0        1        7DH                82H

  242. ;7        0        0        0        0        0        1        1        1        07H                F8H

  243. ;8        0        1        1        1        1        1        1        1        7FH                80H

  244. ;9        0        1        1        0        1        1        1        1        6FH                90H

  245. ;A        0        1        1        1        0        1        1        1        77H                88H

  246. ;b        0        1        1        1        1        1        0        0        7CH                83H

  247. ;C        0        0        1        1        1        0        0        1        39H                C6H

  248. ;d        0        1        0        1        1        1        1        0        5EH                A1H

  249. ;E        0        1        1        1        1        0        0        1        79H                86H

  250. ;F        0        1        1        1        0        0        0        1        71H                8EH



  251. .DSEG                                ;定義程序中使用的變量位置(在RAM空間)

  252. .ORG     $0100

  253. display_buff:                        ;LED顯示緩沖區(qū),8個(gè)字節(jié)

  254. .BYTE        0x00                        ;LED 1 位顯示內(nèi)容

  255. .BYTE        0x00                        ;LED 2 位顯示內(nèi)容

  256. .BYTE        0x00                        ;LED 3 位顯示內(nèi)容

  257. .BYTE        0x00                        ;LED 4 位顯示內(nèi)容

  258. .BYTE        0x00                        ;LED 5 位顯示內(nèi)容

  259. .BYTE        0x00                        ;LED 6 位顯示內(nèi)容

  260. .BYTE        0x00                        ;LED 7 位顯示內(nèi)容

  261. .BYTE        0x00                        ;LED 8 位顯示內(nèi)容



  262. .org        $0108

  263. time_buff:                        ;時(shí)鐘數(shù)據(jù)緩沖區(qū),4個(gè)字節(jié)

  264. .BYTE        0x00                        ;1/100s單元

  265. .BYTE        0x00                        ;秒單元

  266. .BYTE        0x00                        ;分單元

  267. .BYTE        0x00                        ;時(shí)單元
復(fù)制代碼



  該程序?qū)嵗捎靡?guī)范標(biāo)準(zhǔn)的設(shè)計(jì)理念和風(fēng)格,程序中已給出比較詳細(xì)的注解。關(guān)于程序如何具體完成和實(shí)現(xiàn)系統(tǒng)的功能請(qǐng)讀者仔細(xì)閱讀程序,用心體會(huì)。下面僅對(duì)編寫(xiě)ATmega128匯編程序時(shí),在結(jié)構(gòu)和語(yǔ)句使用上一些需要注意的方面加以介紹。

1.將程序中操作最頻繁以及需要特殊位處理的變量定義在AVR的32個(gè)工作寄存器空間,因?yàn)镸CU對(duì)R0-R31的操作僅需要一個(gè)時(shí)鐘周期,而且功能強(qiáng)大。由于R0-R31的功能有不同,而且也僅有32個(gè),所以程序員應(yīng)認(rèn)真考慮和規(guī)劃這32個(gè)工作寄存器的使用。如盡量不要將變量放置在R26-R31中,因?yàn)檫@6個(gè)寄存器構(gòu)成3個(gè)16位的X、Y、Z地址指針寄存器,應(yīng)保留用于各種尋址使用。

2.ATmega128有35個(gè)中斷源,F(xiàn)lash程序存儲(chǔ)器的低段空間為這35個(gè)中斷向量地址。由于ATmega128的程序存儲(chǔ)器空間為64K字,所以與其它AVR不同的是,ATmega128的一個(gè)向量地址空間為2個(gè)字長(zhǎng)度,在中斷向量處應(yīng)使用長(zhǎng)轉(zhuǎn)移指令jmp轉(zhuǎn)移到中斷服務(wù)程序,而一般的AVR的一個(gè)向量地址空間為1個(gè)字長(zhǎng)度,使用rjmp轉(zhuǎn)移指令。出于提高系統(tǒng)可靠性的設(shè)計(jì),對(duì)于系統(tǒng)不使用的中斷向量,應(yīng)填充2個(gè)中斷返回指令reti(每個(gè)reti占一個(gè)字)。在本程序中,為了程序的理解和閱讀方便,使用了reti和nop指令填充一個(gè)2個(gè)字長(zhǎng)度的向量地址空間。

3.程序中使用X、Y、Z三個(gè)16位的地址指針寄存器,基于他們的一些指令有自動(dòng)加(減)一的功能,以及先加(減)、后使用,和先使用、后加(減)的區(qū)別,在使用中應(yīng)注意正確和靈活的使用。

4.由于LED的七段碼對(duì)照表是固定不變的,程序中將LED的七段碼表放置在Flash存儲(chǔ)器中。對(duì)于Flash存儲(chǔ)器的間址取數(shù)只能使用Z寄存器。由于程序存儲(chǔ)器的地址是以字(雙字節(jié))為單位的,因此,16位地址指針寄存器Z的高15位為程序存儲(chǔ)器的字地址,最低位LSB為“0”時(shí),指字的低字節(jié);為“1”時(shí),指字的高字節(jié)。程序中使用偽指令db定義的七段碼為一個(gè)字節(jié),他保存在一個(gè)字的低字節(jié)處。如果定義字,應(yīng)使用偽指令dw。

本例使用指令lpm讀取Flash中的一個(gè)字節(jié),因此在取七段碼表的首地址時(shí)乘2(ldi zl,low(led_7 * 2)),將地址左移一位,Z寄存器的LSB為“0”,表示取該字的低位字節(jié)。

指令lpm能尋址的程序存儲(chǔ)器空間為低64K字節(jié)的頁(yè)(32k字),因此如果常量表的位置處在高64字節(jié)的頁(yè)中,請(qǐng)使用指令elpm。詳細(xì)的指令功能見(jiàn)3.4.3的內(nèi)容。

5.中斷服務(wù)程序中,必須對(duì)MCU的標(biāo)志寄存器SREG進(jìn)行保護(hù)。在T1的溢出中斷服務(wù)程序中,還需要對(duì)TCNT1的初值進(jìn)行設(shè)置,以保證下一次中斷仍為2ms。中斷服務(wù)程序應(yīng)盡量短小,因此在中斷服務(wù)中,只將2ms標(biāo)志置位和10ms加一計(jì)數(shù),其它處理應(yīng)盡量放在主程序中。

6.程序中定義了8個(gè)字節(jié)的顯示緩沖區(qū)和4個(gè)字節(jié)的時(shí)鐘數(shù)據(jù)緩沖區(qū),分別存放8個(gè)LED所對(duì)應(yīng)的顯示數(shù)字和4個(gè)時(shí)間段的時(shí)間值(BCD碼),這12個(gè)單元定義放置在ATmega128的RAM中。ATmega128的RAM單元應(yīng)從0x0100開(kāi)始,前面的地址分別對(duì)應(yīng)的是32個(gè)工作寄存器、I/O寄存器、擴(kuò)展I/O寄存器,因此不要把一般的數(shù)據(jù)單元定義在小于0x0100的空間(參見(jiàn)2.2.2,RAM空間分配)。

7.與使用db或dw偽指令在Flash空間定義常量不同的是,在RAM空間予留變量空間的定義應(yīng)使用byte偽指令。byte偽指令的功能是定義變量的位置(予留空間),不能定義(填充)變量的值,變量具體的值是需要由程序在運(yùn)行中寫(xiě)入的。而偽指令db、dw具有數(shù)據(jù)位置和值定義(填充)的功能。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:342822 發(fā)表于 2020-8-14 21:31 | 只看該作者
325行com r0,錯(cuò)誤改為:com r0 去掉逗點(diǎn)編譯通過(guò)。
回復(fù)

使用道具 舉報(bào)

板凳
ID:342822 發(fā)表于 2020-8-16 14:21 | 只看該作者
Proteus 8仿真avr單片機(jī)匯編參考程序

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表