?? 8051 smb (asm).asm
字號:
;---------------------------------------------------------------------------------
;
; 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 + -