Blame | Last modification | View Log | RSS feed
list p=16F84Ainclude "p16F84a.inc";***** CONFIGURATION__CONFIG _PWRTE_ON & _HS_OSC & _WDT_OFF; pin assignments#define SDA 0 ; Pin 0#define SCL 1 ; Pin 1#define TRIS_SDA TRISB,SDA#define TRIS_SCL TRISB,SCL#define I2C_SDA PORTB,SDA#define I2C_SCL PORTB,SCL#define LED PORTB,2#define I2C_SLAVE1 0x27#define I2C_SLAVE2 0x26CBLOCK 0CH_I ; Loop counterbyte_send ; Byte to send to i2cbyte_read ; Byte read from i2cbyte_temp ; Store byte while address sendi2c_addr ; Address to read/writei2c_ret ; I2C Return Valuedly_loop1 ; Loops for delaysdly_loop2ENDCORG 0goto start ; jump over to main routine;***** Initialisationstart; configure portsclrw ; configure PORTB as all outputstris PORTBclrf PORTBmovlw b'00001011' ; RA0 - Input - Toggle SW, Mode Select; RA1 - Input - Pulse SW, Record; RA2 - Output - LED, Mode; RA3 - Input - Switch, Resettris PORTAclrf byte_sendclrf byte_read;***** Main loopmain_loopbsf LEDcall ReadByte ; Read byte from SLAVE2bcf LEDmovfw byte_read ; Copy the byte read;movlw b'10101010'movwf byte_send ; into the byte to sendcall Delay_Shortbsf LEDcall SendByte ; Send byte to SLAVE1bcf LEDcall Delay_Longgoto main_loopReadBytemovlw I2C_SLAVE2 ; Address of Slave2movwf i2c_addrbsf STATUS,C ; Set mode to readcall I2C_Start ; Send the address with modecall ReadAck;movf i2c_ret;btfss STATUS,Z;goto SendErrcall I2C_Read ; Read byte into byte_readcall ReadAckcall I2C_EndreturnSendBytemovfw byte_send ; Save the byte while sending addressmovwf byte_tempmovlw I2C_SLAVE1 ; 7-bit address of devmovwf i2c_addr ; Set it in the addressbcf STATUS,C ; Use Write mode ('0')call I2C_Start ; Start a transmissioncall ReadAck ; Wait for Ack from slave;movf i2c_ret ; Check return value;btfss STATUS,Z ; Goto SendEnd on NACK;goto SendErrmovfw byte_tempmovwf byte_send;movfw byte_send ; Copy byte to write (counter) to wcall I2C_Write ; Write the byte to the linecall ReadAck ; Should read byte from bus here; checking that its a Nackcall I2C_End ; End the packetreturnSendErrcall I2C_EndreturnI2C_Startrlf i2c_addr,f ; Attach mode (STATUS,C) to 1st bitcall Start ; Start the Transmovfw i2c_addrmovwf byte_send ; Send the complete addresscall I2C_Write ; Write byte to portreturnI2C_Endcall StopreturnI2C_Write;movwf byte_sendmovlw .8 ; 8 bits to sendmovwf _I_WriteBitrlf byte_send,f ; Move highest bit to Cbtfss STATUS,C ; If 'C' is clearcall SDA_Low ; -> Set data lowbtfsc STATUS,C ; If 'C' is setcall SDA_High ; -> Set data highcall SCL_Pulsedecfsz _I,f ; Decrement counter, if not cleargoto _WriteBit ; -> Send next bitcall SDA_Low ; Set low to allow slave to writereturnI2C_Readmovlw .8 ; 8 bits to readmovwf _Iclrf byte_read ; Clear the read bytebcf STATUS,Ccall SDA_High ; Set high so slave can write_ReadBitcall SCL_High ; Pull Clock high, bit should arrive;btfss I2C_SDA ; If sda is clearbcf STATUS,C ; -> Set status 0btfsc I2C_SDA ; If sda is setbsf STATUS,Ccall SCL_Low ; Send the clock lowrlf byte_read,f ; Move highest bit to Cdecfsz _I,f ; Decrement counter, if not cleargoto _ReadBit ; -> Send next bit;call SDA_Low ; Set low to allow slave to writereturnNack ; Clock a high SDAcall SDA_Highcall SCL_PulsereturnAck ; Clock a high SDAcall SDA_Lowcall SCL_PulsereturnReadAckcall SDA_High ; SDA high to allow slave to writecall SCL_Highclrf i2c_retbtfsc I2C_SDAbsf i2c_ret,0call SCL_LowreturnStartcall SDA_Highcall SCL_Highcall SDA_Lowcall SCL_LowreturnStop ; Bring SDA high while Clock highcall SCL_Lowcall SDA_Lowcall SCL_Highcall SDA_HighreturnSCL_Pulsecall SCL_Highcall SCL_LowreturnSDA_Highbsf STATUS,RP0 ; Bank 1bsf TRIS_SDA ; Make SDA pin inputbcf STATUS,RP0 ; Back to bank 0call Delay_ShortreturnSDA_Lowbcf I2C_SDAbsf STATUS,RP0bcf TRIS_SDA ; Make SDA pin outputbcf STATUS,RP0call Delay_ShortreturnSCL_Highbsf STATUS,RP0 ; Bank 1bsf TRIS_SCL ; Make SDA pin inputbcf STATUS,RP0 ; Back to bank 0call Delay_ShortreturnSCL_Lowbcf I2C_SCLbsf STATUS,RP0bcf TRIS_SCL ; Make SDA pin outputbcf STATUS,RP0call Delay_ShortreturnDelay_Short ; 25us delaymovlw .5movwf dly_loop2Delay_Short_1nopdecfsz dly_loop2,fgoto Delay_Short_1returnDelay_Longmovlw .250 ; 250ms delaymovwf dly_loop1Outermovlw .110 ; Close to 1ms when set to .110movwf dly_loop2Innernopnopnopnopnopnopdecfsz dly_loop2,fgoto Innerdecfsz dly_loop1,fgoto OuterreturnEND