欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

23LC1024 SRAM測試程序 - ASM完整版

[復制鏈接]
跳轉到指定樓層
樓主

; =============================================
; 23LC1024 SRAM測試程序 - ASM完整版
; =功能:完整的SRAM讀寫測試,包含UART輸出和LED指示
; =============================================

.include "m16def.inc"          ; 包含ATmega16定義文件

; 系統常量定義
.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時鐘引腳(PB7)
.equ CMD_READ  = 0x03          ; SRAM讀命令
.equ CMD_WRITE = 0x02          ; SRAM寫命令
.equ CMD_RDSR  = 0x05          ; 讀狀態寄存器命令
.equ CMD_WRSR  = 0x01          ; 寫狀態寄存器命令
.equ MODE_SEQ  = 0x40          ; 順序模式配置值
.equ UBRR_VAL  = 12            ; 波特率9600 @ 1MHz

; 數據段定義(SRAM變量)
.dseg
write_data:   .byte 1          ; 寫入數據存儲
read_data:    .byte 1          ; 讀取數據存儲  
addr_high:    .byte 1          ; 24位地址高字節
addr_mid:     .byte 1          ; 24位地址中字節
addr_low:     .byte 1          ; 24位地址低字節
temp:         .byte 1          ; 臨時變量
test_index:   .byte 1          ; 測試用例計數器
test_offset:  .byte 1          ; 測試表偏移量

; 代碼段定義
.cseg
.org 0x0000                    ; 程序起始地址
    rjmp main                  ; 復位向量跳轉到主程序

; 測試數據表 - 7個測試用例(地址+數據)
; 格式:地址高字節, 地址中字節, 地址低字節, 測試數據
test_table:
    .db 0x10, 0x00, 0x00, 0x11  ; 測試1: 地址 0x100000, 數據 0x11
    .db 0x20, 0x00, 0x00, 0x22  ; 測試2: 地址 0x200000, 數據 0x22  
    .db 0x00, 0x01, 0x00, 0x33  ; 測試3: 地址 0x000100, 數據 0x33
    .db 0x00, 0x00, 0x10, 0x44  ; 測試4: 地址 0x000010, 數據 0x44
    .db 0x30, 0x20, 0x10, 0x55  ; 測試5: 地址 0x302010, 數據 0x55
    .db 0x50, 0x20, 0x10, 0x65  ; 測試5: 地址 0x302010, 數據 0x65
    .db 0x80, 0x20, 0x10, 0x81  ; 測試5: 地址 0x302010, 數據 0x81


; 消息字符串定義(中英雙語注釋)
msg_title:    .db "23LC1024 ASM 完整測試",13,10,0                    ; 程序標題
msg_init:     .db "SRAM 已初始化",13,10,0                           ; SRAM初始化完成
msg_test:     .db "正在運行完整測試...",13,10,0                      ; 測試開始提示
msg_ok:       .db " [通過]",13,10,0                                 ; 測試通過
msg_fail:     .db " [失敗]",13,10,0                                 ; 測試失敗
msg_addr:     .db "Addr 0x",0                                       ; 地址顯示前綴
msg_write:    .db " W=0x",0                                         ; 寫入數據顯示前綴
msg_read:     .db " R=0x",0                                         ; 讀取數據顯示前綴
msg_crlf:     .db 13,10,0,0                                         ; 回車換行
msg_done:     .db "=== 所有測試已完成! ===",13,10,0                 ; 測試完成提示
; =============================================
; 主程序
; =系統初始化和測試流程控制
; =============================================
main:
    ; 初始化堆棧指針
    ldi r16, high(RAMEND)      ; 加載RAM結束地址高字節
    out SPH, r16               ; 設置堆棧指針高字節
    ldi r16, low(RAMEND)       ; 加載RAM結束地址低字節
    out SPL, r16               ; 設置堆棧指針低字節

    rcall uart_init            ; 初始化UART串口

    ; 顯示程序標題
    ldi ZL, low(2*msg_title)   ; 加載標題字符串地址低字節
    ldi ZH, high(2*msg_title)  ; 加載標題字符串地址高字節
    rcall uart_puts            ; 發送標題字符串
    rcall uart_crlf            ; 發送回車換行

    ; 初始化SRAM
    rcall sram_init            ; 初始化SPI和SRAM

    ; 顯示初始化完成信息
    ldi ZL, low(2*msg_init)    ; 加載初始化消息地址低字節
    ldi ZH, high(2*msg_init)   ; 加載初始化消息地址高字節
    rcall uart_puts            ; 發送初始化消息

    ; 顯示測試開始信息
    ldi ZL, low(2*msg_test)    ; 加載測試消息地址低字節
    ldi ZH, high(2*msg_test)   ; 加載測試消息地址高字節
    rcall uart_puts            ; 發送測試消息
    rcall uart_crlf            ; 發送回車換行

    ; 設置測試用例數量
    ldi r16, 7                 ; 設置總共運行5個測試用例
    sts test_index, r16        ; 保存測試計數器

    ldi r17, 0                 ; 初始化測試表偏移量為0
    sts test_offset, r17       ; 保存偏移量

