TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: JumppingJack en 05 de Julio de 2006, 17:47:31
-
Excuse me, friends. Although my English is very bad, I wrote in English because my Spanish is worse yet. But I can read in Spanish. I want that a PIC 16f877 (master) reads bytes from two slaves 16f877. I use Proteus to simulate it. When the master reads from only slave, my routine works perfectly. When I use the routine below, the master reads the first byte from the first slave called. Next, the master only read 0xFF. Might anybody help me?
//Master Code
#include <16f877>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,SLOW,FORCE_HW)
void main(void){
byte buffer1=0, buffer2=0, dado1,dado2;
while(TRUE){
i2c_start();
i2c_write(0xa0);
delay_ms(10);
i2c_write(buffer1);
delay_ms(10);
i2c_start();
i2c_write(0xa1);
delay_ms(10);
dado1=i2c_read(0);
i2c_stop();
printf("\n Escravo 1 buffer %i %u\r",buffer1,dado1);
if(++buffer1==10) buffer1=0;
delay_ms(2000);
/*
i2c_start();
i2c_write(0xb0);
delay_ms(10);
i2c_write(buffer2);
delay_ms(10);
i2c_start();
i2c_write(0xb1);
delay_ms(10);
dado2=i2c_read(0);
i2c_stop();
printf("\n Escravo 2 buffer %i %u\r",buffer2,dado2);
if(++buffer2==10) buffer2=0;
delay_ms(2000);
*/
}
}
// Slave address 0xA0
#include <16f877>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#include <lcd>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0, slow)
typedef enum {NOTHING, CONTROL_READ,
ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;
I2C_STATE fState;
BYTE address, buffer[0x10];
#INT_SSP
void ssp_interupt(){
BYTE incoming;
if (i2c_poll() == FALSE){
if (fState == ADDRESS_READ){ //i2c_poll() returns false on the
i2c_write (buffer[address]);//interupt receiving the second
fState = NOTHING; //command byte for random read operation
}
}
else{
incoming = i2c_read();
if (fState == NOTHING){
fState = CONTROL_READ;
}
else
if (fState == CONTROL_READ) {
address = incoming;
fState = ADDRESS_READ;
}
else
if (fState == ADDRESS_READ) {
buffer[address] = incoming;
fState = NOTHING;
}
}
}
void main ()
{
int i=0;
fState = NOTHING;
address = 0x00;
do{
buffer = i;
i+=1;
}while (i<10);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {
}
}
//Slave Address 0x0B
#include <16f877>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#include <lcd>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xb0, slow)
typedef enum {NOTHING, CONTROL_READ,
ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;
I2C_STATE fState;
BYTE address, buffer[0x10];
#INT_SSP
void ssp_interupt(){
BYTE incoming;
output_bit (pin_b0, true);
if (i2c_poll() == FALSE){
if (fState == ADDRESS_READ){ //i2c_poll() returns false on the
i2c_write (buffer[address]);//interupt receiving the second
fState = NOTHING; //command byte for random read operation
}
}
else{
incoming = i2c_read();
if (fState == NOTHING){
fState = CONTROL_READ;
}
else
if (fState == CONTROL_READ) {
address = incoming;
fState = ADDRESS_READ;
}
else
if (fState == ADDRESS_READ) {
buffer[address] = incoming;
fState = NOTHING;
}
}
}
void main ()
{
int i=0;
fState = NOTHING;
address = 0x00;
do{
buffer = 2*i;
i+=1;
}while (i<10);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {
}
}
-
Excuse me, friends. I write in English because my Spanish is wrost. But I can read in Spanish. I want that a PIC 16f877 (master) reads bytes from two slaves 16f877. I use Proteus to simulate. When does the master read from only a slave, does my routine work perfectly. When I use the routine below, the master read the first byte from the first slave called. Next, the master only read 0xFF. Might anybody help me?
Mis experiencias con el proteus no son 100% satisfactorias. Casualmente hice un firmware para un 18F452 que grababa una eeprom i2c.
El software "en el mundo real" funciona de maravillas hace mucho tiempo.
En proteus... el pic hacia cosas extrañas y no logré hacerlo funcionar. Es muy probable que el problema sea que yo no lo sé configurar bien, pero tal vez esto también esté relacionado con tu problema.
Más allá de eso, tu dices:
"When does the master read from only a slave, does my routine work perfectly. "
Has probado 'repetidos' accesos al esclavo 0xA0 ? O solo 1 vez? La diferencia es importante.
Puedes probar esto? Es decir, acceder muchas veces solo al 0xA0 ?
-
Yes, Maunix.
When the master reads from only a slave (no matter wich one), my routine repeatedly works fine.
To block a specific slave, I use /* and */ and test my code.
For example:
Slave 1 Buffer´s: [0xC7 0x23 0x56 0xA9]
Slave 2 Buffer´s: [0x45 0x32 0xAF 0xDE]
If I block the Slave 2, the master continually reads from Slave 1:
0xC7, 0x23, 0x56, 0xA9, 0xC7, 0x23, 0x56, 0xA9,0xC7...
If I block the Slave 1, the master continually reads from Slave 2:
0x45, 0x32, 0xAF, 0xDE,0x45, 0x32, 0xAF, 0xDE,0x45...
But if I block none of them, the master read:
0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF...
Thanks.
-
Como "bloqueas" a tus slave?
a) Comentas el código en el master?
b) quitas la conexión física en el simualdor?
-
Si, Mauricio.
Comento el código.
-
Si, Mauricio.
Comento el código.
Puedes 'capturar errores' ? He observado que en tu código asumes siempre que se conectarán bien y no habrá error alguno.
Errores pueden ser (por citar algunos)
1) Que no puedas tomar el bus
2) Que no recibas el Acknowledge (porque el esclavo no interpretó que el comando era para él)
3) Que haya una colisión en el lado del master
etc.
Si 'capturas' los posibles errores, tal vez descubras algo que sea importante a tener en cuenta y estés muy crítico con algunos tiempos.
Otra cosa que he observado es que no esperas a que se ponga IDLE el bus, simplemente esperas 2 segundos, pero tal vez solo debas comprobar el estado IDLE sin esa demora.
Saludos
-
Dentro del MPLab hay dos rutinas, la i2c.h y la sw_i2c.h. La primera es para hacer un i2c normal, utilizando los registros internos del pic. La otra es para hacer un protocolo i2c con cualquier puerto digital del integrado. No te compliques y utiliza las librerias que ya estan hechas, que seguro que funcionan. La velocidad se la puedes cambiar, ya que dentro del fuente hay notas indicando que se puede modificar.
Atentamente
Deimos
http://www.astroelectronica.iespana.es/
-
Hola dandole una mirada al codigo me parecio ver un error en el codigo del PIC maestro, pues al analizarlo inicia la comunicacion con el primer esclavo, hace un delay de 10ms y escribe el dato en él sin terminar la comunicacion, empezando la comunicacion con el otro pic, me parece que ese es el error
//Master Code
......
while(TRUE){
i2c_start();
i2c_write(0xa0);
delay_ms(10);
i2c_write(buffer1);
delay_ms(10);
i2c_start();
i2c_write(0xa1);
delay_ms(10);
dado1=i2c_read(0);
i2c_stop();
....
Pienso que puede quedar asi:
while(TRUE){
i2c_start();
i2c_write(0xa0);
// delay_ms(10); // no veo que sea necesario esperar tanto tiempo para mandar otro dato
i2c_write(buffer1);
I2C_STOP(); // Aca termina la comunicacion con el 1er esclavo
delay_ms(10);
i2c_start();
i2c_write(0xa1);
// delay_ms(10); // no veo que sea necesario esperar tanto tiempo para recibir un dato
dado1=i2c_read(0);
i2c_stop();
Espero les ayude. Bye :-/
-
Hola señores, se que han pasado 6 años desde este post pero, habría la posibilidad de poder tener contacto con alguien que sepa este problema que le paso al compañero JumpingJack, ya que me esta pasando a mi exactamente lo mismo y no se ya que variar en el código para que funcione. Agradecería muchísimo la posible ayuda que me podáis ofrecer y yo encantado de escuchar posibles ideas para arreglar el problema.
Gracias de antemano.
Saludos