Programación Específica > Programación en C
Problemas Con I2c En Css Picc
(1/1)
jjcorps:
Hola tengo problemas con el i2c para comunicar un maestro con un esclavo,esta comunicacion hace lo siguiente el maestro pide informacion al esclavo el cual le responde con (0xA0) el problema esta en que el maestro recibe siempre la señal (0xFF) es decir todo a 1 es como si no pudiese poner niveles bajos en las lineas de comunicacion i2c.
Uso PIC16F877A tanto para el maestro como para el esclavo y la resistencia pull-up que uso para i2c es 2K2
CODIGO DEL MAESTRO
--- Código: Text --- //////////////////////////////////////////////////// I2C master //// PIC16F877A //// PICmaster.C //// Crea una comunicacion entre varios PICS //// por i2c mandando lo leido al PC por el //// el puerto serie. //// //// Realizado por Juan José Chica Barrera //////////////////////////////////////////////////// #include <16f877A.h>#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP#use delay(clock = 10000000) // reloj 10MHz/* Configuracion principal del I2C Modo Maestro Tasa de transferencia rapida, aunq puede tener problemas I2c se hace por harwdware pa eso lo tenemos en el*/#use i2c(MASTER,SDA=PIN_C4,SCL=PIN_C3,FAST,FORCE_HW)/* Configuracion principal del puerto serie velocidad de 9600 baudios sin paridad con un bit de parada*/#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) /* Rutina de ESCRITURA a un dispositivo conectado al i2c i2cdev --> Direccion del dispositvo i2cdat --> Dato que le quiero enviar*/void i2cw(int i2cdev, int i2cdat){ i2c_start(); // Inicializo comunicación I2C i2c_write(i2cdev); // Envio Dirección de dispositivo I2C + R/W i2c_write(i2cdat); // Envio byte a escribir i2c_stop(); // Cierro comunicacion} /* Rutina de LECTURA a un dispositivo conectado al i2c i2cdev --> Direccion del dispositvo del que quiero leer*/int i2cr(int i2cdev){ // Rutina de lectura I2C int r=0x00; i2c_start(); i2c_write(i2cdev); r=i2c_read(); i2c_stop(); return(r);} unsigned int giro=80;main(){ output_float(PIN_C3); //I2C pin float output_float(PIN_C4); //I2C pin float while(1) { //COMUNICACION CON EL ESCLAVO 1 giro = i2cr(0x02); //Leo del dispositivo esclavo y lo muestro por el puerto B printf("Prueba de i2c %U\n\r",giro); //Lo muestro por el puerto serie delay_ms(1000); //Retardo de 1 segundo giro = 0; //Reseteo la variable } }
CODIGO DEL ESCLAVO
--- Código: Text --- //////////////////////////////////////////////////// I2C slave //// PIC16F877A //// PICslave1.C //// Crea una comunicacion entre varios PICS //// siendo una comunicacion muy basica //// //// Realizado por Juan José Chica Barrera //////////////////////////////////////////////////// #include <16f877A.h>#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP#use delay(clock = 10000000) // reloj 10MHz#use fast_io(B) // cambio rapido de estados en los puertos/* Configuracion principal del I2C Modo Esclavo Direccion 0b00000010 = 0x02 (Son 7 bits el bit que se desprecia es el de menor peso por tanto es 1) Tasa de transferencia rapida, aunq puede tener problemas I2c se hace por harwdware pa eso lo tenemos en el chip*/ #use i2c(SLAVE,SDA=PIN_C4,SCL=PIN_C3,ADDRESS=0x02,FAST,FORCE_HW) byte DATA = 69; // antes era 0x0F //Interrupcion provocada cuando algo ocurre en el i2c#INT_SSPvoid ssp_interupt (){ output_b(0xFF); if(i2c_poll()){ //Si tenemos algo en el buffer de entrada output_b(i2c_read()); //lo mostramos por el puerto B } else{ i2c_write(0xA0); //Si no esq el master quiere q le mandemos la info //solamente la parte baja de un entero (1 byte) output_b(0x00); }} void main (){ set_tris_b(0x00); //RB 7-0:OUT output_b(0); //en un principio esta apagado enable_interrupts(GLOBAL); //Activamos las interrupciones enable_interrupts(INT_SSP); //Activamos la interrupcion para el i2c while (1); //bucle infinito}
Envio los datos por el puerto serie para verlos en condiciones.
¿alguna idea de donde puede estar el error?
tejon1424118:
qu etal.
ya checaste la dirrecion que le estas enviando del maestro al escalvo
porque el dato a enviar en esa parte no es la misma si quieres leer o escribir en es esclavo,
en tu codigo solo aparece la variable, peor no puedo ver cual es el valor que estas enviando
i2cdev=direccion+r/w,
si la direccion del escalvo es 0xa0
para que escriba en el esclavo queda igual 0xa0
pero si quieres leer del esclavo seria oxa1
allisap:
Prueba la siguiente
1.-en el maestro la función i2c_write te devuelve el ACK es decir es cero si el esclavo
recibio los datos y 1 si no los recibio, asi que puedes hacer algo como esto
if (i2c_write(0xB4)==0){ // direccion del sensor melexis para mandar comando
output_toggle(PIN_B0);
}
y coloca un led en el pin B0 si esta parpadeando cada que envias datos
quiere decir que el esclavo si recibe los datos
2.-en el esclavo coloca un toggle de un pin en la interrupción
y coloca un led tambien , con esto sabrias si el esclavo recibe los datos y si esta entrando a la interrupcion,
3.-no uses el pooling , mejor usa la funcion i2c_isr_state();
4.- baja la velocidad,para ver si eso no es lo que te da problemas (primero camina, luego corre )
prueba a usar simples toggles y leds para saber en que punto esta fallando el codigo
esto realmente te ayuda a depurar mas facilmente,
espero te sirva
Saludos
Victor Pasilla Campos
Puebla, Pue
Navegación
Ir a la versión completa