Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC 18F2550 + 16 bit ADC (MCP3426) via I2C

Status
Not open for further replies.

Felipebrz

New Member
Hi,

I'm building a circuit which consists of a PIC 18F2550, a 16 bit ADC (Microchip's MCP3426) and an LCD to display the ADC's readings.
The LCD I managed to get it working and developed a couple of routines for it, thats not really the problem now.
My problem is in getting a reading from the ADC via I2C.
Since I have never used I2C before, I looked for help and managed to find **broken link removed**. Using these routines, I found a bit of a problem on the byte write routine.
First I have to send a byte to the MCP, that first byte is composed of:
bits 7-4: Device Code: 1101
bits 3-1: Address bits: thats the problem...
bit 0: Read/Write' bit
After that byte, the byte I send is considered to be the configuration register.

When I say the address bits are the problem it is because nowhere in the datasheet it gives me an exact address for this device. The MCP3427 and 3428 have a table, but for the 3426 it just says it is "programmed at the factory during production". So what am I supposed to do? I tried sending 000, but apparently that didn't work.

Anyone has any clue?

I'm posting the circuit. The I2C code from AN989 (changed a little for my purposes -- so far I have only tried to use routines Init, ByteWrite and ByteRead) is:

Code:
;*******************Initialization subroutine*********************
;           This routine initializes the MSSP module
;           for I2C Master mode, with a 100 kHz clock.
;*****************************************************************
Init
    movlw   b'11111111'
    movwf   TRISB               ; Set PORTB to all inputs
    clrf    SSPSTAT             ; Disable SMBus inputs
    bsf     SSPSTAT,SMP         ; Disable slew rate control
    movlw   0x18                ; Load 0x18 into WREG
    movwf   SSPADD              ; Setup 100 kHz I2C clock
    movlw   b'00101000'
    movwf   SSPCON1             ; Enable SSP, select I2C Master mode
    clrf    SSPCON2             ; Clear control bits
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bcf     PIR2,BCLIF          ; Clear Bit Collision flag
    return

