📄 pic12i2c.sdi
字号:
,,,; Inputs: EEPROM Address EEADDR
,,,; EEPROM Data EEDATA
,,,; Outputs: Return 01 in W if OK, else return 00 in W
,,,;
,,,; READ_CURRENT: Read EEPROM at address currently held by EE device.
,,,; Inputs: NONE
,,,; Outputs: EEPROM Data EEDATA
,,,; Return 01 in W if OK, else return 00 in W
,,,;
,,,; READ_RANDOM: Read EEPROM byte at supplied address
,,,; Inputs: EEPROM Address EEADDR
,,,; Outputs: EEPROM Data EEDATA
,,,; Return 01 in W if OK, else return 00 in W
,,,;
,,,; Note: EEPROM subroutines will set bit 7 in PC_OFFSET register if the
,,,; EEPROM acknowledged OK, else that bit will be cleared. This bit
,,,; can be checked instead of refering to the value returned in W
,,,;***************************************************************************
,,,;********************** Set up EEPROM control bytes ************************
,,,;***************************************************************************
0022,,READ_CURRENT,READ_CURRENT
0022,0C84,, MOVLW B'10000100' ; PC offset for read current addr. EE_OK bit7='1'
0023,003A,, MOVWF PC_OFFSET ; Load PC offset
0024,0A52,, GOTO INIT_READ_CONTROL
,,,
0025,,WRITE_BYTE,WRITE_BYTE
0025,0C80,, MOVLW B'10000000' ; PC offset for write byte. EE_OK: bit7 = '1'
0026,0A28,, GOTO INIT_WRITE_CONTROL
,,,
0027,,READ_RANDOM,READ_RANDOM
0027,0C83,, MOVLW B'10000011' ; PC offset for read random. EE_OK: bit7 = '1'
,,,
0028,,INIT_WRITE_CONTROL,INIT_WRITE_CONTROL
0028,003A,, MOVWF PC_OFFSET ; Load PC offset register, value preset in W
0029,0CA0,, MOVLW B'10100000' ; Control byte with write bit, bit 0 = '0'
,,,
002A,,START_BIT,START_BIT
002A,04C6,, BCF I2C_PORT,SDA ; Start bit, SDA and SCL preset to '1'
,,,
,,,
,,,;******* Set up output data (control, address, or data) and counter ********
,,,;***************************************************************************
002B,,PREP_TRANSFER_BYTE,PREP_TRANSFER_BYTE
002B,003D,, MOVWF EEBYTE ; Byte to transfer to EEPROM already in W
002C,0C08,, MOVLW .8 ; Counter to transfer 8 bits
002D,003E,, MOVWF COUNTER
,,,#ifdef EMULATED
,,, movlw 0x00 ; make sure both are outputs
,,, tris I2C_PORT
,,,#endif
,,,
,,,
,,,;************ Clock out data (control, address, or data) byte ************
,,,;***************************************************************************
002E,,OUTPUT_BYTE,OUTPUT_BYTE
002E,04E6,, BCF I2C_PORT,SCL ; Set clock low during data set-up
002F,037D,, RLF EEBYTE, F ; Rotate left, high order bit into carry bit
0030,04C6,, BCF I2C_PORT,SDA ; Set data low, if rotated carry bit is
0031,0603,, SKPNC ; a '1', then:
0032,05C6,, BSF I2C_PORT,SDA ; reset data pin to a one, otherwise leave low
0033,0000,, NOP
0034,05E6,, BSF I2C_PORT,SCL ; clock data into EEPROM
0035,02FE,, DECFSZ COUNTER, F ; Repeat until entire byte is sent
0036,0A2E,, GOTO OUTPUT_BYTE
0037,0000,, NOP
,,,
,,,;************************** Acknowledge Check *****************************
,,,;***************************************************************************
0038,04E6,, BCF I2C_PORT,SCL ; Set SCL low, 0.5us < ack valid < 3us
0039,0000,, NOP
003A,05C6,, BSF I2C_PORT,SDA
,,,#ifdef EMULATED
,,, movlw (0x01 << SDA) ; make SDA an input
,,, tris I2C_PORT
,,,#endif
003B,0A3C,, GOTO $+1 ; May be necessary for SCL Tlow at low voltage,
003C,05E6,, BSF I2C_PORT,SCL ; Raise SCL, EEPROM acknowledge still valid
003D,06C6,, BTFSC I2C_PORT,SDA ; Check SDA for acknowledge (low)
003E,04FA,, BCF PC_OFFSET,EE_OK ; If SDA not low (no ack), set error flag
003F,04E6,, BCF I2C_PORT,SCL ; Lower SCL, EEPROM release bus
0040,07FA,, BTFSS PC_OFFSET,EE_OK ; If no error continue, else stop bit
0041,0A69,, GOTO STOP_BIT
,,,#ifdef EMULATED
,,, movlw 0x00 ; SDA back to an output
,,, tris I2C_PORT
,,,#endif
,,,
,,,
,,,;***** Set up program counter offset, based on EEPROM operating mode *****
,,,;***************************************************************************
0042,021A,, MOVF PC_OFFSET,W
0043,0E0F,, ANDLW B'00001111'
0044,01E2,, ADDWF PCL, F
0045,0A4C,, GOTO INIT_ADDRESS ;PC offset=0, write control done, send address
0046,0A4F,, GOTO INIT_WRITE_DATA ;PC offset=1, write address done, send data
0047,0A69,, GOTO STOP_BIT ;PC offset=2, write done, send stop bit
0048,0A4C,, GOTO INIT_ADDRESS ;PC offset=3, write control done, send address
0049,0A52,, GOTO INIT_READ_CONTROL ;PC offset=4, send read control
004A,0A58,, GOTO READ_BIT_COUNTER ;PC offset=5, set counter and read byte
004B,0A69,, GOTO STOP_BIT ;PC offset=6, random read done, send stop
,,,
,,,
,,,;********** Initalize EEPROM data (address, data, or control) bytes ******
,,,;***************************************************************************
004C,,INIT_ADDRESS,INIT_ADDRESS
004C,02BA,, INCF PC_OFFSET, F ; Increment PC offset to 2 (write) or to 4 (read)
004D,021B,, MOVF EEADDR,W ; Put EEPROM address in W, ready to send to EEPROM
004E,0A2B,, GOTO PREP_TRANSFER_BYTE
,,,
,,,
004F,,INIT_WRITE_DATA,INIT_WRITE_DATA
004F,02BA,, INCF PC_OFFSET, F ; Increment PC offset to go to STOP_BIT next
0050,021C,, MOVF EEDATA,W ; Put EEPROM data in W, ready to send to EEPROM
0051,0A2B,, GOTO PREP_TRANSFER_BYTE
,,,
0052,,INIT_READ_CONTROL,INIT_READ_CONTROL
0052,05E6,, BSF I2C_PORT,SCL ; Raise SCL
0053,0000,, nop
0054,05C6,, BSF I2C_PORT,SDA ; raise SDA
0055,02BA,, INCF PC_OFFSET, F ; Increment PC offset to go to READ_BIT_COUNTER next
0056,0CA1,, MOVLW B'10100001' ; Set up read control byte, ready to send to EEPROM
0057,0A2A,, GOTO START_BIT ; bit 0 = '1' for read operation
,,,
,,,
,,,;************************** Read EEPROM data *****************************
,,,;***************************************************************************
0058,,READ_BIT_COUNTER,READ_BIT_COUNTER
0058,05C6,, BSF I2C_PORT,SDA
0059,0000,, NOP
005A,05E6,, BSF I2C_PORT,SCL ; set data bit to 1 so we're not pulling bus down.
005B,0C08,, MOVLW .8 ; Set counter so 8 bits will be read into EEDATA
005C,003E,, MOVWF COUNTER
,,,#ifdef EMULATED
,,, movlw (0x01 << SDA)
,,, tris I2C_PORT
,,,#endif
,,,
005D,,READ_BYTE,READ_BYTE
005D,05E6,, BSF I2C_PORT,SCL ; Raise SCL, SDA valid. SDA still input from ack
005E,0503,, SETC ; Assume bit to be read = 1
005F,07C6,, BTFSS I2C_PORT,SDA ; Check if SDA = 1
0060,0403,, CLRC ; if SDA not = 1 then clear carry bit
0061,037C,, RLF EEDATA, F ; rotate carry bit (=SDA) into EEDATA;
0062,04E6,, BCF I2C_PORT,SCL ; Lower SCL
0063,05C6,, BSF I2C_PORT,SDA ; reset SDA
0064,02FE,, DECFSZ COUNTER, F ; Decrement counter
0065,0A5D,, GOTO READ_BYTE ; Read next bit if not finished reading byte
,,,
0066,05E6,, BSF I2C_PORT,SCL
0067,0000,, NOP
0068,04E6,, BCF I2C_PORT,SCL
,,,;****************** Generate a STOP bit and RETURN ***********************
,,,;***************************************************************************
0069,,STOP_BIT,STOP_BIT
,,,#ifdef EMULATED
,,, movlw 0x00 ; set SDA as output
,,, tris I2C_PORT
,,,#endif
0069,04C6,, BCF I2C_PORT,SDA ; SDA=0, on TRIS, to prepare for transition to '1'
006A,05E6,, BSF I2C_PORT,SCL ; SCL = 1 to prepare for STOP bit
006B,0A6C,, GOTO $+1 ; 4 NOPs neccessary for I2C spec Tsu:sto = 4.7us
006C,0A6D,, GOTO $+1
006D,05C6,, BSF I2C_PORT,SDA ; Stop bit, SDA transition to '1' while SCL high
,,,
006E,07FA,, BTFSS PC_OFFSET,EE_OK ; Check for error
006F,0800,, RETLW NO ; if error, send back NO
0070,0801,, RETLW OK ; if no error, send back OK
,,,
,,,;Note: SDA and SCL still being driven by master, both set to outputs.
,,,;****************************************************************************
,,,;************************ End EEPROM Subroutines **************************
,,,
,,,
,,, END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -