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