PIC18 I2C con sensor de color

0

Hace tiempo que intento que mi PIC18 juegue bien con el sensor de color TCS34725 que tengo. Antes de explicar el problema que tengo, permítame incluir primero los recursos que he estado usando. Este fue el código de ejemplo al que hacía referencia, y here es la hoja de datos del sensor de color.

Por lo tanto, incluiré debajo del código I2C que estoy usando, así como las inicializaciones / cómo estoy configurando el sensor. Sin embargo, tengo algunos problemas con la lectura de los datos de este sensor. Cuando busco obtener datos de mis sensores de color, me doy cuenta de que mis pines SDA / SCL están muy bajos y, como resultado, mi PIC se cuelga. No estoy seguro de lo que está causando esto, ni he podido identificar dónde está el problema exacto. Realmente apreciaría un par de ojos extra en esto. Sin embargo, soy bastante nuevo en PIC, así que no te preocupes :)

Solo para confirmar, todo lo que debo hacer para conectar el sensor de color a mi PIC es conectar los pines SDA / SCL en el sensor a RC4 / RC3 respectivamente. No he visto ninguna literatura anterior que me indique que necesito alguna configuración especial, especialmente cuando uso múltiples dispositivos I2C (DS1307).

EDITAR (2017/02/19 12h50) : Llamo a mi subrutina COLOUR_GET_DATA desde mi main de una manera bastante mundana, pero observo que en realidad no ingresa a la subrutina . Es decir, trato de llamar un comando de escritura simple a la pantalla LCD pero nunca se muestra. Este es el problema en el que estoy trabajando actualmente, y creo que está relacionado con mis pines sda / scl que van bajando.

EDITAR (2017/02/19 15h50) : He cambiado los bits de comando (página 14 en la hoja de datos del sensor) para permitir la "transferencia de protocolo de incremento automático". No estoy seguro de qué significa exactamente esto, pero estoy haciendo dos lecturas consecutivas, una para las direcciones de alta / baja de cada registro de color. ¿Podría ser un problema, dado que actualmente lo he implementado? Menciono esto, porque si elimino el segundo intento de lectura que hago, evito que el reloj se agote. Eso sí, los datos que estoy leyendo ciertamente no son correctos. Supongo que la pregunta es: ¿cómo puedo administrar 2 lecturas consecutivas, la forma en que se describen en la hoja de datos (página 12)?

Aquí está el código I2C que he estado ejecutando con:

#include <p18f4620.inc>
#include <lcd.inc>

errorlevel -302
errorlevel -305
errorlevel -205
errorlevel -203
errorlevel -207

;global labels

variable _waitknt=0

udata
regaddress res 1
databyte res 1
datachar res 1
data_colourL res 1
data_colourH res 1
tens_digit res 1
ones_digit res 1
convert_buffer res 1
d50ms_C res 1
d200us_C res 1

global write_rtc,read_rtc,rtc_convert,i2c_common_setup, READ_COLOUR_I2C, WRITE_COLOUR_I2C
global regaddress, databyte, datachar, tens_digit, ones_digit, convert_buffer, d50ms_C, d200us_C
global data_colourL, data_colourH


;; I2C MACROS
;;
;; Sebastian K, commit 110219-2208
;; forked off PIC16 sample code
;; for PIC18F4620
;; relocatable labels

i2c_common_check_ack macro err_address ;If bad ACK bit received, goto err_address
    btfsc   SSPCON2,ACKSTAT
    goto    err_address
endm

i2c_common_start macro
    bsf     SSPCON2,SEN
    btfss   SSPCON1, WCOL   ; NOTE: I CHANGED THIS TO MAKE WORK, IDK Y THO
    bsf     PIR1, SSPIF
    btfss   PIR1, SSPIF
    bra     $-2
    bcf     PIR1, SSPIF ;clear SSPIF interrupt bit
endm

i2c_common_stop macro
    bsf     SSPCON2,PEN
    btfsc   SSPCON2,PEN
    bra     $-2
    bcf     PIR1, SSPIF
endm

i2c_common_repeatedstart macro
    bsf     SSPCON2,RSEN
    btfss   PIR1, SSPIF
    bra     $-2

    bcf     PIR1, SSPIF ;clear SSPIF interrupt bit
endm

i2c_common_ack macro
    bcf     SSPCON2,ACKDT
    bsf     SSPCON2,ACKEN
    btfsc   SSPCON2,ACKEN
    bra     $-2