; 測試循環主程序
run_tests:
    ; 設置Z指針指向測試參數表的起始地址
    ldi ZL, low(2*test_table)  ; 加載測試表地址低字節
    ldi ZH, high(2*test_table) ; 加載測試表地址高字節

    ; 加上當前測試的偏移量以定位到具體測試用例
    lds r17, test_offset       ; 加載當前偏移量
    add ZL, r17                ; 加到Z指針低字節
    ldi r18, 0                 ; 清零用于帶進位加法
    adc ZH, r18                ; 加到Z指針高字節(帶進位)

    ; 從程序存儲器加載測試參數
    lpm r16, Z+                ; 加載地址高字節并遞增指針
    sts addr_high, r16         ; 保存地址高字節
    lpm r16, Z+                ; 加載地址中字節并遞增指針
    sts addr_mid, r16          ; 保存地址中字節
    lpm r16, Z+                ; 加載地址低字節并遞增指針
    sts addr_low, r16          ; 保存地址低字節
    lpm r16, Z+                ; 加載測試數據并遞增指針
    sts write_data, r16        ; 保存要寫入的數據

    ; 執行SRAM讀寫測試
    rcall sram_write_byte      ; 向SRAM寫入測試數據
    rcall sram_read_byte       ; 從SRAM讀取數據
    rcall display_test_result  ; 顯示測試結果

    ; 更新偏移量指向下一個測試用例(每個測試4個字節參數)
    lds r17, test_offset       ; 加載當前偏移量
    subi r17, -4               ; 偏移量加4(指向下一個測試)
    sts test_offset, r17       ; 保存更新后的偏移量

    ; 檢查是否完成所有測試
    lds r16, test_index        ; 加載剩余測試計數
    dec r16                    ; 計數器減1
    sts test_index, r16        ; 保存更新后的計數
    brne run_tests             ; 如果未完成,繼續下一個測試

    ; 所有測試完成,顯示結束信息
    ldi ZL, low(2*msg_done)    ; 加載完成消息地址低字節
    ldi ZH, high(2*msg_done)   ; 加載完成消息地址高字節
    rcall uart_puts            ; 發送完成消息

    ; 成功指示 - 閃爍LED (如果PC0連接了LED)
    sbi DDRC, 0                ; 設置PC0為輸出(連接LED)
success:
    sbi PORTC, 0               ; 點亮LED(PC0輸出高電平)
    ldi r16, 100               ; 設置延時100ms
    rcall delay_ms             ; 調用延時子程序
    cbi PORTC, 0               ; 熄滅LED(PC0輸出低電平)
    ldi r16, 100               ; 設置延時100ms
    rcall delay_ms             ; 調用延時子程序
    rjmp success               ; 無限循環閃爍LED

