PIC16F877 y sensor TC74 I2C

Hola a todos, después de pasar varias tardes esta semana, y unas últimas horas hoy intentando descubrir el problema sin éxito, recurro a vosotros, a ver si alguno puede indicarme que estoy haciendo mal...

El circuito como veis (adjuntado) es muy sencillito... PIC, Xtal, y el sensor, con sus correspondientes resistencias de desacoplo...

El código, en HI-TECH (MPLAB):

Código:
#include <pic.h> //Standard Hi-Tec C header file this includes the definition for the generic functions and variables i.e TRISC, PORTC, TXREG 
#include "i2c.h" //Defines the I2C functions, this came with the HI-Tec C 
 
/*Setting the config register.  
Watchdog Timer Disable 
Using Hi Speed Xtal 
Low voltage program mode disable 
*/ 
__CONFIG (WDTDIS & HS & LVPDIS);  

void putrsUSART(const char *data); //Function prototype, this defines the functions other than the main() function 

void main() 
{ 
 		INTCON= 0;     //Disable Interrupts 
 		SPBRG = 129;  //Set the baudrate for 9600 @ 20 MHz (0x81)
 		TXSTA = 0x24; //Set the serial port parameters 
 		RCSTA = 0x90; //Set the serial port parameters 
 		PORTC = 0;    //Clear PORTC pins 
 		TRISC = 0x80; //Set the PORTC pin directions i.e Tx and Rx 
 
 int a, b, c, d; //Variables holds I2C Data  
 char td[4];     //Char Array to store I2C Data, this will be sent to the Serial port 

/* 
Continuosly monitor the I2C bus and read the humidity and temperature data  
And send the data to the Serial Port 
*/ 
	 while(1)         
 	{ 
  			i2c_Start();               //Initiate the I2C bus 
 			i2c_SendByte(0xA5);     //Send the Address of the Digipcco sensor to the I2C bus 
  			i2c_ReadAcknowledge();     //Read the ACK from the sensor 
  			__delay_us(2);         //wait for some time 
 	
  			a=i2c_ReadByte();          //Now the sensor sends the first Byte so we gonna read it and save it on the variable a 
   			i2c_SendAcknowledge(1);    //Send an ACK to the sensor so it can send the second Byte, we sends the value (1) so the sensor knows we waiting for more data           
  			__delay_us(2); 

			b=i2c_ReadByte();          //Second byte (MSB of the Humidity) 
  			i2c_SendAcknowledge(1); 
  			__delay_us(2); 

  			c=i2c_ReadByte();          //Third byte (LSB of the Temperature) 
  			i2c_SendAcknowledge(1); 
  			__delay_us(2); 

  			d=i2c_ReadByte();          //Fourth byte (MSB of the Temperature) 
  			i2c_SendAcknowledge(0);    //Sending (0) telling the sensor that we done
  			__delay_us(2); 

  			i2c_Stop();                //Stop the sensor sending data  
  			__delay_us(2); 
  
  			td[0]=a;                   //Filling the I2C Data into a Char Array 
  			td[1]=b; 
  			td[2]=c; 
  			td[3]=d; 
  
			putrsUSART(td);            //Send the 4 Bytes Char Array to the serial port 
  		
			for(int t=0;t<4;t++)       //Cleaning the data array, so that we can avoid repeating the same data 
 			{		 
   					__delay_us(20000); 
   					td[t]=0; 
  			} 
 	} 
} 
 
void putrsUSART(const char *data)  //Function we use to send the data to the Serial port, const char *data is the Char array 
{ 
 	do  //Check the Char Array until it finishes data                             
 	{ 
  		while(!(TXSTA & 0x02)); //Check the TXREG is empty 
   		TXREG = *data;          //Send the Byte to the TXREG 
 	}   
 	while( *data++ );//Check the Char Array until it finishes data 
}

Las funciones, son estándar, copiadas y pegadas a las dadas por Philips. No las pongo, pero si queréis las incluyo... El caso es que al simular, me recorre correctamente todo el código, pero siempre me guarda en las variables el valor FF. Es decir, al final siempre me queda a=FF, b=FF, c=FF y d=FF, cuando debería guardar el valor de la temperatura dada por el sensor.

Indicar que el código está realizado para un sensor digipicco de temperatura y humedad, de ahí que tome 8 bytes, cuando en la simulación, solo entregará 4, ya que es un sensor TC74 de temperatura. Pero ahí no creo que esté el problema, ya que depurando, el valor de la variable 'a' ya me la carga incorrectamente.

No sé que puede pasar, si es un problema del esquemático en Proteus o qué.... ¿alguna idea?
Gracias!
 

Adjuntos

  • Esquematico.PNG
    Esquematico.PNG
    46.8 KB · Visitas: 20
