I have this project communicating MPR121 capacitive touch sensing keyboard with 8051 microcontroller, with some references I've implemented some I2C code for serial communication between master and slave, and I wanted to know whether the slave is responding to transmitted data, so whenever master sends the slave address and some other register or data I wanted to know whether there is a ACK or a NACK and show 1 in the 7seg display when is NACK as in 1-SDA high OR show 0 in 2nd 7seg display as in 0-SDA low, so I made
MOV P1,#00000001B MOV P0, #00000111B ; when NACK MOV P1,#00000010B MOV P0, #01111111B ; when ACK
But the problem is that even with the right and the wrong slave address 0 is showing in the display, where I'm wrong, and btw I tried this code and technique with some other sensor and it worked, is my sensor gone or my code wrong help please ..
Here is all the code:
; MPR121 Address slaveaddr EQU 10110100B ; I2C connections SCLPin BIT P3.6 ;I2C serial clock line. SDAPin BIT P3.7 ;I2C serial data line. IRQ BIT P3.2 ; I2C Data storage locations BitCnt DATA 8H ;Bit counter for I2C routines. ByteCnt DATA 9H ;Byte counter for I2C routines. SlvAdr DATA 0DH ;Slave address for I2C routines. SndDat DATA 21H ;I2C transmit buffer, 4 bytes max. RcvDat DATA 25H ;I2C receive buffer, X bytes max. Flags DATA 20H ;Location for bit flags MPR_REG DATA 0CH ;Location for QMC bit flags MPR_STATUS DATA 2BH ;QMC Status Register (06H in QMC) MPR_RNG DATA 2CH ;QMC Range (2G or 8G) NoAck BIT Flags.0 ;I2C no acknowledge flag. BusFault BIT Flags.1 ;I2C bus fault flag. I2CBusy BIT Flags.2 ;I2C busy flag. org 0 ljmp reset org 30H ;############################## ; I2C ROUTINES # ;############################## BitDly: NOP ;NOPs to delay NOP RET ; SCLHigh - sends SCL pin high and waits for any clock stretching peripherals. SCLHigh: SETB SCLPin ;Set SCL from our end. JNB SCLPin,$ ;Wait for pin to actually go high. RET ; SendStop - sends an I2C stop, releasing the bus. SendStop: CLR SDAPin ;Get SDA ready for stop. ACALL SCLHigh ;Set clock for stop. ACALL BitDly SETB SDAPin ;Send I2C stop. ACALL BitDly CLR I2CBusy ;Clear I2C busy status. RET ;Bus should now be released. ; SendByte - sends one byte of data to an I2C slave device. ; Enter with: ; ACC = data byte to be sent. SendByte: MOV BitCnt,#8 ;Set bit count. SBLoop: CLR C RLC A ;Send one data bit. MOV SDAPin,C ;Put data bit on pin. ACALL SCLHigh ;Send clock. ACALL BitDly CLR SCLPin ACALL BitDly DJNZ BitCnt,SBloop ;Repeat until all bits sent. SETB SDAPin ;Release data line for acknowledge. ACALL SCLHigh ;Send clock for acknowledge. ACALL BitDly JNB SDAPin,SBEX ;Check for valid acknowledge bit. SETB NoAck ;Set status for no acknowledge. MOV P1,#00000001B ;.gfedcba MOV P0, #00000111B SBEX: MOV P1,#00000010B ;.gfedcba MOV P0, #01111111B CLR SCLPin ;Finish acknowledge bit. ACALL BitDly RET ; GoMaster - sends an I2C start and slave address. ; Enter with: ; SlvAdr = slave address. GoMaster: SETB I2CBusy ;Indicate that I2C frame is in progress. CLR NoAck ;Clear error status flags. CLR BusFault JNB SCLPin,Fault ;Check for bus clear. JNB SDAPin,Fault CLR SDAPin ;Begin I2C start. ACALL BitDly CLR SCLPin ACALL BitDly ;Complete I2C start. MOV A,SlvAdr ;Get slave address. ACALL SendByte ;Send slave address. RET Fault: SETB BusFault ;Set fault status RET ; and exit. ; SendData - sends one or more bytes of data to an I2C slave device. ; Enter with: ; ByteCnt = count of bytes to be sent. ; SlvAdr = slave address. ; @R1 = data to be sent (the first data byte will be the ; subaddress, if the I2C device expects one). SendData: ACALL GoMaster ;Acquire bus and send slave address. JB NoAck,SDEX ;Check for slave not responding. SDLoop: MOV A,@R1 ;Get data byte from buffer. ACALL SendByte ;Send next data byte. INC R1 ;Advance buffer pointer. JB NoAck,SDEX ;Check for slave not responding. DJNZ ByteCnt,SDLoop ;All bytes sent? SDEX: ACALL SendStop ;Done, send an I2C stop. RET ;RcvByte - receives one byte of data from an I2C slave device. ; Returns: ; ACC = data byte received. RcvByte: MOV BitCnt,#8 ;Set bit count. CLR A RBLoop: ACALL SCLHigh ;Read one data bit. ACALL BitDly MOV C,SDAPin ;Get data bit from pin. RLC A ;Rotate bit into result byte. CLR SCLPin ACALL BitDly DJNZ BitCnt,RBLoop ;Repeat until all bits received. PUSH ACC ;Save accumulator MOV A,ByteCnt CJNE A,#1,RBAck ;Check for last byte of frame. SETB SDAPin ;Send no acknowledge on last byte. SJMP RBAClk RBAck: CLR SDAPin ;Send acknowledge bit. RBAClk: ACALL SCLHigh ;Send acknowledge clock. POP ACC ;Restore accumulator ACALL BitDly CLR SCLPin SETB SDAPin ;Clear acknowledge bit. ACALL BitDly RET ;RcvData - receives sends one or more bytes of data from an I2C slave device. ; Enter with: ; ByteCnt = count of bytes to be sent. ; SlvAdr = slave address. ; Returns: ; @R1 = data received. ; Note: to receive with a subaddress, use SendData to set the subaddress ; first (no provision for repeated start). RcvData: ACALL GoMaster MOV A, QMC_REG ; Start reading from Register 00 of QMC ACALL SendByte ACALL SCLHigh INC SlvAdr ;Set for READ of slave. ACALL GoMaster ;Acquire bus and send slave address. JB NoAck,RDEX ;Check for slave not responding. RDLoop: ACALL RcvByte ;Recieve next data byte. MOV @R1,A ;Save data byte in buffer. INC R1 ;Advance buffer pointer. DJNZ ByteCnt,RDLoop ;Repeat untill all bytes received. RDEX: ACALL SendStop ;Done, send an I2C stop. RET reset: MOV SP,#2fH MOV Flags, #0 ; Reset I2C Flags MOV SndDat+0,#2BH ; MHDR register MOV SndDat+1,#01H ; value to be written into 2Bh Main: MOV SlvAdr, #slaveaddr MOV R1, #SndDat ;Start of data. MOV ByteCnt, #2 ;Send register and value to be written ACALL SendData SJMP $ END