; =============================================
; 顯示測試結果
; =功能:顯示SRAM測試的詳細結果和驗證狀態
; =============================================
display_test_result:
    ; 顯示地址信息
    ldi ZL, low(2*msg_addr)    ; 加載"地址:"字符串地址低字節
    ldi ZH, high(2*msg_addr)   ; 加載"地址:"字符串地址高字節
    rcall uart_puts            ; 發送地址標簽字符串

    ; 顯示24位地址(高字節→中字節→低字節)
    lds r16, addr_high         ; 加載地址高字節
    rcall uart_puthex          ; 以十六進制顯示高字節
    lds r16, addr_mid          ; 加載地址中字節
    rcall uart_puthex          ; 以十六進制顯示中字節
    lds r16, addr_low          ; 加載地址低字節
    rcall uart_puthex          ; 以十六進制顯示低字節

    ; 顯示寫入的數據
    ldi ZL, low(2*msg_write)   ; 加載"寫入:"字符串地址低字節
    ldi ZH, high(2*msg_write)  ; 加載"寫入:"字符串地址高字節
    rcall uart_puts            ; 發送寫入標簽字符串

    lds r16, write_data        ; 加載之前寫入的數據
    rcall uart_puthex          ; 以十六進制顯示寫入的數據

    ; 顯示讀取的數據
    ldi ZL, low(2*msg_read)    ; 加載"讀取:"字符串地址低字節
    ldi ZH, high(2*msg_read)   ; 加載"讀取:"字符串地址高字節
    rcall uart_puts            ; 發送讀取標簽字符串

    lds r16, read_data         ; 加載從SRAM讀取的數據
    rcall uart_puthex          ; 以十六進制顯示讀取的數據

    ; 驗證測試結果:比較寫入和讀取的數據
    lds r17, write_data        ; 重新加載寫入的數據到r17
    lds r18, read_data         ; 加載讀取的數據到r18
    cp r17, r18                ; 比較兩個數據(r17 - r18)
    breq test_ok               ; 如果相等(Z=1),跳轉到成功處理

    ; 測試失敗處理
    ; 寫入和讀取的數據不匹配
    ldi ZL, low(2*msg_fail)    ; 加載"失敗"字符串地址低字節
    ldi ZH, high(2*msg_fail)   ; 加載"失敗"字符串地址高字節
    rcall uart_puts            ; 發送失敗信息
    ret                        ; 返回主程序

; 測試成功處理
test_ok:
    ; 寫入和讀取的數據完全匹配
    ldi ZL, low(2*msg_ok)      ; 加載"成功"字符串地址低字節
    ldi ZH, high(2*msg_ok)     ; 加載"成功"字符串地址高字節
    rcall uart_puts            ; 發送成功信息
    ret                        ; 返回主程序
; =============================================
; UART子程序
; UART串口通信相關功能子程序
; =============================================

; UART初始化子程序
; 功能:設置UART波特率、數據幀格式和使能發送
uart_init:
    ldi r16, low(UBRR_VAL)      ; 加載波特率分頻值的低字節
    out UBRRL, r16             ; 寫入波特率低字節寄存器
    ldi r16, high(UBRR_VAL)     ; 加載波特率分頻值的高字節
    out UBRRH, r16             ; 寫入波特率高字節寄存器
    ldi r16, (1<<TXEN)         ; 設置TXEN位(發送使能)
    out UCSRB, r16             ; 寫入UART控制狀態寄存器B
    ldi r16, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; 設置URSEL(選擇UCSRC)、8位數據位
    out UCSRC, r16             ; 寫入UART控制狀態寄存器C
    ret                        ; 返回

; 發送單個字符子程序
; 輸入:r16 - 要發送的字符
uart_putchar:
    sbis UCSRA, UDRE           ; 跳過下條指令如果UDR空(UDRE=1)
    rjmp uart_putchar          ; UDR未空,繼續等待
    out UDR, r16               ; UDR已空,發送字符
    ret                        ; 返回

; 發送字符串子程序
; 輸入:Z指針 - 指向程序存儲器中的字符串(以null結尾)
uart_puts:
    lpm r16, Z+                ; 從程序存儲器加載字符并遞增Z指針
    tst r16                    ; 測試字符是否為0
    breq uart_puts_end         ; 如果是0,字符串結束
    rcall uart_putchar         ; 發送當前字符
    rjmp uart_puts             ; 繼續發送下一個字符
