Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include p16f886.inc
- processor p16f886 ;not really critical, can set in configure
- RESET CODE 0x0000
- goto START
- UDATA; gpr0
- var1 RES 1
- var2 RES 2
- i2c_address RES 1
- i2c_write_data RES 1
- i2c_add_search_delay RES 1
- CODE
- START:
- CALL SETUP_I2C
- NOP
- CALL FIND_I2C_ADDRESS
- NOP
- CALL LCD_I2C_INF_LOOP
- NOP
- GOTO $
- SETUP_I2C:
- ;Set SDA (RC4) and SCL (RC3) pins as input
- BANKSEL TRISC
- BSF TRISC, RC3
- BSF TRISC, RC4
- ;Enable I2C (bit5), use I2C Master mode (bits 3:0)
- ;clock set in this mode FOSC / (4 * (SSPADD+1))
- BANKSEL SSPCON
- MOVLW 0x28
- MOVWF SSPCON
- BANKSEL SSPCON2
- CLRF SSPCON2 ;SSPCON2 controls the actual operation. Init to 0
- ; SSPADD = (_XTAL_FREQ/(4*feq_K))-1;
- BANKSEL SSPADD
- MOVLW 0x18 ;decimal 24 gives 80Khz clock
- MOVWF SSPADD
- BANKSEL SSPSTAT
- CLRF SSPSTAT ;Clear out any status bits
- RETURN
- ;wait for I2C to stop being busy
- WAIT_I2C:
- ;check bit2 of SSPSTAT (in master mode 0 indicates completion)
- BANKSEL SSPSTAT
- BTFSC SSPSTAT,2
- GOTO $-1
- ;check the individual operations completion
- ;acken, rcen, pen, rsen, sen pg. 180
- test_sspcon2:
- BANKSEL SSPCON2
- MOVLW 0x1F
- ANDWF SSPCON2, 0
- BANKSEL STATUS
- BTFSS STATUS,Z ;repeat if status is not 0
- GOTO test_sspcon2
- RETURN
- START_I2C:
- ;function puts out the start condition after ensuring not busy
- CALL WAIT_I2C
- BANKSEL SSPCON2
- BSF SSPCON2, SEN
- RETURN
- STOP_I2C:
- ;function puts out the stop condition after ensuring not busy
- CALL WAIT_I2C
- BANKSEL SSPCON2
- BSF SSPCON2, PEN
- RETURN
- WRITE_I2C:
- ;function writes out to I2C, this is used for both add and data
- ;the data should be place ind i2c_write_data
- CALL WAIT_I2C
- BANKSEL i2c_write_data
- MOVF i2c_write_data,0
- BANKSEL SSPBUF
- MOVWF SSPBUF ;place the address or data in SSPBUF for
- ;transmission
- RETURN
- FIND_I2C_ADDRESS:
- ;This function repeatedly checks the I2C lines for presense of
- ;the pcf8574 chip and stores the address in i2c_address
- ;A retun or 1 indicates success
- ;address is 7 bits + LSB r/w`
- MOVLW 0x00 ;init W to 0
- BANKSEL i2c_address
- MOVWF i2c_address
- addr_search_again:
- CALL START_I2C ;assert start
- BANKSEL i2c_address
- MOVF i2c_address,0
- BANKSEL i2c_write_data
- MOVWF i2c_write_data ; pass the argument (data to transmit)
- ;MOVWF i2c_address ;save the data (actually address)
- CALL WRITE_I2C ;write it out on the bus
- BANKSEL SSPSTAT ;wait for transmission to complete
- BTFSC SSPSTAT,2
- GOTO $-1
- MOVLW 0xFF
- BANKSEL i2c_add_search_delay
- MOVWF i2c_add_search_delay
- MOVLW i2c_add_search_delay
- DECFSZ i2c_add_search_delay,1;decrement W, update W, skip if zero
- ;here 0, or 1 both mean the same
- GOTO $-1
- BANKSEL SSPCON2
- BTFSS SSPCON2, ACKSTAT ;bit ->0 means ack received
- GOTO addr_search_break
- ;MOVF i2c_address,0 ;restore the address, increment
- ;INCFSZ W,0 ;on a rollover FF-> 0 break out
- BANKSEL i2c_address
- INCFSZ i2c_address,1 ;increment add, resotre to w, skip on rollover
- GOTO addr_search_again
- addr_search_break:
- BANKSEL i2c_address
- MOVF i2c_address, 0
- BANKSEL STATUS
- BTFSC STATUS, Z ;skip if zero flag not set, else return 0
- RETLW 0x00 ;0 indicates no response on all address.
- RETLW 0x01
- LCD_I2C_INF_LOOP:
- ;just an infinite loop writing via I2C to the LCD
- ;this is just used to manually program it during ICD
- ;For the i2c lcd backpack, this is the pin mapping (D0-3 are tied high for 4bit md)
- ;Bit 7 6 5 4 3 2 1 0
- ;conn D7 D6 D5 D4 LED e rw rs
- ;To use the 1602 in 4 bit mode follow these rules:
- ;1. Start with the 4 bit config write. The lower nibble is tied low/high. so
- ;the first one would effectivley be an 8 bit write to set 4 bit mode
- ;i.e. 88,8c,88 (e -> 0,1,0 with constant data). When it switches modes, it auto
- ;goes into 2 rows mode dunno why
- ;2. Now it's in 4 bit mode, send nibbles msb first, strobing e every time
- ;e.g to set the row count to two, 5x7 char 28,2c,28,88,8c,88
- ;3. clear the display and we can start using it for displaying letter.
- ;CALL START_I2C
- CALL I2C_START
- BANKSEL i2c_address
- MOVF i2c_address, 0
- MOVWF i2c_write_data
- CALL WRITE_I2C ;write address
- NOP
- CALL WAIT_I2C
- ;directly modify i2c_write_data address
- NOP
- CALL WRITE_I2C
- NOP
- CALL STOP_I2C
- NOP
- GOTO LCD_I2C_INF_LOOP
- RETURN
- END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement