⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 8051 smb (asm).asm

📁 SMBUS function by 8051 (assembly)
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;---------------------------------------------------------------------------------
;
; Copyright 2001 Cygnal Integrated Products, Inc.
;
; Program: SMBus_EX1.asm
; Created on: 2/21/01
; Last mod  : 27 AUG 03 -- BW
; Created by: JS
;
; Example code to interface a single 256-byte EEPROM to a C8051F00x via the SMBus
; Code assumes a single EEPROM with  slave address 1010000 is connected on 
; the SDA and SCL lines, and no other masters are on the bus.
; 
; The SEND routine performs a 1-byte write to the EEPROM.  This consists of (1) START, 
; (2) slave address + W, (3) memory location byte write, and (4) a data byte write.
; 
; STEPS FOR WRITING TO EEPROM:
;   1) Load slave address into SLA_ADD
;   2) Load memory address into MEM_ADD
;   3) Load data byte into TRANSMIT_BYTE. 
;   4) Call SEND
;
; The RECEIVE routine performs a 1-byte read from the EEPROM. This consists of (1)
; START, (2) slave address + W, (3) memory location byte write, (4) repeated START,
; (5) slave address + R, (6) data byte read.
;
; STEPS FOR RECEIVING DATA:
;   1) Load slave address into SLA_ADD
;   2) Load memory address into MEM_ADD
;   3) Call RECEIVE
;   4) Read RECEIVE_BYTE
;
; The SMBus state table is broken into 8-byte state segments, allowing the SMBus 
; status code (SMB0STA) to be used as a state index.  Note that this leaves only
; 8 bytes of code space per SMBus state definition. As a result, certain tasks
; have been altered to limit state definition lengths:
;
; 1) The SMB_MTDBACK state (Master transmitter, data byte sent, ACK received) is 
; reduced to a bit-check and branch operation.  The branch is outside of the state 
; table, so that a larger code segment may be executed for this state. 
;
; 2) Three data bytes are used for slave address storage: SLA_ADD, WRI_ADD, READ_ADD.
; Rather than using bit-wise operations in the SMBus states, each transfer routine 
; pre-loads the address values.  Since a RECEIVE includes both a WRITE and READ
; transfer, two address bytes are necessary - WRI_ADD and READ_ADD.  SLA_ADD is used
; as a generic slave chip select before a function call. 
;
; Note that SLA_ADD is equivalent to WRI_ADD, since WRI_ADD = SLA_ADD + W (W=0). 
; The two are left separate to clarify the demonstration.
;
;-----------------------------------------------------------------------------------

;-----------------------------------------------------------------------------------
; EQUATES
;-----------------------------------------------------------------------------------

   $include (c8051f000.inc)          ; Include register definition file.

   WRITE           EQU   00h         ; SMBus WRITE command
   READ            EQU   01h         ; SMBus READ command

   CHIP_A          EQU   0A0h        ; EEPROM slave address

   ; SMBus States
   SMB_BUS_ERROR   EQU   00h         ; (all modes) BUS ERROR
   SMB_START       EQU   08h         ; (MT & MR) START transmitted
   SMB_RP_START    EQU   10h         ; (MT & MR) repeated START
   SMB_MTADDACK    EQU   18h         ; (MT) Slave address + W transmitted;
                                     ;  ACK received
   SMB_MTADDNACK   EQU   20h         ; (MT) Slave address + W transmitted;
                                     ;  NACK received
   SMB_MTDBACK     EQU   28h         ; (MT) data byte transmitted; ACK rec'vd
   SMB_MTDBNACK    EQU   30h         ; (MT) data byte transmitted; NACK rec'vd
   SMB_MTARBLOST   EQU   38h         ; (MT) arbitration lost
   SMB_MRADDACK    EQU   40h         ; (MR) Slave address + R transmitted;
                                     ;  ACK received
   SMB_MRADDNACK   EQU   48h         ; (MR) Slave address + R transmitted;
                                     ;  NACK received
   SMB_MRDBACK     EQU   50h         ; (MR) data byte rec'vd; ACK transmitted
   SMB_MRDBNACK    EQU   58h         ; (MR) data byte rec'vd; NACK transmitted


;-----------------------------------------------------------------------------------
; VARIABLES
;-----------------------------------------------------------------------------------

MYDATA      SEGMENT DATA             ; declare DATA segment
            RSEG  MYDATA             ; select DATA segment


   TRANSMIT_BYTE:  DS    1           ; Holds a byte to be transmitted by the SMBus
   RECEIVE_BYTE:   DS    1           ; Holds a byte just received by the SMBus
   SLA_ADD:        DS    1           ; Holds the slave address
   WRI_ADD:        DS    1           ; Holds the slave address + WRITE
   READ_ADD:       DS    1           ; Holds the slave address + READ
   MEM_ADD:        DS    1           ; EEPROM memory location to be accessed
    
    ; Variables used for testing.
   TEST_COUNT:     DS    1           ; Test counter variable
   TEST_BYTE:      DS    1           ; Test data
   TEST_ADDR:      DS    1           ; Test memory location