uart_puts_end:
    ret                        ; 返回

; 發送回車換行子程序
; 功能:發送CR(回車)和LF(換行)序列
uart_crlf:
    ldi ZL, low(2*msg_crlf)    ; 加載回車換行字符串地址低字節
    ldi ZH, high(2*msg_crlf)   ; 加載回車換行字符串地址高字節
    rcall uart_puts            ; 發送回車換行字符串
    ret                        ; 返回

; 發送十六進制數字子程序
; 輸入:r16 - 要發送的字節(以十六進制形式發送兩個字符)
uart_puthex:
    push r16                   ; 保存原始值
    swap r16                   ; 交換高低4位
    andi r16, 0x0F            ; 屏蔽高4位,保留低4位
    rcall hex_to_ascii         ; 轉換為ASCII字符
    rcall uart_putchar         ; 發送高4位對應的字符
    pop r16                    ; 恢復原始值
    andi r16, 0x0F            ; 屏蔽高4位,保留低4位
    rcall hex_to_ascii         ; 轉換為ASCII字符
    rcall uart_putchar         ; 發送低4位對應的字符
    ret                        ; 返回

; 十六進制到ASCII轉換子程序
; 輸入:r16 - 十六進制數字(0-15)
; 輸出:r16 - 對應的ASCII字符
hex_to_ascii:
    cpi r16, 10                ; 比較數字是否小于10
    brlo hex_digit             ; 如果小于10,跳轉到數字處理
    subi r16, -('A'-10)        ; 大于等于10,轉換為'A'-'F'
    ret                        ; 返回
hex_digit:
    subi r16, -'0'             ; 小于10,轉換為'0'-'9'
    ret                        ; 返回
; =============================================
; SPI子程序
; =SPI總線通信和SRAM操作相關子程序
; =============================================

; SPI初始化子程序
; 功能:配置SPI引腳方向和SPI控制寄存器
spi_init:
    sbi DDRB, MOSI_PIN         ; 設置MOSI引腳為輸出
    sbi DDRB, SCK_PIN          ; 設置SCK時鐘引腳為輸出
    sbi DDRB, SRAM_CS          ; 設置SRAM片選引腳為輸出
    cbi DDRB, MISO_PIN         ; 設置MISO引腳為輸入
    sbi PORTB, SRAM_CS         ; 拉高SRAM片選(不選中)
    ldi r16, (1<<SPE)|(1<<MSTR)|(1<<SPR0) ; 使能SPI、主機模式、時鐘分頻
    out SPCR, r16              ; 寫入SPI控制寄存器
    ret                        ; 返回

; SPI數據傳輸子程序
; 功能:通過SPI發送和接收一個字節
; 輸入:r16 - 要發送的數據
; 輸出:r16 - 接收到的數據
spi_transfer:
    out SPDR, r16              ; 啟動SPI傳輸,寫入數據到SPI數據寄存器
spi_wait:
    in r16, SPSR               ; 讀取SPI狀態寄存器
    sbrs r16, SPIF             ; 跳過下條指令如果傳輸完成(SPIF=1)
    rjmp spi_wait              ; 傳輸未完成,繼續等待
    in r16, SPDR               ; 傳輸完成,讀取接收到的數據
    ret                        ; 返回

; SRAM初始化子程序
; 功能:初始化SPI接口并配置SRAM工作模式
sram_init:
    rcall spi_init             ; 初始化SPI接口
    cbi PORTB, SRAM_CS         ; 拉低SRAM片選(選中芯片)
    ldi r16, CMD_WRSR          ; 加載寫狀態寄存器命令
    rcall spi_transfer         ; 發送命令
    ldi r16, MODE_SEQ          ; 加載順序模式配置值
    rcall spi_transfer         ; 發送模式配置
    sbi PORTB, SRAM_CS         ; 拉高SRAM片選(取消選中)
    ldi r16, 10                ; 設置延時10ms
    rcall delay_ms             ; 調用延時子程序
    ret                        ; 返回

