fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

PIC 16F876A i2c (ma...
 
Avisos
Vaciar todo

PIC 16F876A i2c (maestro y esclavo en el mismo PIC)

7 Respuestas
3 Usuarios
0 Reactions
3,590 Visitas
xyvy
Respuestas: 50
 XyVy
Topic starter
(@xyvy)
Trusted Member
Registrado: hace 16 años

Hola chicos, estoy usando un PIC 16F876A para realizar comunicaciones como esclavo de un PC usando i2c, y todo funciona correctamente.

Por otro lado tengo otro pequeño programa que usa un PIC 16F876A como maestro para comunicarse con una controladora de motores la MD22 y todo va bien, mediante un interruptor, arranco y paro un motor a mi voluntad.

Ahora estoy intentado juntar todo eso, aprovechando el i2c por hardware para el modo esclavo del PIC contra el PC (maestro), y usando otras dos patillas para simular por software i2c como maestro para comunicarme con la controladora MD22 (esclavo).

Bueno el programa surge nada más poner el #use i2c(MASTER, ....) a partir de ese momento la parte del esclavo deja de funcionar.

Os pongo el programa completo y me decías porqué, aparece con comentarios las funciones del maestro, porque solo con poner el #use i2c(Master...) deja de funcionar el circuito.

#include <16F876A>

#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected

#use delay(clock=4000000)

#byte port_b=0x06

//#use i2c(MASTER, FAST, sda=PIN_A0, scl=PIN_A1, address=0xB0, force_sw, stream=i2cM)
#use i2c(SLAVE, FAST, sda=PIN_C4, scl=PIN_C3, address = 0x08, force_hw, stream = i2cS)

// Comandos soportados por el PIC 16F876 en nuestro software
#define INIT 0x01
#define CONSULTA_MOTOR1 0x02
#define CONSULTA_MOTOR2 0x03
#define MUEVE_MOTOR1 0x04
#define MUEVE_MOTOR2 0x05
#define INTERRUPTOR1 0x06
#define INTERRUPTOR2 0x07
#define INTERRUPTOR3 0x08
#define INTERRUPTOR4 0x09
#define STOP_MOTOR1 0x0A
#define STOP_MOTOR2 0x0B

// definimos los datos para usar i2c
char data;
char cuenta;
BYTE state;
BYTE comando;
BYTE dato;

/*
void inicializa()
{
output_high(PIN_B2);
i2c_start(i2cM);
i2c_write(i2cM, 0xB0); // Dirección del dispositivo
i2c_write(i2cM, 0x00); // Registro de Modo
i2c_write(i2cM, 0x01); // Motor1 detenido
i2c_stop(i2cM);
output_low(PIN_B2);
}

void MueveMotor1(char dato)
{
output_high(PIN_B2);
i2c_start(i2cM);
i2c_write(i2cM, 0xB0); // Dirección del dispositivo
i2c_write(i2cM, 0x01); // Registro de modo
i2c_write(i2cM, dato); // Registro Velocidad motor 1
i2c_stop(i2cM);
output_low(PIN_B2);
}

void MueveMotor2(char dato)
{
output_high(PIN_B2);
i2c_start(i2cM);
i2c_write(i2cM, 0xB0); // Dirección del dispositivo
i2c_write(i2cM, 0x02); // Velocidad de los motores
i2c_write(i2cM, dato); // Velocidad del motor2
i2c_stop(i2cM);
output_low(PIN_B2);
}

void StopMotor1()
{
output_high(PIN_B2);
i2c_start(i2cM);
i2c_write(i2cM, 0xB0); // Dirección del dispositivo
i2c_write(i2cM, 0x01); // Registro de Modo
i2c_write(i2cM, 128);
i2c_stop(i2cM);
output_low(PIN_B2);
}

void StopMotor2()
{
output_high(PIN_B2);
i2c_start(i2cM);
i2c_write(i2cM, 0xB0); // Dirección del dispositivo
i2c_write(i2cM, 0x02); // Velocidad de los motores
i2c_write(i2cM, 128); // velocidad del motor1
i2c_stop(i2cM);
output_low(PIN_B2);
}

*/

#INT_SSP
void ssp_interupt ()
{
state = i2c_isr_state();

if(state<0x80) //master is sending data
{
if(state == 0)
{

} else if (state == 1) //first received byte
{
output_high(PIN_B2);
comando = i2c_read(i2cS);
} if (state==2) { // 2º byte recibido
dato=i2c_read(i2cS);
}
}else if (state == 0x80) { //master is requesting data
output_high(PIN_B1);
if (input(PIN_B4)) {
i2c_write(i2cS, 1);
} else {
i2c_write(i2cS, 0);
}
i2c_write(i2cS, cuenta); //send requested data
cuenta++;
}
}

void main()
{
char data;
int pulsado=0;
char sw=0;
int activo;
cuenta=0;
port_b=0;

enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);

sw=0;
pulsado=0;
while (1) {
/*
activo=input(PIN_B4);
if (activo && (sw==0) && (!pulsado)) {
output_low(PIN_B2);
MueveMotor1(255);
StopMotor2();
pulsado=1;
sw=1;
} else if (activo && (sw==1) && (!pulsado)) {
output_high(PIN_B2);
MueveMotor2(255);
StopMotor1();
pulsado=1;
sw=0;
}

delay_ms(50);
if (!input(PIN_B4)) {
output_low(PIN_B2);
pulsado=0;
}
delay_ms(50); */
}

}

Se acepta cualquier sugerencia, porque por más que le doy vueltas no encuentro la solución.

Gracias de antemano.

Responder
6 respuestas
xyvy
Respuestas: 50
 XyVy
Topic starter
(@xyvy)
Trusted Member
Registrado: hace 16 años

Hola Lorth, no se que te refieres a lo del puerto con LOW, los pines B1 y B2 tienen asociados unos led, rojo y verde para indicar un poco el estado del aparato, no se si te refieres al output_low(PIN_B2) por ejemplo.

El i2c esclavo en el PIC lo hago por hardware porque lei que sino no funciona bien, usando solamente el pic en modo esclavo el programa funciona perfectamente. El problema viene al introducir #use i2c(master...) porque entonces la parte del esclavo deja de funciona correctamente.

Que hago?

Responder
xyvy
Respuestas: 50
 XyVy
Topic starter
(@xyvy)
Trusted Member
Registrado: hace 16 años

Bueno señores ya lo he resuelto, creo saber porqué, los uses los he dejado de la siguiente manera:

#use i2c(MASTER, sda=PIN_A0, scl=PIN_A1, address=0xB0, stream=i2cM)
#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, address = 0x08, force_hw, stream = i2cS)

Pero donde creo que tenía el fallo era la rutina de atención a la interrupción que trataba el modo esclavo, (se me había olvidado indicar de que steram se trataba), luego ha quedado:

#INT_SSP
void ssp_interupt ()
{
state = i2c_isr_state(i2cS);

if(state<0x80) //master is sending data
{
if(state == 0)
{

} else if (state == 1) //first received byte
{
output_high(PIN_B2);
comando = i2c_read(i2cS);
} if (state==2) { // 2º byte recibido
dato=i2c_read(i2cS);
}
}else if (state == 0x80) { //master is requesting data
output_high(PIN_B1);
if (input(PIN_B4)) {
i2c_write(i2cS, 1);
} else {
i2c_write(i2cS, 0);
}
i2c_write(i2cS, cuenta); //send requested data
cuenta++;
}
}

Gracias por vuestro tiempo!!
Cuidaos!

Responder
Página 2 / 2
Compartir: