|
|
79.gif (605.63 KB, 下載次數(shù): 0)
下載附件
2025-10-7 11:24 上傳
; =============================================
; 23LC1024 SRAM測(cè)試程序 - ASM完整版
; =功能:完整的SRAM讀寫測(cè)試,包含UART輸出和LED指示
; =============================================
.include "m16def.inc" ; 包含ATmega16定義文件
; 系統(tǒng)常量定義
.equ F_CPU = 1000000 ; CPU頻率 1MHz
.equ SRAM_CS = PB4 ; SRAM片選引腳(PB4)
.equ MOSI_PIN = PB5 ; SPI主出從入引腳(PB5)
.equ MISO_PIN = PB6 ; SPI主入從出引腳(PB6)
.equ SCK_PIN = PB7 ; SPI時(shí)鐘引腳(PB7)
.equ CMD_READ = 0x03 ; SRAM讀命令
.equ CMD_WRITE = 0x02 ; SRAM寫命令
.equ CMD_RDSR = 0x05 ; 讀狀態(tài)寄存器命令
.equ CMD_WRSR = 0x01 ; 寫狀態(tài)寄存器命令
.equ MODE_SEQ = 0x40 ; 順序模式配置值
.equ UBRR_VAL = 12 ; 波特率9600 @ 1MHz
; 數(shù)據(jù)段定義(SRAM變量)
.dseg
write_data: .byte 1 ; 寫入數(shù)據(jù)存儲(chǔ)
read_data: .byte 1 ; 讀取數(shù)據(jù)存儲(chǔ)
addr_high: .byte 1 ; 24位地址高字節(jié)
addr_mid: .byte 1 ; 24位地址中字節(jié)
addr_low: .byte 1 ; 24位地址低字節(jié)
temp: .byte 1 ; 臨時(shí)變量
test_index: .byte 1 ; 測(cè)試用例計(jì)數(shù)器
test_offset: .byte 1 ; 測(cè)試表偏移量
; 代碼段定義
.cseg
.org 0x0000 ; 程序起始地址
rjmp main ; 復(fù)位向量跳轉(zhuǎn)到主程序
; 測(cè)試數(shù)據(jù)表 - 7個(gè)測(cè)試用例(地址+數(shù)據(jù))
; 格式:地址高字節(jié), 地址中字節(jié), 地址低字節(jié), 測(cè)試數(shù)據(jù)
test_table:
.db 0x10, 0x00, 0x00, 0x11 ; 測(cè)試1: 地址 0x100000, 數(shù)據(jù) 0x11
.db 0x20, 0x00, 0x00, 0x22 ; 測(cè)試2: 地址 0x200000, 數(shù)據(jù) 0x22
.db 0x00, 0x01, 0x00, 0x33 ; 測(cè)試3: 地址 0x000100, 數(shù)據(jù) 0x33
.db 0x00, 0x00, 0x10, 0x44 ; 測(cè)試4: 地址 0x000010, 數(shù)據(jù) 0x44
.db 0x30, 0x20, 0x10, 0x55 ; 測(cè)試5: 地址 0x302010, 數(shù)據(jù) 0x55
.db 0x50, 0x20, 0x10, 0x65 ; 測(cè)試5: 地址 0x302010, 數(shù)據(jù) 0x65
.db 0x80, 0x20, 0x10, 0x81 ; 測(cè)試5: 地址 0x302010, 數(shù)據(jù) 0x81
; 消息字符串定義(中英雙語(yǔ)注釋)
msg_title: .db "23LC1024 ASM 完整測(cè)試",13,10,0 ; 程序標(biāo)題
msg_init: .db "SRAM 已初始化",13,10,0 ; SRAM初始化完成
msg_test: .db "正在運(yùn)行完整測(cè)試...",13,10,0 ; 測(cè)試開(kāi)始提示
msg_ok: .db " [通過(guò)]",13,10,0 ; 測(cè)試通過(guò)
msg_fail: .db " [失敗]",13,10,0 ; 測(cè)試失敗
msg_addr: .db "Addr 0x",0 ; 地址顯示前綴
msg_write: .db " W=0x",0 ; 寫入數(shù)據(jù)顯示前綴
msg_read: .db " R=0x",0 ; 讀取數(shù)據(jù)顯示前綴
msg_crlf: .db 13,10,0,0 ; 回車換行
msg_done: .db "=== 所有測(cè)試已完成! ===",13,10,0 ; 測(cè)試完成提示
; =============================================
; 主程序
; =系統(tǒng)初始化和測(cè)試流程控制
; =============================================
main:
; 初始化堆棧指針
ldi r16, high(RAMEND) ; 加載RAM結(jié)束地址高字節(jié)
out SPH, r16 ; 設(shè)置堆棧指針高字節(jié)
ldi r16, low(RAMEND) ; 加載RAM結(jié)束地址低字節(jié)
out SPL, r16 ; 設(shè)置堆棧指針低字節(jié)
rcall uart_init ; 初始化UART串口
; 顯示程序標(biāo)題
ldi ZL, low(2*msg_title) ; 加載標(biāo)題字符串地址低字節(jié)
ldi ZH, high(2*msg_title) ; 加載標(biāo)題字符串地址高字節(jié)
rcall uart_puts ; 發(fā)送標(biāo)題字符串
rcall uart_crlf ; 發(fā)送回車換行
; 初始化SRAM
rcall sram_init ; 初始化SPI和SRAM
; 顯示初始化完成信息
ldi ZL, low(2*msg_init) ; 加載初始化消息地址低字節(jié)
ldi ZH, high(2*msg_init) ; 加載初始化消息地址高字節(jié)
rcall uart_puts ; 發(fā)送初始化消息
; 顯示測(cè)試開(kāi)始信息
ldi ZL, low(2*msg_test) ; 加載測(cè)試消息地址低字節(jié)
ldi ZH, high(2*msg_test) ; 加載測(cè)試消息地址高字節(jié)
rcall uart_puts ; 發(fā)送測(cè)試消息
rcall uart_crlf ; 發(fā)送回車換行
; 設(shè)置測(cè)試用例數(shù)量
ldi r16, 7 ; 設(shè)置總共運(yùn)行5個(gè)測(cè)試用例
sts test_index, r16 ; 保存測(cè)試計(jì)數(shù)器
ldi r17, 0 ; 初始化測(cè)試表偏移量為0
sts test_offset, r17 ; 保存偏移量
; 測(cè)試循環(huán)主程序
run_tests:
; 設(shè)置Z指針指向測(cè)試參數(shù)表的起始地址
ldi ZL, low(2*test_table) ; 加載測(cè)試表地址低字節(jié)
ldi ZH, high(2*test_table) ; 加載測(cè)試表地址高字節(jié)
; 加上當(dāng)前測(cè)試的偏移量以定位到具體測(cè)試用例
lds r17, test_offset ; 加載當(dāng)前偏移量
add ZL, r17 ; 加到Z指針低字節(jié)
ldi r18, 0 ; 清零用于帶進(jìn)位加法
adc ZH, r18 ; 加到Z指針高字節(jié)(帶進(jìn)位)
; 從程序存儲(chǔ)器加載測(cè)試參數(shù)
lpm r16, Z+ ; 加載地址高字節(jié)并遞增指針
sts addr_high, r16 ; 保存地址高字節(jié)
lpm r16, Z+ ; 加載地址中字節(jié)并遞增指針
sts addr_mid, r16 ; 保存地址中字節(jié)
lpm r16, Z+ ; 加載地址低字節(jié)并遞增指針
sts addr_low, r16 ; 保存地址低字節(jié)
lpm r16, Z+ ; 加載測(cè)試數(shù)據(jù)并遞增指針
sts write_data, r16 ; 保存要寫入的數(shù)據(jù)
; 執(zhí)行SRAM讀寫測(cè)試
rcall sram_write_byte ; 向SRAM寫入測(cè)試數(shù)據(jù)
rcall sram_read_byte ; 從SRAM讀取數(shù)據(jù)
rcall display_test_result ; 顯示測(cè)試結(jié)果
; 更新偏移量指向下一個(gè)測(cè)試用例(每個(gè)測(cè)試4個(gè)字節(jié)參數(shù))
lds r17, test_offset ; 加載當(dāng)前偏移量
subi r17, -4 ; 偏移量加4(指向下一個(gè)測(cè)試)
sts test_offset, r17 ; 保存更新后的偏移量
; 檢查是否完成所有測(cè)試
lds r16, test_index ; 加載剩余測(cè)試計(jì)數(shù)
dec r16 ; 計(jì)數(shù)器減1
sts test_index, r16 ; 保存更新后的計(jì)數(shù)
brne run_tests ; 如果未完成,繼續(xù)下一個(gè)測(cè)試
; 所有測(cè)試完成,顯示結(jié)束信息
ldi ZL, low(2*msg_done) ; 加載完成消息地址低字節(jié)
ldi ZH, high(2*msg_done) ; 加載完成消息地址高字節(jié)
rcall uart_puts ; 發(fā)送完成消息
; 成功指示 - 閃爍LED (如果PC0連接了LED)
sbi DDRC, 0 ; 設(shè)置PC0為輸出(連接LED)
success:
sbi PORTC, 0 ; 點(diǎn)亮LED(PC0輸出高電平)
ldi r16, 100 ; 設(shè)置延時(shí)100ms
rcall delay_ms ; 調(diào)用延時(shí)子程序
cbi PORTC, 0 ; 熄滅LED(PC0輸出低電平)
ldi r16, 100 ; 設(shè)置延時(shí)100ms
rcall delay_ms ; 調(diào)用延時(shí)子程序
rjmp success ; 無(wú)限循環(huán)閃爍LED
; =============================================
; 顯示測(cè)試結(jié)果
; =功能:顯示SRAM測(cè)試的詳細(xì)結(jié)果和驗(yàn)證狀態(tài)
; =============================================
display_test_result:
; 顯示地址信息
ldi ZL, low(2*msg_addr) ; 加載"地址:"字符串地址低字節(jié)
ldi ZH, high(2*msg_addr) ; 加載"地址:"字符串地址高字節(jié)
rcall uart_puts ; 發(fā)送地址標(biāo)簽字符串
; 顯示24位地址(高字節(jié)→中字節(jié)→低字節(jié))
lds r16, addr_high ; 加載地址高字節(jié)
rcall uart_puthex ; 以十六進(jìn)制顯示高字節(jié)
lds r16, addr_mid ; 加載地址中字節(jié)
rcall uart_puthex ; 以十六進(jìn)制顯示中字節(jié)
lds r16, addr_low ; 加載地址低字節(jié)
rcall uart_puthex ; 以十六進(jìn)制顯示低字節(jié)
; 顯示寫入的數(shù)據(jù)
ldi ZL, low(2*msg_write) ; 加載"寫入:"字符串地址低字節(jié)
ldi ZH, high(2*msg_write) ; 加載"寫入:"字符串地址高字節(jié)
rcall uart_puts ; 發(fā)送寫入標(biāo)簽字符串
lds r16, write_data ; 加載之前寫入的數(shù)據(jù)
rcall uart_puthex ; 以十六進(jìn)制顯示寫入的數(shù)據(jù)
; 顯示讀取的數(shù)據(jù)
ldi ZL, low(2*msg_read) ; 加載"讀取:"字符串地址低字節(jié)
ldi ZH, high(2*msg_read) ; 加載"讀取:"字符串地址高字節(jié)
rcall uart_puts ; 發(fā)送讀取標(biāo)簽字符串
lds r16, read_data ; 加載從SRAM讀取的數(shù)據(jù)
rcall uart_puthex ; 以十六進(jìn)制顯示讀取的數(shù)據(jù)
; 驗(yàn)證測(cè)試結(jié)果:比較寫入和讀取的數(shù)據(jù)
lds r17, write_data ; 重新加載寫入的數(shù)據(jù)到r17
lds r18, read_data ; 加載讀取的數(shù)據(jù)到r18
cp r17, r18 ; 比較兩個(gè)數(shù)據(jù)(r17 - r18)
breq test_ok ; 如果相等(Z=1),跳轉(zhuǎn)到成功處理
; 測(cè)試失敗處理
; 寫入和讀取的數(shù)據(jù)不匹配
ldi ZL, low(2*msg_fail) ; 加載"失敗"字符串地址低字節(jié)
ldi ZH, high(2*msg_fail) ; 加載"失敗"字符串地址高字節(jié)
rcall uart_puts ; 發(fā)送失敗信息
ret ; 返回主程序
; 測(cè)試成功處理
test_ok:
; 寫入和讀取的數(shù)據(jù)完全匹配
ldi ZL, low(2*msg_ok) ; 加載"成功"字符串地址低字節(jié)
ldi ZH, high(2*msg_ok) ; 加載"成功"字符串地址高字節(jié)
rcall uart_puts ; 發(fā)送成功信息
ret ; 返回主程序
; =============================================
; UART子程序
; UART串口通信相關(guān)功能子程序
; =============================================
; UART初始化子程序
; 功能:設(shè)置UART波特率、數(shù)據(jù)幀格式和使能發(fā)送
uart_init:
ldi r16, low(UBRR_VAL) ; 加載波特率分頻值的低字節(jié)
out UBRRL, r16 ; 寫入波特率低字節(jié)寄存器
ldi r16, high(UBRR_VAL) ; 加載波特率分頻值的高字節(jié)
out UBRRH, r16 ; 寫入波特率高字節(jié)寄存器
ldi r16, (1<<TXEN) ; 設(shè)置TXEN位(發(fā)送使能)
out UCSRB, r16 ; 寫入U(xiǎn)ART控制狀態(tài)寄存器B
ldi r16, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; 設(shè)置URSEL(選擇UCSRC)、8位數(shù)據(jù)位
out UCSRC, r16 ; 寫入U(xiǎn)ART控制狀態(tài)寄存器C
ret ; 返回
; 發(fā)送單個(gè)字符子程序
; 輸入:r16 - 要發(fā)送的字符
uart_putchar:
sbis UCSRA, UDRE ; 跳過(guò)下條指令如果UDR空(UDRE=1)
rjmp uart_putchar ; UDR未空,繼續(xù)等待
out UDR, r16 ; UDR已空,發(fā)送字符
ret ; 返回
; 發(fā)送字符串子程序
; 輸入:Z指針 - 指向程序存儲(chǔ)器中的字符串(以null結(jié)尾)
uart_puts:
lpm r16, Z+ ; 從程序存儲(chǔ)器加載字符并遞增Z指針
tst r16 ; 測(cè)試字符是否為0
breq uart_puts_end ; 如果是0,字符串結(jié)束
rcall uart_putchar ; 發(fā)送當(dāng)前字符
rjmp uart_puts ; 繼續(xù)發(fā)送下一個(gè)字符
uart_puts_end:
ret ; 返回
; 發(fā)送回車換行子程序
; 功能:發(fā)送CR(回車)和LF(換行)序列
uart_crlf:
ldi ZL, low(2*msg_crlf) ; 加載回車換行字符串地址低字節(jié)
ldi ZH, high(2*msg_crlf) ; 加載回車換行字符串地址高字節(jié)
rcall uart_puts ; 發(fā)送回車換行字符串
ret ; 返回
; 發(fā)送十六進(jìn)制數(shù)字子程序
; 輸入:r16 - 要發(fā)送的字節(jié)(以十六進(jìn)制形式發(fā)送兩個(gè)字符)
uart_puthex:
push r16 ; 保存原始值
swap r16 ; 交換高低4位
andi r16, 0x0F ; 屏蔽高4位,保留低4位
rcall hex_to_ascii ; 轉(zhuǎn)換為ASCII字符
rcall uart_putchar ; 發(fā)送高4位對(duì)應(yīng)的字符
pop r16 ; 恢復(fù)原始值
andi r16, 0x0F ; 屏蔽高4位,保留低4位
rcall hex_to_ascii ; 轉(zhuǎn)換為ASCII字符
rcall uart_putchar ; 發(fā)送低4位對(duì)應(yīng)的字符
ret ; 返回
; 十六進(jìn)制到ASCII轉(zhuǎn)換子程序
; 輸入:r16 - 十六進(jìn)制數(shù)字(0-15)
; 輸出:r16 - 對(duì)應(yīng)的ASCII字符
hex_to_ascii:
cpi r16, 10 ; 比較數(shù)字是否小于10
brlo hex_digit ; 如果小于10,跳轉(zhuǎn)到數(shù)字處理
subi r16, -('A'-10) ; 大于等于10,轉(zhuǎn)換為'A'-'F'
ret ; 返回
hex_digit:
subi r16, -'0' ; 小于10,轉(zhuǎn)換為'0'-'9'
ret ; 返回
; =============================================
; SPI子程序
; =SPI總線通信和SRAM操作相關(guān)子程序
; =============================================
; SPI初始化子程序
; 功能:配置SPI引腳方向和SPI控制寄存器
spi_init:
sbi DDRB, MOSI_PIN ; 設(shè)置MOSI引腳為輸出
sbi DDRB, SCK_PIN ; 設(shè)置SCK時(shí)鐘引腳為輸出
sbi DDRB, SRAM_CS ; 設(shè)置SRAM片選引腳為輸出
cbi DDRB, MISO_PIN ; 設(shè)置MISO引腳為輸入
sbi PORTB, SRAM_CS ; 拉高SRAM片選(不選中)
ldi r16, (1<<SPE)|(1<<MSTR)|(1<<SPR0) ; 使能SPI、主機(jī)模式、時(shí)鐘分頻
out SPCR, r16 ; 寫入SPI控制寄存器
ret ; 返回
; SPI數(shù)據(jù)傳輸子程序
; 功能:通過(guò)SPI發(fā)送和接收一個(gè)字節(jié)
; 輸入:r16 - 要發(fā)送的數(shù)據(jù)
; 輸出:r16 - 接收到的數(shù)據(jù)
spi_transfer:
out SPDR, r16 ; 啟動(dòng)SPI傳輸,寫入數(shù)據(jù)到SPI數(shù)據(jù)寄存器
spi_wait:
in r16, SPSR ; 讀取SPI狀態(tài)寄存器
sbrs r16, SPIF ; 跳過(guò)下條指令如果傳輸完成(SPIF=1)
rjmp spi_wait ; 傳輸未完成,繼續(xù)等待
in r16, SPDR ; 傳輸完成,讀取接收到的數(shù)據(jù)
ret ; 返回
; SRAM初始化子程序
; 功能:初始化SPI接口并配置SRAM工作模式
sram_init:
rcall spi_init ; 初始化SPI接口
cbi PORTB, SRAM_CS ; 拉低SRAM片選(選中芯片)
ldi r16, CMD_WRSR ; 加載寫狀態(tài)寄存器命令
rcall spi_transfer ; 發(fā)送命令
ldi r16, MODE_SEQ ; 加載順序模式配置值
rcall spi_transfer ; 發(fā)送模式配置
sbi PORTB, SRAM_CS ; 拉高SRAM片選(取消選中)
ldi r16, 10 ; 設(shè)置延時(shí)10ms
rcall delay_ms ; 調(diào)用延時(shí)子程序
ret ; 返回
; SRAM寫字節(jié)子程序
; 功能:向SRAM指定地址寫入一個(gè)字節(jié)數(shù)據(jù)
; 輸入:addr_high, addr_mid, addr_low - 24位地址
; write_data - 要寫入的數(shù)據(jù)
sram_write_byte:
cbi PORTB, SRAM_CS ; 拉低SRAM片選(選中芯片)
ldi r16, CMD_WRITE ; 加載寫命令
rcall spi_transfer ; 發(fā)送寫命令
lds r16, addr_high ; 加載地址高字節(jié)
rcall spi_transfer ; 發(fā)送地址高字節(jié)
lds r16, addr_mid ; 加載地址中字節(jié)
rcall spi_transfer ; 發(fā)送地址中字節(jié)
lds r16, addr_low ; 加載地址低字節(jié)
rcall spi_transfer ; 發(fā)送地址低字節(jié)
lds r16, write_data ; 加載要寫入的數(shù)據(jù)
rcall spi_transfer ; 發(fā)送數(shù)據(jù)字節(jié)
sbi PORTB, SRAM_CS ; 拉高SRAM片選(取消選中)
ldi r16, 5 ; 設(shè)置延時(shí)5ms
rcall delay_ms ; 調(diào)用延時(shí)子程序
ret ; 返回
; SRAM讀字節(jié)子程序
; 功能:從SRAM指定地址讀取一個(gè)字節(jié)數(shù)據(jù)
; 輸入:addr_high, addr_mid, addr_low - 24位地址
; 輸出:read_data - 讀取到的數(shù)據(jù)
sram_read_byte:
cbi PORTB, SRAM_CS ; 拉低SRAM片選(選中芯片)
ldi r16, CMD_READ ; 加載讀命令
rcall spi_transfer ; 發(fā)送讀命令
lds r16, addr_high ; 加載地址高字節(jié)
rcall spi_transfer ; 發(fā)送地址高字節(jié)
lds r16, addr_mid ; 加載地址中字節(jié)
rcall spi_transfer ; 發(fā)送地址中字節(jié)
lds r16, addr_low ; 加載地址低字節(jié)
rcall spi_transfer ; 發(fā)送地址低字節(jié)
ldi r16, 0x00 ; 加載啞元數(shù)據(jù)用于接收
rcall spi_transfer ; 發(fā)送啞元數(shù)據(jù)并接收SRAM數(shù)據(jù)
sts read_data, r16 ; 保存讀取到的數(shù)據(jù)
sbi PORTB, SRAM_CS ; 拉高SRAM片選(取消選中)
ret ; 返回
; =============================================
; 延時(shí)子程序
; =功能:提供精確的微秒和毫秒級(jí)延時(shí)
; =============================================
; 毫秒延時(shí)子程序
; 輸入:r16 - 延時(shí)的毫秒數(shù)
; 使用寄存器:r16, r17, r18
delay_ms:
push r17 ; 保存r17寄存器
push r18 ; 保存r18寄存器
delay_ms_outer:
ldi r17, 200 ; 設(shè)置外層循環(huán)計(jì)數(shù)器(200次)
delay_ms_inner:
ldi r18, 250 ; 設(shè)置內(nèi)層循環(huán)計(jì)數(shù)器(250次)
delay_ms_inner2:
dec r18 ; 內(nèi)層循環(huán)遞減
brne delay_ms_inner2 ; 內(nèi)層循環(huán)未結(jié)束則繼續(xù)
dec r17 ; 外層循環(huán)遞減
brne delay_ms_inner ; 外層循環(huán)未結(jié)束則繼續(xù)
dec r16 ; 毫秒計(jì)數(shù)器遞減
brne delay_ms_outer ; 未達(dá)到指定毫秒數(shù)則繼續(xù)
pop r18 ; 恢復(fù)r18寄存器
pop r17 ; 恢復(fù)r17寄存器
ret ; 返回
; 微秒延時(shí)子程序
; 輸入:r16 - 延時(shí)的微秒數(shù)
; 注意:基于1MHz時(shí)鐘,每個(gè)循環(huán)約4個(gè)時(shí)鐘周期=4微秒
; 實(shí)際延時(shí)時(shí)間 = (r16 * 4) 微秒
delay_us:
nop ; 空操作(1周期)
nop ; 空操作(1周期)
nop ; 空操作(1周期)
dec r16 ; 計(jì)數(shù)器遞減(1周期)
brne delay_us ; 不為零則跳轉(zhuǎn)(2周期為零跳轉(zhuǎn)/1周期繼續(xù))
ret ; 返回
; =============================================
; 程序結(jié)束
; =============================================
|
評(píng)分
-
查看全部評(píng)分
|