; SRAM寫字節子程序
; 功能:向SRAM指定地址寫入一個字節數據
; 輸入:addr_high, addr_mid, addr_low - 24位地址
;       write_data - 要寫入的數據
sram_write_byte:
    cbi PORTB, SRAM_CS         ; 拉低SRAM片選(選中芯片)
    ldi r16, CMD_WRITE         ; 加載寫命令
    rcall spi_transfer         ; 發送寫命令
    lds r16, addr_high         ; 加載地址高字節
    rcall spi_transfer         ; 發送地址高字節
    lds r16, addr_mid          ; 加載地址中字節
    rcall spi_transfer         ; 發送地址中字節
    lds r16, addr_low          ; 加載地址低字節
    rcall spi_transfer         ; 發送地址低字節
    lds r16, write_data        ; 加載要寫入的數據
    rcall spi_transfer         ; 發送數據字節
    sbi PORTB, SRAM_CS         ; 拉高SRAM片選(取消選中)
    ldi r16, 5                 ; 設置延時5ms
    rcall delay_ms             ; 調用延時子程序
    ret                        ; 返回

; SRAM讀字節子程序
; 功能:從SRAM指定地址讀取一個字節數據
; 輸入:addr_high, addr_mid, addr_low - 24位地址
; 輸出:read_data - 讀取到的數據
sram_read_byte:
    cbi PORTB, SRAM_CS         ; 拉低SRAM片選(選中芯片)
    ldi r16, CMD_READ          ; 加載讀命令
    rcall spi_transfer         ; 發送讀命令
    lds r16, addr_high         ; 加載地址高字節
    rcall spi_transfer         ; 發送地址高字節
    lds r16, addr_mid          ; 加載地址中字節
    rcall spi_transfer         ; 發送地址中字節
    lds r16, addr_low          ; 加載地址低字節
    rcall spi_transfer         ; 發送地址低字節
    ldi r16, 0x00              ; 加載啞元數據用于接收
    rcall spi_transfer         ; 發送啞元數據并接收SRAM數據
    sts read_data, r16         ; 保存讀取到的數據
    sbi PORTB, SRAM_CS         ; 拉高SRAM片選(取消選中)
    ret                        ; 返回
; =============================================
; 延時子程序
; =功能:提供精確的微秒和毫秒級延時
; =============================================

; 毫秒延時子程序
; 輸入:r16 - 延時的毫秒數
; 使用寄存器:r16, r17, r18
delay_ms:
    push r17                   ; 保存r17寄存器
    push r18                   ; 保存r18寄存器
delay_ms_outer:
    ldi r17, 200               ; 設置外層循環計數器(200次)
delay_ms_inner:
    ldi r18, 250               ; 設置內層循環計數器(250次)
delay_ms_inner2:
    dec r18                    ; 內層循環遞減
    brne delay_ms_inner2       ; 內層循環未結束則繼續
    dec r17                    ; 外層循環遞減
    brne delay_ms_inner        ; 外層循環未結束則繼續
    dec r16                    ; 毫秒計數器遞減
    brne delay_ms_outer        ; 未達到指定毫秒數則繼續
    pop r18                    ; 恢復r18寄存器
    pop r17                    ; 恢復r17寄存器
    ret                        ; 返回

; 微秒延時子程序
; 輸入:r16 - 延時的微秒數
; 注意:基于1MHz時鐘,每個循環約4個時鐘周期=4微秒
; 實際延時時間 = (r16 * 4) 微秒
delay_us:
    nop                        ; 空操作(1周期)
    nop                        ; 空操作(1周期)
    nop                        ; 空操作(1周期)
    dec r16                    ; 計數器遞減(1周期)
    brne delay_us              ; 不為零則跳轉(2周期為零跳轉/1周期繼續)
    ret                        ; 返回
; =============================================
; 程序結束
; =============================================

評分

參與人數 2黑幣 +80 收起 理由
admin + 50 共享資料的獎勵!
wpppmlah + 30 贊一個!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表