Electronic Circuits and Projects Forum



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

  1. #1
    Felipebrz Felipebrz is offline

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

    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 AN989. 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
    Attached Images

  2. #2
    ericgibbs ericgibbs is offline
    Super Moderator
    hi,
    Regarding the address for the 3246, what other 'lettering' is shown with/after the MCP3426 letters.??? ie anything like A0 etc.??
    0
    Eric " Good enough is Perfect "
    I will NOT answer PM's requesting technical help, please use the Forum
    "Nigels Asm tutorials:" www.winpicprog.co.uk/
    "Ian Rogers 'C' conversion of Nigels Asm tutorials:" http://www.electro-tech-online.com/c...torials-c.html

  3. Thread Starter #3
    Felipebrz Felipebrz is offline
    It reads, exactly:
    3426A0E
    1134
    S22
    0

  4. #4
    ericgibbs ericgibbs is offline
    Super Moderator
    Quote Originally Posted by Felipebrz View Post
    It reads, exactly:
    3426A0E
    1134
    S22
    hi,
    The A0 means is fixed at address 0,,, you can buy buy A1,A2 or A3 versions,, addr = 1,2,3

    Ok.
    0
    Eric " Good enough is Perfect "
    I will NOT answer PM's requesting technical help, please use the Forum
    "Nigels Asm tutorials:" www.winpicprog.co.uk/
    "Ian Rogers 'C' conversion of Nigels Asm tutorials:" http://www.electro-tech-online.com/c...torials-c.html

  5. Thread Starter #5
    Felipebrz Felipebrz is offline
    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!!
    0

Tags
Similar Threads
Thread Starter Forum Replies Last Post
PIC & software serial bit-banging Oznog Microcontrollers 5 21st April 2005, 10:33 PM
pic micro controller 16f877 ADC elangomlog Microcontrollers 3 14th May 2004, 10:28 PM
8-Bit ADC chip pike Datasheets, Manuals or Parts 2 15th March 2004, 04:38 AM
Interfacing a PIC 18F452 and an ADC AD7827 + SPI com french_student Microcontrollers 2 8th December 2003, 08:15 AM
Using a PIC to async a 16 bit ADC.. Blueteeth Microcontrollers 7 22nd October 2003, 02:30 AM
Electronic Circuits  |  Learning Electronics

Join our community with over 100,000 Members! It's free, easy and when you're logged in you have many more features! Click to register.
Page Time: 0.07714 seconds      Memory: 7,505 KB      Queries: 17      Templates: 0