endm

i2c_common_nack macro
    bsf     SSPCON2,ACKDT
    bsf     SSPCON2,ACKEN

    _waitl#v(_waitknt)
    btfsc   SSPCON2,ACKEN
    goto    _waitl#v(_waitknt)
    _waitknt    set _waitknt+1
endm

i2c_common_write macro
    btfsc   SSPSTAT, BF
    bra     $-2

    movwf   SSPBUF

    btfss   PIR1, SSPIF
    bra     $-2
    bcf     PIR1, SSPIF ;clear SSPIF interrupt bit
endm

i2c_common_read macro
    bsf     SSPCON2,RCEN ;Begin receiving byte from
    btfss   PIR1, SSPIF
    bra     $-2
    bcf     PIR1, SSPIF
    movf    SSPBUF,w
endm

code

i2c_common_setup
    movlw   b'00000000'
    movwf   SSPSTAT ;set I2C line leves, clear all flags.

    movlw   24 ;100kHz baud rate: 10000000 osc / [4*100000] -1
    movwf   SSPADD ;RTC only supports 100kHz

    movlw   b'00101000' ;Config SSP for Master Mode I2C
    movwf   SSPCON1

    clrf    SSPCON2

    bsf     SSPCON1,SSPEN ;Enable SSP module

    bcf     PIR2, SSPIE ;don't cause an interrupt on SSPIF, please. We're just polling it.
    bcf     PIR1, SSPIF
    bcf     SSPSTAT, BF
    i2c_common_stop ;Ensure the bus is free
return

write_rtc
    i2c_common_start

    movlw   0xD0 ;DS1307 address | WRITE bit
    i2c_common_write
    i2c_common_check_ack WR_ERR1_RTC

    ;Write data to I2C bus (Register Address in RTC)
    movf    regaddress,w ;Set register pointer in RTC
    i2c_common_write ;
    i2c_common_check_ack WR_ERR2_RTC

    ;Write data to I2C bus (Data to be placed in RTC register)
    movf    databyte,w ;Write data to register in RTC
    i2c_common_write
    i2c_common_check_ack WR_ERR3_RTC

    goto    WR_END_RTC

    WR_ERR1_RTC
    nop
    movlw   b'00001101'
    movwf   LATA    
    goto    WR_END

    WR_ERR2_RTC
    nop
    movlw   b'00001111'
    movwf   LATA
    bsf LATE,0
    goto    WR_END

    WR_ERR3_RTC
    nop
    movlw   b'00001001'
    movwf   LATA
    goto    WR_END
    WR_END_RTC
    i2c_common_stop ;Release the I2C bus
return

read_rtc
    i2c_common_start

    movlw   0xD0 ;DS1307 address | WRITE bit
    i2c_common_write ;
    i2c_common_check_ack RD_ERR1_RTC

    ;Write data to I2C bus (Register Address in RTC)
    movf    regaddress,w ;Set register pointer in RTC
    i2c_common_write
    i2c_common_check_ack RD_ERR2_RTC

    ;Re-Select the DS1307 on the bus, in READ mode
    i2c_common_repeatedstart
    movlw   0xD1 ;DS1307 address | READ bit
    i2c_common_write
    i2c_common_check_ack RD_ERR3_RTC

    ;Read data from I2C bus (Contents of Register in RTC)
    i2c_common_read
    movwf datachar
    i2c_common_nack ;Send acknowledgement of data reception

    goto RD_END_RTC

    RD_ERR1_RTC
    nop
    movlw   b'00000011'
    movwf   LATA
    goto    RD_END
    RD_ERR2_RTC
    nop
    movlw   b'00000101'
    movwf   LATA
    goto    RD_END
    RD_ERR3_RTC
    nop
    movlw   b'00000111'
    movwf   LATA
    goto    RD_END
    RD_END_RTC
    i2c_common_stop
return

rtc_convert
    movwf   convert_buffer ; B1 = HHHH LLLL
    swapf   convert_buffer,w ; W = LLLL HHHH
    andlw   0x0f ; Mask upper four bits 0000 HHHH
    addlw   0x30 ; convert to ASCII
    movwf   tens_digit ;saves into 10ths digit

    movf    convert_buffer,w
    andlw   0x0f ; w = 0000 LLLL
    addlw   0x30 ; convert to ASCII
    movwf   ones_digit ; saves into 1s digit
return

