Enlace para microcontrolador PIC 18F4620 ficha técnica si puede lo necesita
Uso "Mikroc for PIC pro 6.0" como compilador y escribo un programa para comunicarme entre dos 18f4620 uno es maestro y el otro es esclavo. Tanto el esclavo como el maestro están trabajando en el oscilador HS modo con 4MHZ oscilador de cristal
El código completo para master pic 18f4620
//MAster pic 18f4620
const unsigned short int crystalOscillator =4000000;
void I2C_Master_Init(const unsigned long c)
{
SSPCON1 = 0b00101000;
SSPCON2 = 0;
SSPADD = (crystalOscillator/(4*c))-1;
SSPSTAT = 0;
TRISC.B3 = 1; //Setting as input as given in datasheet
TRISC.B4 = 1; //Setting as input as given in datasheet
}
void I2C_Master_Wait()
{
while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
}
void I2C_Master_Start()
{
I2C_Master_Wait();
SSPCON2.SEN = 1;
}
void I2C_Master_RepeatedStart()
{
I2C_Master_Wait();
SSPCON2.RSEN = 1;
}
void I2C_Master_Stop()
{
I2C_Master_Wait();
SSPCON2.PEN = 1;
}
void I2C_Master_Write(unsigned short int d)
{
I2C_Master_Wait();
SSPBUF = d;
}
unsigned short int I2C_Master_Read(unsigned short int a)
{
unsigned short temp;
I2C_Master_Wait();
SSPCON2.RCEN = 1;
I2C_Master_Wait();
temp = SSPBUF;
I2C_Master_Wait();
if(a==1){SSPCON2.ACKDT=1;}
else{SSPCON2.ACKDT=0;}
SSPCON2.ACKEN = 1;
return temp;
}
void main()
{
I2C_Master_Init(100000); //Initialize I2C Master with 100KHz clock
Delay_ms(500);
while(1)
{
I2C_Master_Start(); //Start condition
I2C_Master_Write(0x30); //7 bit address + Write
// I2C_Master_Write(0x00); //Write data
//I2C_Master_Write(0x00);
I2C_Master_Stop(); //Stop condition
Delay_ms(2000);
}
}
El código completo para esclavo pic 18f4620
//Slave pic 18f4620
//##############################################################################
unsigned short int zed=0;
volatile unsigned short int new =0 ,dataRead=0 , dataWrite=0;
unsigned char dataReadCh[7] , dataWriteCh[7];
//##############################################################################
void interrupt()
{
if(PIR1.SSPIF == 1)
{
SSPCON1.CKP = 0;
new=1;
if ((SSPCON1.SSPOV) || (SSPCON1.WCOL))
{
zed = SSPBUF; // Read the previous value to clear the buffer
SSPCON1.SSPOV = 0; // Clear the overflow flag
SSPCON1.WCOL = 0; // Clear the collision bit
SSPCON1.CKP = 1;
}
if((!SSPSTAT.D_A||SSPSTAT.D_A) && !SSPSTAT.R_W)
{
while(!SSPSTAT.BF){};
while(SSPSTAT.BF){dataRead = SSPBUF;}
SSPCON1.CKP = 1;
}
else if((!SSPSTAT.D_A||SSPSTAT.D_A) && SSPSTAT.R_W)
{
while(SSPSTAT.BF){zed = SSPBUF;}
SSPBUF = dataWrite ;
SSPCON1.CKP = 1;
while(SSPSTAT.BF){};
}
PIR1.SSPIF = 0;
}
}
//##############################################################################
void I2C_Slave_Init(unsigned short int address)
{
SSPSTAT = 0b10000000;
SSPADD = address;
SSPCON1 = 0b00110110;
SSPCON2 = 0b00000001;
TRISC.B3 = 1; //Setting as input as given in datasheet
TRISC.B4 = 1; //Setting as input as given in datasheet
TRISC.B0=1;
TRISC.B1=1;TRISC.B2=1;TRISC.B5=1;TRISC.B6=1;TRISC.B7=1;
INTCON = 0b00000000;
INTCON.PEIE = 1;
INTCON.GIE = 1;
PIE1.SSPIE = 1;
PIR1.SSPIF = 0;
while(SSPSTAT.BF){zed = SSPBUF;SSPCON1.SSPOV = 0;SSPCON1.WCOL = 0;}
}
//##############################################################################
void main()
{
ADCON1=0b00001111;
TRISA.B0 = 0; //PORTD as output
PORTA.B0=0;
I2C_Slave_Init(0x18); //Initialize as a I2C Slave with address 0x30
while(1)
{
if(new==1)
{
PORTA.B0=1;
new=0;
}
}
}
Utilizo ese código tanto en " simulador de protues 8.0 " como en tableros reales 18f6420
Nuncaobtengounareaccióndelesclavocomosinoexistiera,siempreobtengounaseñal"notACK" que no se sabe es del Maestro o una respuesta del esclavo, pero estoy seguro de que "PIR1.SSPIF" nunca se vuelve igual a 1, ya que una vez que esto ocurra después de que ocurra una interrupción de MSSP, el valor de la variable llamada "nuevo" será igual a 1 y el LED en PORTA.B0 se iluminará
Entonces, cualquier ayuda, por favor, o cualquier edición en mi código que pueda sugerir para que funcione, por favor
Nota : cuando cambio SSPMx a 1110 en lugar de 0110, se produce la interrupción del MSSP esclavo y PIR1.SSPIF se convierte en 1. El LED de PORTA.B0 se ilumina de manera que el esclavo se interrumpe con éxito en el bit de paro de inicio, pero no con el envío de bytes de direcciones ni con la Llamada general, ya que traté de habilitar la llamada general y el envío de 0x00h, pero al final recibí la señal "NO ACK" / p>
SSPM3: SSPM0: bits de selección del modo de puerto serie síncrono maestro (2)
1111 = Modo esclavo I2C, dirección de 10 bits con bit de inicio y parada interrupciones habilitadas
1110 = Modo esclavo I2C, dirección de 7 bits con bit de inicio y parada interrupciones habilitadas
1011 = Modo maestro controlado por firmware I2C (Slave inactivo)
1000 = Modo maestro I2C, reloj = FOSC / (4 * (SSPADD + 1))
0111 = Modo esclavo I2C, dirección de 10 bits
0110 = Modo esclavo I2C, dirección de 7 bits