久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5884|回復: 2
打印 上一主題 下一主題
收起左側

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。



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

  2. ;AVR匯編程序實例

  3. ;簡易帶1/100秒的24小時制時鐘

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

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



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

  7. .def count                =        r18        ;循環計數單元

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

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

  10. .def count_10ms        =        r21                ;10ms計數單元

  11. .def flag_2ms                =        r22        ;2ms到標志

  12. .def temp                        =        r23        ;臨時變量

  13. .def temp1                =        r24                ;臨時變量

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



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

  16. .org $0000

  17.         jmp reset                ;復位處理

  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. ;程序開始

  86. .org $0046

  87. reset:

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

  89.         out sph,r16

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

  91.         out spl,r16

  92.         

  93.         ser temp                        

  94.         out ddra,temp                                ;設置PORTA為輸出,段碼輸出

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

  96.         out portc,temp                        ;PORTC輸出$FF, 無顯示



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

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



  99. ;初始化時鐘時間為11:59:55:00

  100.         ldi xl,low(time_buff)                ;

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

  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                                ;時 = 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,轉main循環

  125.         clr flag_2ms                                ;到,請2ms標志

  126.         rcall display                                ;調用LED顯示時間(動態掃描顯示一位)

  127. d_10ms_ok:

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

  129.         brne main                                        ;No,轉main循環

  130.         clr count_10ms                        ;10ms到,清零10ms計數器

  131.         rcall time_add                        ;調用時間加10ms調整

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

  133.         rjmp main                                        ;轉main循環



  134. ;LED動態掃描顯示子程序,2ms執行一次,一次點亮一位,8位循環

  135. display:

  136.         clr r0

  137.         ser temp                                        ;temp = 0x11111111

  138.         out portc,temp                        ;關顯示,去消影和拖尾作用

  139.         ldi yl,low(display_buff)

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

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

  142.         adc yh,r0                                        ;加上低位進位

  143.         ld temp,y                                        ;temp中為要顯示的數字

  144.         

  145.         clr r0

  146.         ldi zl,low(led_7 * 2)

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

  148.         add zl,temp                                ;加上要顯示的數字

  149.         adc zh,r0                                        ;加上低位進位        

  150.         lpm                                        ;讀對應七段碼到R0中

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



  152.         mov r0,p_temp

  153.         com r0,

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

  155.         

  156.         inc position                        ;調整到下一次顯示位

  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. ;時鐘時間調整,加0.01秒

  165. time_add:

  166.         ldi xl,low(time_buff)        ;

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

  168.                 rcall dhm3                        ;ms單元加1調整

  169.                 cpi temp,0x99                ;

  170.                 brne        time_add_ret        ;未到99ms返回

  171.                 rcall dhm                        ;秒單元加1調整

  172.                 cpi temp,0x60

  173.                 brne        time_add_ret        ;未到60秒返回

  174.                 rcall dhm                        ;分單元加1調整

  175.                 cpi temp,0x60

  176.                 brne time_add_ret                ;未到60分返回

  177.                 rcall dhm                        ;時單元加1調整

  178. cpi temp,0x24

  179.      brne time_add_ret                        ;未到24時返回

  180.         clr temp

  181.         st x,temp                                ;到24時,時單元清另

  182. time_add_ret:

  183.         ret



  184. ;低段時間清零,高段時間加1,BCD調整

  185. dhm:  clr temp                        ;當前時段清零

  186. dhm1: st  x+,temp                        ;當前時段清零,X寄存器指針加一

  187. dhm3: ld  temp,x                        ;取出新時段數據

  188.       inc temp                  ;加一

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

  190.       brhs dhm2                        ;例如$58+1=$59,不須調整;

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

  192. dhm2: st x,temp                        ;并將調整結果送回

  193.       ret



  194. ;將時鐘單元數據送LED顯示緩沖單元中

  195. put_t2d:

  196.         ldi xl,low(time_buff)                ;

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

  198.         ldi yl,low(display_buff)

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

  200.         ldi count,4                                ;循環次數 = 4

  201. loop:

  202.         ld        temp,x+                                ;讀一個時間單元

  203.         mov        temp1,temp

  204.         swap        temp1

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

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

  207.         st y+,temp                                ;寫入2個顯示單元

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

  209.         dec        count

  210.         brne        loop                        ;4個時間單元->8個顯示單元

  211.         ret



  212. ;T1時鐘溢出中斷服務

  213. time1_ovf:

  214.         in temp_int,sreg

  215.         push temp_int                                ;保護狀態寄存器

  216.         

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

  218.         out tcnt1h,temp_int

  219.         ldi temp_int,0x0c

  220.         out tcnt1l,temp_int

  221.         

  222.         inc count_10ms                        ;10ms計數器加一

  223.         ldi flag_2ms,0x01                        ;置2ms標志到

  224.         

  225. pop temp_int

  226.         out sreg,        temp_int                        ;恢復狀態寄存器

  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 共陰極 共陽極

  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顯示緩沖區,8個字節

  254. .BYTE        0x00                        ;LED 1 位顯示內容

  255. .BYTE        0x00                        ;LED 2 位顯示內容

  256. .BYTE        0x00                        ;LED 3 位顯示內容

  257. .BYTE        0x00                        ;LED 4 位顯示內容

  258. .BYTE        0x00                        ;LED 5 位顯示內容

  259. .BYTE        0x00                        ;LED 6 位顯示內容

  260. .BYTE        0x00                        ;LED 7 位顯示內容

  261. .BYTE        0x00                        ;LED 8 位顯示內容



  262. .org        $0108

  263. time_buff:                        ;時鐘數據緩沖區,4個字節

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

  265. .BYTE        0x00                        ;秒單元

  266. .BYTE        0x00                        ;分單元

  267. .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具有數據位置和值定義(填充)的功能。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:342822 發表于 2020-8-14 21:31 | 只看該作者
325行com r0,錯誤改為:com r0 去掉逗點編譯通過。
回復

使用道具 舉報

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

回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: av在线视| 国产福利在线播放 | www.v888av.com | 精久久久久 | 欧美日韩一区二区三区不卡视频 | 日日噜噜夜夜爽爽狠狠 | 激情影院久久 | 久久久久中文字幕 | 波多野结衣在线观看一区二区三区 | 九九热免费视频在线观看 | 国产视频第一页 | 亚洲国产精品va在线看黑人 | 欧美一区二区三区在线观看 | 亚洲成人精品视频 | 国产黄色av网站 | 日韩一区二区三区四区五区六区 | 91一区二区 | 久久久久久久久毛片 | 午夜丰满少妇一级毛片 | 天天综合天天 | 亚洲一在线| 中文字幕在线观看一区 | av黄色在线观看 | 久久精品天堂 | 91精品国产综合久久小仙女图片 | 亚洲午夜视频 | 国产男女猛烈无遮掩视频免费网站 | 视频三区| 麻豆久久久久久 | 中文字幕在线观看日韩 | 三级在线视频 | h在线观看| 爱爱视频网| 日韩二 | 精品欧美乱码久久久久久1区2区 | 亚洲视频观看 | 欧美精品一二三区 | 91在线一区 | 国产亚洲精品久久情网 | jav成人av免费播放 | 亚洲一区视频在线播放 |