READ_COLOUR_I2C
    i2c_common_start

    movlw   0x52        ;TCS34725 address 0x29 << 1, WRITE bit (+0)
    i2c_common_write
    i2c_common_check_ack RD_ERR1

    ;Write command to I2C bus (Register Address in TCS34725)
    movlw   regaddress
    iorlw   0x80        ;command bit
    i2c_common_write
    i2c_common_check_ack RD_ERR2

    ;Re-Select the TCS34725 on the bus, in READ mode
    i2c_common_repeatedstart
    movlw   0x53        ;TCS34725 address 0x29 << 1, READ bit (+1)
    i2c_common_write
    i2c_common_check_ack RD_ERR3

    ;Read data from I2C bus (Contents of Register in TCS34725)
    i2c_common_read
    movwf data_colourL
    i2c_common_nack     ;Send acknowledgement of data reception

    i2c_common_read
    movwf data_colourH
    i2c_common_nack     ;Send acknowledgement of data reception

    goto RD_END

    RD_ERR1
    nop
    movlw   b'00000011'
    movwf   LATA
    goto    RD_END
    RD_ERR2
    nop
    movlw   b'00000101'
    movwf   LATA
    goto    RD_END
    RD_ERR3
    nop
    movlw   b'00000111'
    movwf   LATA
    goto    RD_END
    RD_END
    i2c_common_stop
return

WRITE_COLOUR_I2C
    i2c_common_start

    movlw   0x52 ;TCS34725 address | WRITE bit
    i2c_common_write
    i2c_common_check_ack WR_ERR1

    ;Write data to I2C bus (Register Address in TCS34725)
    movlw   regaddress
    iorlw   0x80
    i2c_common_write
    i2c_common_check_ack WR_ERR2

    ;Write data to I2C bus (Data to be placed in TCS34725 register)
    movlw   databyte 
    i2c_common_write
    i2c_common_check_ack WR_ERR3

    goto    WR_END

    WR_ERR1
    nop
    movlw   b'00001101'
    movwf   LATA    
    goto    WR_END

    WR_ERR2
    nop
    movlw   b'00001111'
    movwf   LATA
    bsf LATE,0
    goto    WR_END

    WR_ERR3
    nop
    movlw   b'00001001'
    movwf   LATA
    goto    WR_END
    WR_END
    i2c_common_stop ;Release the I2C bus

return
end

Y aquí está mi configuración para el sensor de color

    extern  i2c_common_setup, regaddress, databyte, datachar, READ_COLOUR_I2C, WRITE_COLOUR_I2C, WR_DATA, data_colourL, data_colourH