;*******************Start bit subroutine**************************
;           This routine generates a Start condition
;           (high-to-low transition of SDA while SCL
;           is still high.
;*****************************************************************
BSTART
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     SSPCON2,SEN         ; Generate Start condition
bstart_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    bra     bstart_wait         ; If not, keep checking

    return

;*******************Restart bit subroutine**************************
;           This routine generates a Repeated Start
;           condition (high-to-low transition of SDA
;           while SCL is still high.
;*****************************************************************
BRESTART
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     SSPCON2,RSEN        ; Generate Restart condition
brestart_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    bra     brestart_wait       ; If not, keep checking

    return

;*******************Stop bit subroutine***************************
;           This routine generates a Stop condition
;           (low-to-high transition of SDA while SCL
;           is still high.
;*****************************************************************
BSTOP
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     SSPCON2,PEN         ; Generate Stop condition
bstop_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    bra     bstop_wait          ; If not, keep checking

    return

;*******************Data transmit subroutine**********************
;           This routine transmits the byte of data
;           stored in 'datao' to the serial EEPROM
;           device. Instructions are also in place
;           to check for an ACK bit, if desired.
;           Just replace the 'bra' instruction,
;           or create an 'ackfailed' label, to provide
;           the functionality.
;*****************************************************************
TX_BYTE
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    movf    datao,W             ; Copy datao to WREG
    movwf   SSPBUF              ; Write byte out to device
tx_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    bra     tx_wait             ; If not, keep checking
    btfsc   SSPCON2,ACKSTAT     ; Check if ACK bit was received
    call    ackfailed           ; This executes if no ACK received    

    return

;*******************Data receive subroutine***********************
;           This routine reads in one byte of data from
;           the serial EEPROM device, and stores it in
;           'datai'.  It then responds with either an
;           ACK or a NO ACK bit, depending on the value
;           of 'ACKDT' in 'SSPCON2'.
;*****************************************************************
RX_BYTE
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     SSPCON2,RCEN        ; Initiate reception of byte
rx_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    bra     rx_wait             ; If not, keep checking
    movf    SSPBUF,W            ; Copy byte to WREG
    movwf   datai               ; Copy WREG to datai
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     SSPCON2,ACKEN       ; Generate ACK/NO ACK bit    
rx_wait2
    btfss   PIR1,SSPIF          ; Check if operation completed
    bra     rx_wait2            ; If not, keep checking

    return

;*******************Byte write test subroutine********************
;           This routine tests the byte write feature
;           of the serial EEPROM device.  It will write
;           1 byte of data to the device at address 0x5A00.
;*****************************************************************
ByteWrite
    rcall   BSTART              ; Generate Start condition

                                ; Send control byte
    movlw   WRITE_ADDR          ; Load control byte for write
    movwf   datao               ; Copy to datao for output
    rcall   TX_BYTE             ; Send control byte to device

                                ; Send word address high byte
    movlw   B'10011000'         ; Configuração do MCP!!!
    movwf   datao               ; Copy to datao for output
    rcall   TX_BYTE

    rcall   BSTOP               ; Generate Stop condition

;    rcall   Poll                ; Poll for write completion

    return

;*******************Page write test subroutine********************
;           This routine demonstrates the page write
;           feature of the serial EEPROM device.  It will
;           write NUMBYTES number of bytes of data to the
;           device starting at address 0x5A00.  Since this
;           is a page write, all bytes will be written
;           to the device at the same time.
;           Note that if a page boundary is crossed during
;           the operation, the address will wrap back to
;           the beginning of the page, overwriting any
;           previously stored data.
;*****************************************************************
PageWrite
    movlw   NUMBYTES
    movwf   bytecount           ; Initialize counter to NUMBYTES

    rcall   BSTART              ; Generate start bit
                                ; Now we send the control byte
    movlw   WRITE_ADDR
    movwf   datao               ; Copy control byte to buffer
    rcall   TX_BYTE             ; Output control byte to device

                                ; Send word address high byte
    movlw   0x5A                ; Use 0x5A for address to send
    movwf   datao               ; Copy address to buffer
    rcall   TX_BYTE

                                ; Send word address low byte
    movlw   0x00                ; Use 0x00 for address to send
    movwf   datao               ; Copy address to buffer
    rcall   TX_BYTE             ; Output address to device

txbyte                          ; This loop transfers all of
                                ; the data bytes to the device
    movf    bytecount,W         ; Use bytecount as data value
    movwf   datao               ; Copy data to buffer
    rcall   TX_BYTE             ; Output data to device

    decfsz  bytecount,F         ; Check if finished looping
    bra     txbyte              ; Continue looping

    rcall   BSTOP               ; Generate stop bit
    rcall   Poll                ; Poll for write completion
    return

;*******************Byte read test subroutine*********************
;           This routine tests the byte read feature
;           of the serial EEPROM device.  It will read
;           1 byte of data at address 0x5A00 from the device.
;*****************************************************************
ByteRead
    rcall   BSTART              ; Generate Start condition

;                                ; Send control byte
;    movlw   WRITE_ADDR          ; Load control byte for write
;    movwf   datao               ; Copy to datao for output
;    rcall   TX_BYTE             ; Send control byte to device
;
;                                ; Send word address high byte
;    movlw   0x5A                ; Load 0x5A for word address
;    movwf   datao               ; Copy to datao for output
;    rcall   TX_BYTE             ; Send high byte to device
;
;                                ; Send word address low byte
;    movlw   0x00                ; Load 0x00 for word address
;    movwf   datao               ; Copy to datao for output
;    rcall   TX_BYTE             ; Send word address to device
;
;    rcall   BRESTART            ; Generate Restart condition

                                ; Send control byte
    movlw   READ_ADDR           ; Load control byte for read
    movwf   datao               ; Copy to datao for output
    rcall   TX_BYTE             ; Send control byte to device

                                ; Read data byte
    bsf     SSPCON2,ACKDT       ; Select to send NO ACK bit
    rcall   RX_BYTE             ; Read data byte from device

    rcall   BSTOP               ; Generate Stop condition

    return

;*******************Sequential read test subroutine***************
;           This routine tests the sequential read feature
;           of the serial EEPROM device.  It will read
;           NUMBYTES number of bytes of data to the device
;           starting at address 0x5A00, one byte after another.
;*****************************************************************
SequentialRead
    movlw   NUMBYTES
    movwf   bytecount           ; Initialize counter to NUMBYTES

    rcall   BSTART              ; Generate start bit
                                ; Now send the control byte
                                ; for a write, to set address
    movlw   WRITE_ADDR
    movwf   datao               ; Copy control byte to buffer
    rcall   TX_BYTE             ; Output control byte to device

                                ; Send word address high byte
    movlw   0x5A                ; Load 0x5A for word address
    movwf   datao               ; Copy to datao for output
    rcall   TX_BYTE             ; Send high byte to device

                                ; Send word address low byte
    movlw   0x00                ; Load 0x5A for word address
    movwf   datao               ; Copy to datao for output
    rcall   TX_BYTE             ; Send word address to device

    rcall   BRESTART            ; Generate another start bit
                                ;   to switch to read mode
    movlw   READ_ADDR
    movwf   datao               ; Copy control byte to buffer
    rcall   TX_BYTE             ; Output control byte to device

rxbyte
                                ; Finally, read the data byte
    decfsz  bytecount,F         ; Check if finished looping
    bra     continue            ; If not finished, keep going
    bsf     SSPCON2,ACKDT       ; Otherwise, select to send NO ACK bit
    rcall   RX_BYTE             ;   and input final byte from device

    rcall   BSTOP               ; Generate stop bit
    return

continue
    bcf     SSPCON2,ACKDT       ; Select to send ACK bit
    rcall   RX_BYTE             ; Input data from device
    bra     rxbyte              ; Continue looping

;*******************Acknowledge Polling subroutine****************
;           This subroutine polls the EEPROM device
;           for an ACK bit, which indicates that the
;           internal write cycle has completed. Code
;           is in place for a timeout routine, just
;           uncomment the 'bra TimedOut' line, and
;           provide a 'TimedOut' label.
;*****************************************************************
Poll
    movlw   .40
    movwf   pollcnt             ; Set max polling times to 40
polling
    rcall   BRESTART            ; Generate start bit
    movlw   WRITE_ADDR          ; Now send the control byte
    movwf   datao               ; Copy control byte to buffer
    rcall   TX_BYTE             ; Output control byte to device
    btfss   SSPCON2,ACKSTAT     ; Was the ACK bit low?
    bra     exitpoll            ; If yes, stop polling
                                ; If no, check if polled 40 times
    decfsz  pollcnt,F           ; Is poll counter down to zero?
    bra     polling             ; If no, poll again
;   bra     TimedOut            ; If yes, part didn't respond
                                ; in time, so take action
exitpoll
    rcall   BSTOP               ; Generate stop bit
    return
 
hi,
Regarding the address for the 3246, what other 'lettering' is shown with/after the MCP3426 letters.??? ie anything like A0 etc.??
 
Hi!

It's been a while since I put my hands in this project, but I've been at it again and have some doubts. Apparently, I'm now correctly addressing the MCP3426 and I can acquire some measurements from the ADC, but I'm not sure about the contents of the conversion.
For instance, whenever I have 0V on the inputs, the ADC returns me a number around 653 (dec) and whenever I have 1V at the inputs, the ADC returns me a number around 1030 (dec).
I'm in 16bit mode, PGA=1 and VDD=5V.
Whit this, at 16bit, shouldn't 0V be 0 (dec, or 0x0000) and 1V be 1/5 of 0xFFFF (0x333 or d'13.107')?

The following is the code for the I2C communication with the MCP (based on AN989):
Code:
 WRITE_ADDR     equ             b'11010000'     ; Address byte do MCP3426, operação de escrita
 READ_ADDR      equ             b'11010001' ; Address byte do MCP3426, operação de leitura
(...)
InicializaI2C
 CLRF   TRISB                           ; Configura PORTB como saída
 BSF            TRISB,0                         ; Configura SDA (RB0) como entrada
 BSF            TRISB,1                         ; Configura SCL (RB1) como entrada
 MOVLW  b'10000000'
 MOVWF  SSPSTAT
 MOVLW   .19                                    ; Valor para o clock de 100kHz e FOSC de 8MHz
 MOVWF   SSPADD              ; Setup 100 kHz I2C clock
     MOVLW   b'00101000'
     MOVWF   SSPCON1             ; Enable SSP, select I2C Master mode
     CLRF    SSPCON2             ; Clear control bits
     BCF     PIR1,SSPIF          ; Clear SSP interrupt flag
     BCF     PIR2,BCLIF          ; Clear Bit Collision flag
     RETURN
;******************* Start bit subroutine**************************
 BSTART    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
     bsf     SSPCON2,SEN         ; Generate Start condition
 bstart_wait    btfss   PIR1,SSPIF          ; Check if operation completed
     bra     bstart_wait         ; If not, keep checking
    return
;******************* Restart bit subroutine**************************
 BRESTART    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
     bsf     SSPCON2,RSEN        ; Generate Restart condition
 brestart_wait    btfss   PIR1,SSPIF          ; Check if operation completed
     bra     brestart_wait       ; If not, keep checking
    return
;******************* Stop bit subroutine***************************
 BSTOP  bsf     SSPCON2,PEN     ; send stop bit
 btfsc  SSPCON2,PEN     ; has stop bit been sent?
 goto   $-2             ; no, loop back to test
 return
;******************* Data transmit subroutine**********************
 TX_BYTE
     bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
     movf    datao,W             ; Copy datao to WREG
     movwf   SSPBUF              ; Write byte out to device
 tx_wait    btfss   PIR1,SSPIF          ; Check if operation completed
     bra     tx_wait             ; If not, keep checking
     btfsc   SSPCON2,ACKSTAT     ; Check if ACK bit was received
     call    ackfailed           ; This executes if no ACK received    
     return
 ;******************* Data receive subroutine***********************
 RX_BYTE
     bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
     bsf     SSPCON2,RCEN        ; Initiate reception of byte
 rx_wait
     btfss   PIR1,SSPIF          ; Check if operation completed
     bra     rx_wait             ; If not, keep checking
     movf    SSPBUF,W            ; Done! Copy byte to WREG
     movwf   datai               ; Copy WREG to datai
     bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
     bsf     SSPCON2,ACKEN       ; Generate ACK/NO ACK bit
    rx_wait2    btfss   PIR1,SSPIF          ; Check if operation completed
     bra     rx_wait2            ; If not, keep checking
    return
; Send a command to the MCP
 EnviaComandoMCP
     RCALL   BSTART              ; Gera condição de início
     MOVLW   WRITE_ADDR          ; Carrega byte de controle para escrita
     MOVWF   datao               ; Carrega o byte de controle em datao
     RCALL   TX_BYTE             ; Envia o byte de controle
     MOVFF      Comando,datao           ; Envia o byte de configuração para o registrador datao
     RCALL   TX_BYTE                            ; Envia o byte de configuração
     RCALL   BSTOP               ; Gera condição de parada
     RETURN    ; Acquire from the MCP
  
 RecebeMCP
     RCALL   BSTART              ; Gera condição de início
     MOVLW   READ_ADDR           ; Carrega byte de controle para leitura
     MOVWF   datao               ; Carrega o byte de controle em datao
     RCALL   TX_BYTE             ; Envia o byte de controle
 ACKStatTest
 BTFSC  SSPCON2,ACKSTAT         ; Se ACKSTAT=0 (ACK recebido), pula a linha
 GOTO   ACKStatTest                     ; Se ACKSTAT=1 (ACK não recebido), tenta novamente
     BCF     SSPCON2,ACKDT       ; Envia o bit ACK
     RCALL   RX_BYTE             ; Lê o byte de dados do MCP (carrega em datai)
     MOVFF      datai,MCP_MSB
     BSF     SSPCON2,ACKDT       ; Envia o bit NO ACK, para ler o próximo byte e parar
     RCALL   RX_BYTE             ; Lê o byte de dados do MCP (carrega em datai)
     MOVFF      datai,MCP_LSB
     RCALL   BSTOP               ; Gera condição de parada
     RETURN

And the configuration byte is 10011000

Can anyone give me some advice on these results? Thanks!!
 
Status
Not open for further replies.

Latest threads

Back
Top