Scenix I2CM_VP.SRC

; ******************************************************************************
; Virtual Peripheral: I2C Subroutines
;
; Length: 133 bytes (total)
; Authors: Chip Gracey, President, Parallax Inc.
;		 modified by Craig Webb, Consultant to Scenix Semiconductor, Inc.
; Written: 97/03/10 to 98/6/03
;
;******************************************************************************
;
;****** Assembler directives
;
; uses: SX28AC, 2 pages of program memory, 8 banks of RAM, high speed osc.
; operating in turbo mode, with 8-level stack & extended option reg.
; 
		DEVICE pins28,pages2,banks8,oschs
		DEVICE turbo,stackx,optionx
		ID 'I2C'			;program ID label
		RESET reset_entry ;set reset/boot address
;
;******************************* Program Variables ***************************
;
; Port Assignment: Bit variables
;
scl EQU RA.0 ;I2C clock
sda EQU RA.1 ;I2C data I/O
;
;
;****** Register definitions (bank 0)
;
		org 8 ;start of program registers
main = $ ;main bank
;
temp ds 1 ;temporary storage
byte ds 1 ;temporary UART/I2C shift reg.
flags DS 1 ;program flags register
;
seq_flag EQU flags.1 ;I2C: R/W mode (if sequential=1)
got_ack EQU flags.2 ; if we got ack signal
;
		org 90H ;bank4 variables
I2C EQU $ ;I2C bank
;
data DS 1 ;data byte from/for R/W
address DS 1 ;byte address
count DS 1 ;bit count for R/W
delay DS 1 ;timing delay for write cycle
byte_count DS 1 ;number of bytes in R/W
num_bytes DS 1 ;number of byte to view at once
save_addr DS 1 ;backup location for address
;
in_bit EQU byte.0 ;bit to receive on I2C
out_bit EQU byte.7 ;bit to transmit on I2C 
;
control_r = 10100001b ;control byte: read E2PROM
control_w = 10100000b ;control byte: write E2PROM
portsetup_r = 00000110b ;Port A config: read bit
portsetup_w = 00000100b ;Port A config: write bit
eeprom_size = 128 ;storage space of EEPROM
;
t_all = 31 ;bit cycle delay (62=5 usec)
;
;
		ORG	0h			;Program Start adress
;
;******************************** I2C Subroutines *****************************
;
; These routines write/read data to/from the 24LCxx EEPROM at a rate of approx.
; 200kHz. For faster* reads (up to 400 kHz max), read, write, start amd stop
; bit cycles and time between each bus access must be individually tailored
; using the CALL Bus_delay:custom entry point with appropriate values in the W
; register - in turbo mode: delay[usec] = 1/xtal[MHz] * (6 + 4 * (W-1)).
; Acknowledge polling is used to reduce delays between successive operations 
; where the first of the two is a write operation. In this case, the speed
; is limited by the EEPROM's storage time.
;
;****** Subroutine(s) : Write to I2C EEPROM
; These routines write a byte to the 24LCxxB EEPROM. Before calling this
; subroutine, the address and data registers should be loaded accordingly. The
; sequential mode flag should be clear for normal byte writing operation.
; To write in sequential/page mode, please see application note. 
;
; Input variable(s) : data, address, seq_flag
; Output variable(s) : none
; Variable(s) affected : byte, temp, count, delay
; Flag(s) affected : none
; Timing (turbo) : approx. 200 Kbps write rate
; : approx. 10 msec between successive writes
;
I2C_write CALL Set_address ;write address to slave
:page_mode MOV W,data ;get byte to be sent
		CALL Write_byte ;Send data byte
		JB seq_flag,:done ;is this a page write?
		CALL Send_stop ;no, signal stop condition
:done RETP ;leave and fix page bits
;
Set_address CALL Send_start ;send start bit
		MOV W,#control_w ;get write control byte
		CALL Write_byte ;Write it & use ack polling
		JNB got_ack,Set_address ; until EEPROM ready
		MOV W,address ;get EEPROM address pointer
		CALL Write_byte ; and send it
		RETP ;leave and fix page bits
;
Write_byte MOV byte,W ;store byte to send
		MOV count,#8 ;set up to write 8 bits
:next_bit CALL Write_bit ;write next bit
		RL byte ;shift over to next bit
		DJNZ count,:next_bit ;whole byte written yet?
		CALL Read_bit ;yes, get acknowledge bit
		SETB got_ack ;assume we got it
		SNB in_bit ;did we get ack (low=yes)?
		CLRB got_ack ;if not, flag it
;
; to use the LED as a 'no_ack' signal, the ':toggle_led' line in the interrupt
; section must be commented out, and the next 3 instructions uncommented.
; CLRB led_pin ;default: LED off
; SNB in_bit ;did we get ack (low=yes)?
; SETB led_pin ; if not, flag it with LED
;
		RETP ;leave and fix page bits
;
Write_bit MOVB sda,out_bit ;put tx bit on data line
		MOV !ra,#portsetup_w ;set Port A up to write
		JMP :delay1 ;100ns data setup delay
:delay1 JMP :delay2 ; (note: 250ns at low power)
:delay2 SETB scl ;flip I2C clock to high
; MOV W,#t_high ;get write cycle timing*
		CALL Bus_delay ;do delay while bus settles
		CLRB scl ;return I2C clock low
		MOV !ra,#portsetup_r ;set sda->input in case ack
; MOV W,#t_low ;get clock=low cycle timing*
		CALL Bus_delay ;allow for clock=low cycle
		RETP ;leave and fix page bits
;
Send_start SETB sda ;pull data line high
		MOV !ra,#portsetup_w ;setup I2C to write bit
		JMP :delay1 ;100ns data setup delay