MYBITS      SEGMENT BIT
            RSEG  MYBITS

   RW:             DBIT  1           ; R/W command bit. 1=READ, 0=WRITE
   SM_BUSY:        DBIT  1           ; SMBus Busy flag (kept in software)
   BYTE_SENT:      DBIT  1           ; Used to indicate what byte was just sent:
                                     ;   1: EEPROM memory address sent
                                     ;   0: Data byte sent
   
;-------------------
; STACK

STACK       SEGMENT IDATA            ; declare STACK segment
            RSEG  STACK
            DS 80h                   ; reserve 128 bytes for stack

;------------------------------------------------------------------------------------
; RESET and INTERRUPT VECTORS
;------------------------------------------------------------------------------------

CSEG
   
; Reset Vector
   org   00h
   ljmp  Reset_Vector
   
; SMBus Interrupt Vector
   org   03Bh
   ljmp  SMBus_ISR

MYCODE      SEGMENT CODE
            RSEG MYCODE
            USING 0
   
;--------------------------------------------------------------------------------------
; Reset Vector
; 
; - Disables Watchdog Timer
; - Routes SDA and SCL to GPIO pins via the crossbar
; - Enables crossbar
; - Jumps to MAIN


Reset_Vector:

   mov   WDTCN, #0DEh                 ; Disable Watchdog Timer
   mov   WDTCN, #0ADh

   mov   SP, #STACK                   ; Initialize Stack Pointer   

   orl   OSCICN, #03h                 ; Set internal oscillator to highest setting
                                      ; (16 MHz)

   mov   XBR0, #01h                   ; Route SMBus to GPIO pins through crossbar
   mov   XBR2, #40h                   ; Enable crossbar and weak pull-ups

   ljmp   MAIN

;------------------------------------------------------------------------------------
; MAIN PROGRAM
;------------------------------------------------------------------------------------

MAIN:
   acall SMBus_Init                  ; Initialize SMBus
   setb  EA                          ; Enable global interrupts

   mov   TEST_BYTE, #0ffh            ;   
   mov   TEST_ADDR, #00h             ; Load initial test values
   mov   TEST_COUNT, #0feh           ;

; TEST CODE--------------------------------------------------------------------------


TEST:

   ; Send TEST_BYTE to memory location TEST_ADDR
   mov   SLA_ADD, #CHIP_A            ; Load slave address
   mov   TRANSMIT_BYTE, TEST_BYTE    ; Load transmit data into TRANSMIT_BYTE
   mov   MEM_ADD, TEST_ADDR          ; Load memory address into MEM_ADD
   acall SEND                        ; Call send routine

   ; Read memory location TEST_ADDR into RECEIVE_BYTE
   mov   SLA_ADD, #CHIP_A            ; Load slave address
   mov   MEM_ADD, TEST_ADDR          ; Load memory address into MEM_ADD
   acall RECEIVE                     ; Call receive routine

   ; Compare byte received to byte sent
   mov   A, RECEIVE_BYTE             ; Load received byte into accumulator
   cjne  A, TEST_BYTE, END_TEST      ; Compare sent byte to received byte
                                     ; Jump to END_TEST if not equal

   ; Change test variables
   dec   TEST_BYTE                   ; If sent=received, change test variables
   inc   TEST_ADDR                   ; and cycle through again.
   
   ; Cycle through again if TEST_COUNTER not zero   
   djnz  TEST_COUNT, TEST            ; Decrement counter, loop back to beginning
   mov   A, #99h                     ; Load accumulator with 99h if test successful.
   
END_TEST:

   jmp   $                           ; Spin
;---------------------------------------------------------------------------------------
; SUBROUTINES
;---------------------------------------------------------------------------------------

;---------------------------------------------------------------------------------------
; SEND subroutine.  Assumes that the slave address, memory location, and transmit
; data have all been loaded into their associated variables. This routine manages
; the SM_BUSY bit, sets RW=WRITE, loads the WRI_ADD, and initiates the transfer.
;
SEND:

   push   ACC                        ; Preserve accumulator
   jb     SM_BUSY, $                 ; Wait for SMBus to be free
   clr    RW                         ; RW = 0 (WRITE)


   mov    A, SLA_ADD                 ; Store SLA_ADD + WRITE
   orl    A, #WRITE                  ; in WRI_ADD
   mov    WRI_ADD, A                 ;

   setb   SM_BUSY                    ; Occupy SMBus
   setb   STA                        ; Initiate Transfer
   pop    ACC                        ; Restore accumulator

   ret

;---------------------------------------------------------------------------------------
; RECEIVE subroutine. Assumes that the slave address and memory location have been 
; loaded into their associated variables. This routine manages the SM_BUSY bit, sets
; RW=READ, loads the READ_ADD and WRI_ADD, and initiates the transfer.
; 
; Note that the RECEIVE transfer consists of a WRITE of the memory location to be accessed,
; followed by a repeated START and a READ operation.  Therefore, both WRI_ADD
; and READ_ADD are used by this routine.
RECEIVE:

   push  ACC                          ; Preserve accumulator
   jb    SM_BUSY, $                   ; Wait for SMBus to be free
   setb  RW                           ; RW = 1 (READ)

   mov   A, SLA_ADD                   ; Store SLA_ADD + WRITE
   orl   A, #WRITE                    ; in WRITE_ADD
   mov   WRI_ADD, A                   ;
   
   mov   A, SLA_ADD                   ; Store SLA_ADD + READ

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -