Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Estoy tratando de comunicar dos PIC16F877 via I2C, utilizando lenguaje C para PIC (PICC), y hasta ahora no lo he logrado. 😕 no encuentro la manera que el PIC maestro se enlace con el PIC esclavo, necesito algún tipo de información, tutorial o enlace de alguna página que pueda ayudarme por favor. 😆
Efectivamente, esa es la idea. Tanto maestro como esclavo leen bytes que procenden de su convertidor analógico-digital. El maestro puede ver en su puerto B el valor de su convertidor AD o bien, ver el valor del último byte leído del esclavo. El esclavo por su parte, puede mostrar en su puerto B el valor de su convertidor AD o bien el último dato escrito por el maestro en él. Para ver uno u otro dato, cada PIC emplea un PIN que puede ser activado por un dip_switch como indicas.
Respecto a lo de Slow, el protocolo I2C permite dos velocidades de transferencia. Para indicar al compilador CCS si prefieres la baja o la alta, debes especificar la palabra Slow o Fast, según el caso.
Hola Mosvack, al fin se comunicaron los PIC's via I2C, los programas que me enviastes funcionan a la perfección, ayer mismo los termine de probar, ahora solo me falta adaptarlo a mi proyecto de tesis... Muchas Gracias por la colaboración prestada... saludos desde Venezuela... 😀 estamos en contacto...
Hola Mosvack, la rutina que me enviastes funciona muy bien, pero ahora necesito enviar mas de 1Byte en la transmisión I2C. Como la haría?? tienes alguna idea de cómo hacerlo? he tratado de modificar ese programa para lograrlo y hasta ahora no lo he podido hacer.. Cualquier comentario o idea se le agradecería. Gracias por la ayuda prestada!!! 😛
Hola Rick_rs
Algo fundamental que tienes que tener en cuenta es que maestro y esclavo deben saber el número bytes que van a intercambiar. Si el maestro está recibiendo bytes del esclavo, puede abortar la comunicación generando el pulso de STOP. En el caso del esclavo, si desconoce el número de bytes a recibir y resulta mayor de los que esperaba... los bytes restantes procedentes del maestro no serán atendidos...
Para modificar las rutinas en el caso del maestro debería bastar con añadir más líneas ... por ejemplo... sería algo como esto para dos bytes:
// Rutina de petición de dato
//bit_set(sspcon2,3);
i2c_start();
output_bit(PIN_A5,i2c_write(DIREC + 1)); // Dirección con bit de lectura (1)
valor = i2c_read(0); // Dato recibido del esclavo
valor2 = i2c_read(0); // 2º Dato recibido...
i2c_stop();
delay_ms(1000); // Retardo para no env.....
(y para el envío)
// Rutina de envío de dato
// bit_clear(sspcon2,3);
i2c_start();
output_bit(PIN_A5,i2c_write(DIREC + 0)); // Dirección con bit de escritura (0)
output_bit(PIN_C0,i2c_write(captura)); // Dato
output_bit(PIN_C0,i2c_write(otro_dato)); // El otro byte...
i2c_stop();
delay_ms(1000); // Retardo ...
____________________________
(*) Por cierto... creo que no te lo dije... pero esos pines que pongo a cero y uno, como el A5 y el C0 los empleé para poder ver cómo iba la transmisión... pero no son necesarios para la misma... simplemente están ahí desde la fase de las pruebas...
_______________________________
Respecto al esclavo, para lograr la sincronización y que no se te escapen bytes, dispone de un bit en el registro SSPCON1 que congela la señal de reloj. De hecho, este bit (CKP) se pone a cero al coincidir la dirección enviada por el maestro, con la propia del esclavo. Lo que tú necesitas es que esta línea se te ponga a cero con cada byte que recibas... para dar tiempo al programa del esclavo a recoger los bytes del maestro... de lo contrario, el maestro emitiría dichos bytes de corrido y posiblemente recibirías datos erróneos o se bloquearía la transmisión. Si no recuerdo mal... creo que el compilador CCS configura los registros del PIC para que CKP se ponga a cero tras cada recepción, por lo que sólo tendrías que ocuparte de ponerlo a 1 cuando estés listo para recibir el nuevo byte... algo así:
#int_SSP
SSP_isr()
{
int direcc;
output_bit(PIN_A2,1);
while(!bit_test(pir1,3));
bit_clear(pir1,3);
#asm
movf sspbuf,0
movwf direcc
#endasm
if(bit_test(direcc,0) == 0)
{
bit_set(sspcon1,4); // Desbloqueo de reloj...
while(!bit_test(pir1,3));
bit_clear(pir1,3);
// Primera lectura...
#asm
movf sspbuf,0
movwf valor
#endasm
// Aquí metemos las líneas de código para mover el dato
// recibido en "valor" a otro lugar...
// una vez movido, descongelamos la señal y recogemos el otro dato
bit_set(sspcon1,4); // Descongelando la línea de reloj...
#asm
movf sspbuf,0
movwf valor
#endasm
// Nuevo dato en valor...
output_bit(PIN_A3,1);
}else{
#asm
movf captura,0
movwf sspbuf
#endasm
// Efectuado primer envío..
#asm
movf dato_2,0
movwf sspbuf
#endasm
//preparado segundo envío
bit_set(sspcon1,4); // Descongelando la línea de reloj
while(!bit_test(pir1,3));
bit_clear(pir1,3);
output_bit(PIN_A5,1);
}
No recuerdo muy bien si la línea de reloj se congelaba tanto en los envíos como en las recepciones o sólo en las recepciones del esclavo. Creo que CCS lo configura para los dos. Si no fuera así, tendrías dos opciones. Probar a configurar tú los registros según el datasheet para bloquear la línea en ambas direcciones o congelarla tú "a mano" empleando las funciones "bit_set" y "bit_clear" con el registro SSPCON1.
Espero que te sirva
Saludos
Hola Mosvack
Modifique el programa siguiendo tus sugerencias, y ya el PIC Esclavo recibe mas de 1byte, pero aún no he logrado que transmita al PIC Maestro mas de 1byte...
No entiendo bien como funciona la línea de reloj en modo de transmisión del esclavo, coloque la secuencia de rutina que especificastes para los dos envíos, pero solo llega el 1byte al Maestro, y la comunicación entre ellos no se cuelga...
Seguire haciendo pruebas a ver que tal me va, y si consigues algo por allí al respecto estaría muy interesado en leerlo... Gracias por tu colaboración.. 🙂