:delay1 JMP :delay2 ; (note: 250ns at low power)
:delay2 SETB scl ;pull I2C clock high
; MOV W,#t_su_sta ;get setup cycle timing*
		CALL Bus_delay ;allow start setup time
:new CLRB sda ;data line goes high->low
; MOV W,#t_hd_sta ;get start hold cycle timing*
		CALL Bus_delay ;allow start hold time 
		CLRB scl ;pull I2C clock low
; MOV W,#t_buf ;get bus=free cycle timing*
		CALL Bus_delay ;pause before next function 
		RETP ;leave and fix page bits
;
Send_stop CLRB sda ;pull data line low
		MOV !ra,#portsetup_w ;setup I2C to write bit
		JMP :delay1 ;100ns data setup delay
:delay1 JMP :delay2 ; (note: 250ns at low power)
:delay2 SETB scl ;pull I2C clock high
; MOV W,#t_su_sto ;get setup cycle timing*
		CALL Bus_delay ;allow stop setup time
		SETB sda ;data line goes low->high
; MOV W,#t_low ;get stop cycle timing*
		CALL Bus_delay ;allow start/stop hold time 
		RETP ;leave and fix page bits
;
Bus_delay MOV W,#t_all ;get timing for delay loop
:custom MOV temp,W ;save it
:loop DJNZ temp,:loop ;do delay
		RETP ;leave and fix page bits
;
;****** Subroutine(s) : Read from I2C EEPROM
; These routines read a byte from a 24LCXXB E2PROM either from a new address
; (random access mode), from the current address in the EEPROM's internal
; address pointer (CALL Read_byte:current), or as a sequential read. In either
; the random access or current address mode, seq_flag should be clear. Please
; refer to the application note on how to access the sequential read mode.
;
; Input variable(s) : address, seq_flag
; Output variable(s) : data
; Variable(s) affected : byte, temp, count, delay
; Flag(s) affected : none
; Timing (turbo) : reads at approx. 200Kbps 
;
I2C_read CALL Set_address ;write address to slave
:current CALL Send_start ;signal start of read
		MOV W,#control_r ; get read control byte
		CALL Write_byte ; and send it
:sequential MOV count,#8 ;set up for 8 bits
		CLR byte ;zero result holder
:next_bit RL byte ;shift result for next bit
		CALL Read_bit ;get next bit
		DJNZ count,:next_bit ;got whole byte yet?
		MOV data,byte ;yes, store what was read
		SB seq_flag ;is this a sequential read?
:non_seq JMP Send_stop ; no, signal stop & exit
		CLRB out_bit ; yes, setup acknowledge bit
		CALL Write_bit ; and send it
		RETP ;leave and fix page bits
;
Read_bit CLRB in_bit ;assume input bit low
		MOV !ra,#portsetup_r ;set Port A up to read
		SETB scl ;flip I2C clock to high
; MOV W,#t_high ;get read cycle timing*
		CALL Bus_delay ;Go do delay
		SNB sda ;is data line high?
		SETB in_bit ;yes, switch input bit high
		CLRB scl ;return I2C clock low
; MOV W,#t_buf ;get bus=free cycle timing*
		CALL Bus_delay ;Go do delay
		RETP ;leave and fix page bits
;
; *****	High level functions: Store byte & Erase
;
Store_W		BANK I2C ;switch to EEPROM bank
		MOV data,W ;save incoming value
		CALL I2C_Write ;store it in EEPROM
		INC address ;move to next address
		INC byte_count ;adjust # bytes stored
		MOV W,eeprom_size ;get memory size
		MOV W,address-W ;are we past end?
		SNZ ;if not, skip ahead
		CLR address ;if so, reset it
:done RETP ;leave and fix page bits
;
Erase_Mem CLR address ;restore address pointer
		MOV num_bytes,#eeprom_size ;wipe whole mem
:wipeloop CLR data ;byte to wipe with=0
; MOV data,address ;byte to wipe with=addr
		CALL I2C_write ;wipe EEPROM byte
		INC address ;move to next address
		DJNZ num_bytes,:wipeloop ;Erased enough yet?
		CLR byte_count ;done, reset stored count
		CLR save_addr ;reset backup address
		RETP ;leave and fix page bits
;
;************************** End of I2C Subroutines ****************************
;
;***************************** MAIN PROGRAM CODE ******************************
;
;		ORG 100h
;
; Program execution begins here on power-up or after a reset
;
reset_entry
		mov ra,#%1011 ;initialize port RA
		mov !ra,#%0100 ;Set RA in/out directions
		CLR FSR ;reset all ram starting at 08h
:zero_ram SB FSR.4 ;are we on low half of bank?
		SETB FSR.3 ;If so, don't touch regs 0-7
		CLR IND ;clear using indirect addressing
		IJNZ FSR,:zero_ram ;repeat until done
		mov !option,#%11011111 ;disable rtcc interrupt
;
; Main Program Loop
;
:loop		MOV	W,#55			;example byte
		CALL Store_W ;Store byte in next I2c address
;
; <program code goes here>
;
		JMP :loop ;back to main loop
;
;***************
		END ;End of program code

file: /Techref/scenix/i2cm_vp.src, 13KB, , updated: 1999年2月20日 13:23, local time: 2025年9月4日 00:37,
40.74.122.252:LOG IN

©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://massmind.org/techref/scenix/i2cm_vp.src"> scenix i2cm_vp</A>

Did you find what you needed?

Welcome to massmind.org!

Welcome to massmind.org!

.

AltStyle によって変換されたページ (->オリジナル) /