Roberts II, Charles K. wrote: > > READ_DAC_DIRECT > ;The high and low bytes of the DAC value are passed out of DAC_RH, > DAC_RL ;which are in BANK0 > > DISABLE_IRQ > BANK1 > BSF SSPCON2,SEN ;set start bit Correct. You might want to clear SSPIF first, just in case. > > BANK0 > BTFSS PIR1,SSPIF ; wait for interrupt flag to be set > GOTO $-1 > BCF PIR1,SSPIF ;clear irq flag > > MOVLW 0x19 > MOVWF SSPBUF ;send out the address Correct. > > > BTFSS PIR1,SSPIF ; wait for interrupt flag to be set > GOTO $-1 > BCF PIR1,SSPIF ;clear irq flag > > > BANK1 > BTFSC SSPCON2,ACKSTAT ;Check if message acknowledged by D/A > GOTO $-1 The ACK bit is already there (or not) - no need to "wait" for it to come. Just test it, and if it is set (no ACK), send a stop bit and signal an error, or just send a stop bit and retry the whole thing. > BSFSS PCON2,RCEN ;Place MSSP into receive mode That should be BSF SSPCON2,RCEN How does PCON2 even compile? It should say undefined symbol. > > BANK1 > BTFSS SSPSTAT,BF ;wait for input buffer to be filled > GOTO $-1 > > BANK0 > BSF PIR1,SSPIF ;set interrupt flag I usually just wait for SSPIF and forget about BF. Also, why do you _set_ SSPIF? > > BANK1 > BCF SSPCON2,ACKDT ;Clear acknowledge data bit Correct. But maybe move it down with ACKEN for clarity. > > BANK0 > BCF PIR1,SSPIF ;clear irq flag > MOVF SSPBUF,W ;move received data from SSPBUF to W > MOVWF DAC_RH ;write data to DAC_RH Correct. > > BANK1 > BSF SSPCON2,ACKEN ;Set acknowledge sequence enable bit Correct. > > BANK0 > BSF PIR1,SSPIF ;set irq flag Again, why? > > > BANK1 > BSF SSPCON2,RCEN ;Start next receive Correct. > > BTFSC SSPCON2,RCEN ; wait for receive bit to be cleared > GOTO$-1 Why do you use a different checking method the second byte? Be consistent. > > BANK0 > MOVF SSPBUF,W ;read data from SSPBUF > MOVWF DAC_RL ;write data to DAC_RL > > BANK1 > BSF SSPCON2,ACKDT ;Set acknowledge bit > BSF SSPCON2,ACKEN ;Set acknowledge sequence enable bit > BSF SSPCON2,PEN ;set stop bit Correct. > > BANK0 > ENABLE_IRQ > RETURN ; and return > Here is the way I do it. This is to read a PCF8574 IC - a single byte. It stores it in RESBUF[1]. To read two bytes just duplicate that part of the code and make sure you sent an ACK (not NAK) the first time around. WAITSET is just: WAITSET MACRO REG,BIT ; wait for bit set btfss REG,BIT goto $-1 ENDM bcf PIR1,SSPIF ; clear any previous interrupt bsf STATUS,RP0 bsf SSPCON2,SEN ; send I2C START bcf STATUS,RP0 WAITSET PIR1,SSPIF bcf PIR1,SSPIF movlw (INPADDR<<1)|1 ; send address, read mode movwf SSPBUF WAITSET PIR1,SSPIF bcf PIR1,SSPIF bsf STATUS,RP0 btfsc SSPCON2,ACKSTAT ; ACK received? goto IN_NAK ; Nope. Problem. ;-- BEGIN read byte bsf SSPCON2,RCEN ; OK, receive data bcf STATUS,RP0 WAITSET PIR1,SSPIF bcf PIR1,SSPIF movf SSPBUF,W ; get data movwf RESBUF+1 bsf STATUS,RP0 bsf SSPCON2,ACKDT ; NAK (we do not want any more data) bsf SSPCON2,ACKEN ; send it bcf STATUS,RP0 WAITSET PIR1,SSPIF bcf PIR1,SSPIF bsf STATUS,RP0 ;-- END read byte bsf SSPCON2,PEN ; send I2C STOP bcf STATUS,RP0 WAITSET PIR1,SSPIF bcf PIR1,SSPIF Hope that helps. -- Hector Martin (hector@marcansoft.com) Public Key: http://www.marcansoft.com/hector.asc -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist