Estoy usando el microcontrolador Pic24fj128ga202 y eeprom 24c256 e ISL1208 RTC que se conecta a través del bus I2c. El problema es que puedo leer y escribir los datos en eeprom y RTC, pero en otras placas (con el mismo diseño) no puedo leer ni escribir los datos a través del bus i2c. He publicado mi código y mi esquema también amablemente, alguien se dirige a mí, ¿cuál es el problema? No tengo osciloscopio para comprobar esto.
#include <stdio.h>
#include "C:\Program Files\Microchip\xc16\v1.24\support\PIC24F\h\p24FJ128GA202.h"
#include "uart.h"
// calculate baud rate of I2C
#define Fosc 32000000
#define Fcy (Fosc/2)
#define Fsck 400000
#define I2C_BRG ((Fcy/2/Fsck)-1)
int main()
{
InitProcessor();
Delayms();
while(1)
{
I2c_Write(0xA0,1,'A');
Delayms(5000);
uart1tx(I2C_read(0xA0,1));
}
}
void InitProcessor(void)
{
// Oscillator 8mhz no pll
OSCCON = 0x0011;
CLKDIV = 0x0000;
// Configure Digital pins
ANSA = 0x0003;
ANSB = 0x0000;
// Assign IO values for Ports
PORTA = 0x0000;
TRISA = 0x001B;
TRISB = 0x468f; // 7 as receive and 8 as transmitter
//PORTB = 0x0000;
// Interrupt Bits
INTCON1 = 0x0000; // Disable Interrupts
INTCON2 = 0x0000;
// Init I2C
I2C2CONL = 0x8000;
I2C2CONH = 0x0000;
I2C2STAT = 0x0000;
I2C2BRG = I2C_BRG;
//I2C2BRG = 79;
Delayms(1000);
Init_rtc();
}
void Init_rtc()
{
I2c_Write(0xde, 0x07, 0x10);
I2c_Write(0xde, 0x06, 0x00);
Delayms(20);
}
void I2c_Write(unsigned char DeviceAddress,unsigned int Addr,unsigned char i2c_value)
{
unsigned char i2c_exit=1,i2c_write=0;
int I2creg = 0;
IFS3 &= ~0x0004;
I2C2CONL |= 0x0001;
I2cTimer = 0;
while(i2c_exit)
{
if(I2cTimer > 30){ // Exit routine
i2c_exit = 0;
}
if(IFS3& 0x0004)
{
IFS3 &= ~0x0004;
I2cTimer = 0;
if(i2c_write == 0)
{
I2C2TRN = (DeviceAddress & 0xfe);
if(DeviceAddress == 0xde)
i2c_write = 1;
}
else if(i2c_write == 1)
I2C2TRN = Addr >> 8;
else if(i2c_write == 2)
I2C2TRN = Addr & 0xFF;
else if(i2c_write == 3)
I2C2TRN = i2c_value;
else if(i2c_write == 4)
I2C2CONL |= 0x04;
else
{
i2c_write = 100;
i2c_exit = 0;
}
i2c_write++;
}
}
Delayms(5);
}
/* Function to Read and return a data through I2C */
unsigned char I2C_read(unsigned char DeviceAddress,unsigned int Addr)
{ unsigned char db, ReadState=0,I2CFlag;
ReadState = 0;
IFS3 &= ~0x0004; // Master I2C interrupt flag
I2CFlag = 1;
I2C2CONL |= 0x0001; // SEN = 1;
I2cTimer = 0;
while(I2CFlag){
if(I2cTimer > 30){ // Exit routine
I2CFlag = 0;
//ModemDiagnostics(64,1);
}
//uart1tx('r');
if(IFS3 & 0x0004)
{
I2cTimer = 0;
IFS3 &= ~0x0004;
if(ReadState == 0)
{
I2C2TRN = (DeviceAddress & 0xfe);
if(DeviceAddress == 0xde)
ReadState = 1;
}
else if(ReadState == 1)
I2C2TRN = Addr >> 8;
else if(ReadState == 2)
I2C2TRN = Addr & 0xff;
else if(ReadState == 3)I2C2CONL |= 0x0002;
else if(ReadState == 4)I2C2TRN = (DeviceAddress | 0x01);
else if(ReadState == 5){
I2C2CONL |= 0x0008; // RCEN = 1, Enable data receive
db = I2C2RCV;
}
else if(ReadState == 6){
db = I2C2RCV; // Read Data
I2C2CONL |= 0x0020; // ACKDT = 1, Set Acknowledge bit (No Acknowledge)
Delayms(5);
I2C2CONL |= 0x0010; // ACKEN = 1
}
else if(ReadState == 7)I2C2CONL |= 0x04; // PEN = 1, Stop enable bit forI2C
else{ReadState = 100; I2CFlag = 0;}
ReadState++;
}
}
if(db)
return db;
else
return 0;
}
El cálculo del pull-up máximo a 400kHz es:
= ; reordenando, obtenemos:
= para su caso, dando 30pF.
Las capacitancias de los pines de la EEPROM y el RTC son probablemente del orden de 10pF; agregue la capacitancia del pin del PIC y ya se está acercando a 30pF, poniendo el diseño en un borde peludo (para usar el término común), donde puede o no funcionar correctamente, que es precisamente lo que está experimentando.
No es difícil obtener 10 pF o más de capacitancia parásita, y esto violaría el requisito del tamaño máximo de pull-up, lo que conduciría a datos I2C corruptos.
Si reemplaza estas piezas con 4.7k, se le permiten casi 64pF de capacitancia de bus, lo que muy probablemente resolverá el problema.
Como se señaló, si reduce la velocidad del autobús y funciona correctamente, ese es un indicador claro de que este es el problema.
Debido a que está funcionando como desea en otra placa, asumiré que los problemas provienen del hardware (incluso si un mal software puede empeorarlo). Puedo ver 2 razones para esto:
Pedro Smith