;    #define TCS34725_ADDRESS          (0x29)
;
;    #define TCS34725_COMMAND_BIT      (0x80)
;
;    #define TCS34725_ENABLE           (0x00)
;    #define TCS34725_ENABLE_AIEN      (0x10)    /* RGBC Interrupt Enable */
;    #define TCS34725_ENABLE_WEN       (0x08)    /* Wait enable - Writing 1 activates the wait timer */
;    #define TCS34725_ENABLE_AEN       (0x02)    /* RGBC Enable - Writing 1 actives the ADC, 0 disables it */
;    #define TCS34725_ENABLE_PON       (0x01)    /* Power on - Writing 1 activates the internal oscillator, 0 disables it */
;    #define TCS34725_ATIME            (0x01)    /* Integration time */
;    #define TCS34725_WTIME            (0x03)    /* Wait time (if TCS34725_ENABLE_WEN is asserted) */
;    #define TCS34725_WTIME_2_4MS      (0xFF)    /* WLONG0 = 2.4ms   WLONG1 = 0.029s */
;    #define TCS34725_WTIME_204MS      (0xAB)    /* WLONG0 = 204ms   WLONG1 = 2.45s  */
;    #define TCS34725_WTIME_614MS      (0x00)    /* WLONG0 = 614ms   WLONG1 = 7.4s   */
;    #define TCS34725_AILTL            (0x04)    /* Clear channel lower interrupt threshold */
;    #define TCS34725_AILTH            (0x05)
;    #define TCS34725_AIHTL            (0x06)    /* Clear channel upper interrupt threshold */
;    #define TCS34725_AIHTH            (0x07)
;    #define TCS34725_PERS             (0x0C)    /* Persistence register - basic SW filtering mechanism for interrupts */
;    #define TCS34725_PERS_NONE        (0b0000)  /* Every RGBC cycle generates an interrupt                                */
;    #define TCS34725_PERS_1_CYCLE     (0b0001)  /* 1 clean channel value outside threshold range generates an interrupt   */
;    #define TCS34725_PERS_2_CYCLE     (0b0010)  /* 2 clean channel values outside threshold range generates an interrupt  */
;    #define TCS34725_PERS_3_CYCLE     (0b0011)  /* 3 clean channel values outside threshold range generates an interrupt  */
;    #define TCS34725_PERS_5_CYCLE     (0b0100)  /* 5 clean channel values outside threshold range generates an interrupt  */
;    #define TCS34725_PERS_10_CYCLE    (0b0101)  /* 10 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_15_CYCLE    (0b0110)  /* 15 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_20_CYCLE    (0b0111)  /* 20 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_25_CYCLE    (0b1000)  /* 25 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_30_CYCLE    (0b1001)  /* 30 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_35_CYCLE    (0b1010)  /* 35 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_40_CYCLE    (0b1011)  /* 40 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_45_CYCLE    (0b1100)  /* 45 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_50_CYCLE    (0b1101)  /* 50 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_55_CYCLE    (0b1110)  /* 55 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_60_CYCLE    (0b1111)  /* 60 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_CONFIG           (0x0D)
;    #define TCS34725_CONFIG_WLONG     (0x02)    /* Choose between short and long (12x) wait times via TCS34725_WTIME */
;    #define TCS34725_CONTROL          (0x0F)    /* Set the gain level for the sensor */
;    #define TCS34725_ID               (0x12)    /* 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727 */
;    #define TCS34725_STATUS           (0x13)
;    #define TCS34725_STATUS_AINT      (0x10)    /* RGBC Clean channel interrupt */
;    #define TCS34725_STATUS_AVALID    (0x01)    /* Indicates that the RGBC channels have completed an integration cycle */
;    #define TCS34725_CDATAL           (0x14)    /* Clear channel data */
;    #define TCS34725_CDATAH           (0x15)
;    #define TCS34725_RDATAL           (0x16)    /* Red channel data */
;    #define TCS34725_RDATAH           (0x17)
;    #define TCS34725_GDATAL           (0x18)    /* Green channel data */
;    #define TCS34725_GDATAH           (0x19)
;    #define TCS34725_BDATAL           (0x1A)    /* Blue channel data */
;    #define TCS34725_BDATAH           (0x1B)


    COLOUR_INIT macro
    COLOUR_WRITE    0x00, 0x01 ; Enable Register (0x00), Power ON (0x01)
    COLOUR_WRITE    0x00, 0x02 ; Enable Register (0x00), RGBC enable (0x02)
    COLOUR_WRITE    0x01, 0xf6 ; Timing Register (0x01), 24ms rgbc cycle
    COLOUR_WRITE    0x0f, 0x03 ; Control Register (0x0f), 60x gain (0x03)
    endm

    COLOUR_READ  macro  address
    movlw   address
    movwf   regaddress
    call    READ_COLOUR_I2C
    endm

    COLOUR_WRITE macro address, datliteral
    movlw   address
    movwf   regaddress
    movlw   datliteral
    movwf   databyte
    call    WRITE_COLOUR_I2C
    endm

    COLOUR_GET_DATA macro clear, red, green, blue, temp_col
    call    WR_DATA

    COLOUR_READ 0x14    ; read clear colour address low, command bits set later
    DATA_TO_COLOUR  data_colourH, data_colourL, temp_col, clear

    COLOUR_READ 0x16    ; read red colour address low, command bits set later
    DATA_TO_COLOUR  data_colourH, data_colourL, temp_col, red

    COLOUR_READ 0x18    ; read green colour address low, command bits set later
    DATA_TO_COLOUR  data_colourH, data_colourL, temp_col, green

    COLOUR_READ 0x1A    ; read clear colour address low, command bits set later
    DATA_TO_COLOUR  data_colourH, data_colourL, temp_col, blue
    endm

    DATA_TO_COLOUR macro addrH, addrL, count, final
    movlw   0x08
    movwf   count
    movlw   addrH
    ROTATEL count
    iorwf   addrL
    movwf   final
    endm

    ROTATEL  macro count
    rlncf   WREG
    decfsz  count
    bra ROTATEL
    endm

Cualquier y toda ayuda es bienvenida. Muchas gracias!

Mateo

    
pregunta mreiter

0 respuestas

Lea otras preguntas en las etiquetas