Según me han comentado tengo que configurar los registros SPCON, SPCON2, etc... del PIC, ¿pero no se supone que ya lo hace el archivo de cabecera? (#ifdef I2C_MODULE). Si lo tengo que modificar yo, ¿qué parametros hay que ajustar?

Código:
#ifndef	_I2C_H_
#define _I2C_H_

/*
 *	SDA (data) and SCL (clock) bits
 *	
 *	Special note!!!
 *	
 *	If the clock and data lines are in the same port, you will need
 *	to beware of the Read/Modify/Write issue in the PIC - since
 *	a bit set or clear on any one bit in a port will read and write
 *	back all other bits. 
 */

#ifndef _XTAL_FREQ
 // Unless specified elsewhere, 4MHz system frequency is assumed
 #define _XTAL_FREQ 20000000
#endif

/* Uncomment the next line to use the PIC's SSP Module*/
//#define I2C_MODULE 1

#ifdef I2C_MODULE
/* I2C module uses PORT C */
#define SCL             RC3             /* clock on port C bit 2 */
#define SCL_DIR         TRISC3
#define SDA     RC4                     /* data on port C bit 1 */
#define SDA_DIR         TRISC4
#define I2CTRIS TRISC
#define MASTER_MODE     0B1011          /* I2C firmware controlled Master Mode (slave idle) */
#define SSPMode(val)   SSPCON &=0xF0; SSPCON|=(val & 0xf)

#else
/* Change port as required - defaults to port b */
#define	SCL		RB2		/* clock on port B bit 2 */
#define	SCL_DIR		TRISB2

#define SDA             RB1             /* data on port B bit 1 */
#define	SDA_DIR		TRISB1
#define I2CTRIS TRISB

#endif

#define M_SDA_INP	0x02
#define M_SDA_OUT   0xFD
#define M_SCL_INP   0x04
#define M_SCL_OUT	0xFB

#define I2C_INPUT	1		/* data direction input */
#define I2C_OUTPUT	0		/* data direction output */

#define I2C_READ	0x01		/* read bit used with address */
#define I2C_WRITE	0x00		/* write bit used with address */

#define FALSE		0
#define TRUE		!FALSE

#define I2C_ERROR	(-1)
#define I2C_LAST	FALSE		/* SendAck: no more bytes to send */
#define I2C_MORE	TRUE		/* SendAck: more bytes to send */

#define i2c_Start()		i2c_Restart()
#define i2c_WriteTo(address)	i2c_Open((address), I2C_WRITE)
#define i2c_ReadFrom(address)	i2c_Open((address), I2C_READ)

#ifdef I2C_MODULE
#define SCL_HIGH() SCL_DIR = I2C_INPUT
#define SCL_LOW()  SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA_DIR = I2C_INPUT
#define SDA_LOW()  SDA_DIR = I2C_OUTPUT
#else
#define SCL_HIGH() SCL = 1; SCL_DIR = I2C_OUTPUT
#define SCL_LOW()  SCL = 0; SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA = 1; SDA_DIR = I2C_OUTPUT
#define SDA_LOW()  SDA = 0; SDA_DIR = I2C_OUTPUT
#endif

/*
 * Timings for the i2c bus. Times are rounded up to the nearest
 * micro second.
 */

#define I2C_TM_BUS_FREE		5
#define	I2C_TM_START_SU		5
#define I2C_TM_START_HD		4
#define I2C_TM_SCL_LOW		5
#define	I2C_TM_SCL_HIGH		4
#define I2C_TM_DATA_SU		1
#define I2C_TM_DATA_HD          0
#define I2C_TM_SCL_TO_DATA	4	/* SCL low to data valid */
#define	I2C_TM_STOP_SU		4
#define I2C_TM_SCL_TMO		10	/* clock time out */

extern signed char	i2c_ReadAcknowledge(void);
extern unsigned char	i2c_SendAddress(unsigned char, unsigned char);
extern unsigned char	i2c_SendByte(unsigned char);
extern int		i2c_ReadByte(void);
extern void		i2c_Restart(void);
extern void		i2c_Stop(void);
extern void		i2c_SendAcknowledge(unsigned char);
extern signed char	i2c_PutByte(unsigned char);
extern int		i2c_GetByte(unsigned char);
extern unsigned char	i2c_Open(unsigned char, unsigned char);
extern unsigned char	i2c_GetString(unsigned char *, unsigned char);
extern int		i2c_PutString(const unsigned char *, unsigned char);
extern unsigned char	i2c_WaitForSCL(void);
extern void 		i2c_Free(void);
extern unsigned char	i2c_read(unsigned char);
#endif			/* _I2C_H_ */

Indicar que el PIC es master ;)
 
Atrás
Arriba