CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C Solutions and Problems on MultiSlave(Real)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
leonardo.araujo



Joined: 28 Jan 2004
Posts: 0
Location: Brasil

View user's profile Send private message Send e-mail

I2C Solutions and Problems on MultiSlave(Real)
PostPosted: Tue Feb 17, 2004 7:56 am     Reply with quote

Hi people sorry about my last Message (I wasnīt succeding on sending this message)
Does someone knows why when I use I2C to comunicate with a slave PIC and then try to communicate to another the second slave donīt respond.
When I use
i2c_start
i2c_write (slave1)
i2c_stop
AND
i2c_start
i2c_write(slave2)
i2c_stop

The slave 2 does not respond (If I use just on slave the comunication is Ok)
In this message I will try to put the source code of them:
Master Code
Code:

#include "C:\Documents and Settings\leonardo.araujo\Desktop\Projeto Telemetria\I2cMaster\i2cmaster.h"

/*Byte alto e baixo dos valores do ADC*/
BYTE v_alto,v_baixo;
BYTE v_adc_alto,v_adc_baixo;
void le_entrada(int entrada);
void le_atuador();
void atua_entrada(int8 n_bit,int1 b_val);
void inicia_lcd();
void escreve_controle_lcd();

void main()
{

   BYTE leo1,leo2;
   BYTE cont = 0;
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   inicia_lcd();
   while (TRUE)
   {
      le_entrada(31);
      cont++;
      if (cont > 1)
         break;
   }
   //To tendo que fazer um WorkArround neste Bug de Botar um bit de Sinal
   //e para mandar um valor de 8 bits terei que mandar 2 vezes
   printf("(%d %d)",v_adc_alto,v_adc_baixo);
   while (TRUE)
   {
      le_entrada(10);
      cont++;
      if (cont > 1)
         break;
   }
   printf("(%d %d)",v_adc_alto,v_adc_baixo);
   while (TRUE)
   {
      le_entrada(17);
      cont++;
      if (cont > 1)
         break;
   }
   printf("(%d %d)",v_adc_alto,v_adc_baixo);

   /*Agora endereca o microcontrolador de atuacao*/
   cont = 0;
   while (TRUE)
   {
      le_atuador();
      atua_entrada(7,1);

      cont++;
      if (cont > 10)
         break;
   }
   printf("Vindo do Atuador os nibles %d %d",v_alto,v_baixo);

}

void le_entrada(int entrada)
{
   //Procedure para fazer requisicao para o modulo ADC
   i2c_start();
   i2c_write(0x2E);//Manda um Request for Write
   i2c_write('?');//Manda Byte de comando
   i2c_write(entrada);//Complemento do comando
   
   //Agora le do Modulo a ordem e primeiro alto depois baixo
   i2c_start();   //Acho que vai ter que reescever o master tambem
   i2c_write(0x2F);//Manda um Request for read
   v_adc_alto = i2c_read();//Recebe sinalizando que quer mais
   v_adc_baixo = i2c_read(0);//Recebe ultimo byte*/
   //delay_us(50);
   i2c_stop();//Porque o I2C_Stop nao esta funcionando?
}

void le_atuador()
{
      i2c_start();
      i2c_write(0x20);//Manda um Request for Write
      i2c_write('?');//Manda Byte de comando

      i2c_start();   //Acho que vai ter que reescever o master tambem
      i2c_write(0x21);//Manda um Request for read
      v_alto = i2c_read();//Recebe sinalizando que quer mais
      v_baixo = i2c_read(0);//Recebe ultimo byte*/
      i2c_stop();
}

void atua_entrada(int8 n_bit,int1 b_val)
{
   //Mandando escrever em alguma pino do port B
      i2c_start();
      i2c_write(0x20);//Manda um Request for Write
      i2c_write(n_bit);
      i2c_write(b_val);
      i2c_write('!');//Manda Byte de comando
      i2c_stop();//Este Stop é opcional poder ser usado um Repeated Start
}

void inicia_lcd()
{
   /*Rotina de Inicializacao do LCD*/
   output_low(PIN_C7);//Poe E LOW
   delay_ms(20);
   escreve_controle_lcd();
}

void escreve_controle_lcd()
{
   output_low(PIN_C5);

   output_high(PIN_C7);//Poe E HIGH
   delay_cycles(10);
   output_low(PIN_C7);//Poe E LOW
}

And his header
Code:

#include <16F876.h>
#device adc=8
#use delay(clock=4000000)
#fuses HS,NOWDT,PUT,NOLVP
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,FORCE_HW)
#use rs232(baud=1200,parity=N,xmit=PIN_B7,rcv=PIN_B6,bits=8)


If I send 2 slave codes the server donīt receive my message then I will send just one (This code is fully working)
Code:

#include "C:\atuador\Atuador.h"

/*Buffer de Recebimento do PIC*/
int8 buff[TAM_BUFF];//Cuidado para nao acabar com a memoria do PIC
int8 indice_buff;
BYTE v_alto = 0,v_baixo = 0;
int1 em_processo_i2c_wr = 0;
int1 em_processo_i2c_r = 0;
char comando = 0;

void processa_pergunta()
{
   BYTE valor_b;
   /*Este comando manda uma o byte referente a uma porta como so vai ser a linha
   portb nos vamos mandar a parte alta e a parte baixa do byte de portb*/
   valor_b = input_b();
   //Agora antes de terminar a funcao vamos separa os bytes para mandar para I2C
   swap(valor_b);
   v_alto = valor_b&0b00001111;
   swap(valor_b);
   v_baixo = valor_b&0b00001111;
}

#int_SSP
interrupcao_i2c()
{
   CKP = 0;
   if (SSPSTAT != 0x30)
   {
      //0x2d(101101) Mascara os bits deixando aparecer somente D/a, S, R/W, BF
      switch (SSPSTAT & 0x2D)
      {
         //O Modulo Leitor foi enderecadao para receber um comando
         case (estado_1):
         /*Operacao Write do Master, o endereco fica em SSPBUF, temos que
         ler SSPBUF para apagar BF, O master tem que dar um tempo para*/
         for (indice_buff = 0;indice_buff < TAM_BUFF;indice_buff++)
         {
            buff[indice_buff]=0;
         }
         SSPOV=0; //Zera Bit de Overflow pois pode ter sido setado anteriormente
         indice_buff = 0;
         buff[indice_buff]=SSPBUF; //Le SSPBUF apagando BF
         CKP = 1; //Deixa o Master continuar
         break;

         //Agora o master esta mandando o comando (2 Vezes por comando)
         case (estado_2):
         SSPOV=0; //Zera Bit de Overflow pois pode ter sido setado anteriormente
         buff[indice_buff] = SSPBUF; //Le SSPBUF apagando BF
         if (buff[indice_buff] = '?') processa_pergunta();
         /*No Clock Streching nos podemos depurar, pois depois que soltar o CKP
         o Master vai continuar mandando ...*/
         indice_buff++; //Incrementa buffer
         //Nao deixa rolar Buffer Overflow (Caralho tem falha de seguranca)
         if (indice_buff >=TAM_BUFF)
         {
            indice_buff = 0;
            em_processo_i2c_wr = 1;
         }
         CKP = 1; //Deixa o Master continuar
         break;

         case (estado_3):
         /*O master vai comecar uma operacao de read iniciando com Start ou
         Restart depois mandando o endereco em SSPBUF*/
         indice_buff = 0;
         SSPBUF = v_alto;
         em_processo_i2c_r = 1;
         indice_buff++; //Incrementa para o proximo estado ... (estado 4)
         CKP=1; //Deixa o Master Shiftar SSPBUF fora do Slave liberando clock
         break;

         case (estado_4):
         /*Master quer ler mais bytes novamente*/
         //SSPBUF = buff[indice_buff]; //Manda Proximo Byte do buffer pro Master
         SSPBUF = v_baixo;
         indice_buff++; //Incrementa buffer
         //Nao deixa rolar Buffer Overflow (Caralho tem falha de seguranca)
         if (indice_buff >TAM_BUFF) indice_buff = 0;
         CKP=1; //Deixa o Master Shiftar SSPBUF fora do Slave liberando clock

         case (estado_5):
         /*Master nao quer mais saber de receber dados do slave, a logica i2c
         deve ser resetada e esperar por uma nova operacao do Master*/
         CKP = 1;
         break;

         default:
         /*Aconteceu um estado inesperado e nao conhecido devemos resetar o pic
         porem agora vou so indicar que algo fudeu..*/
         while (1);
         break;
      }
   }
}

void main()
{
   set_tris_a(0b00000000);
   set_tris_c(0b11111111);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   //Habilita interrupcoes para I2C
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   /*Inicia I2C em Modo Slave*/
   SSPCON1 = 0b00110110; //Modo Slave 7 bits enderecamento
   SSPADD = ENDERECO_SLAVE;
   SSPSTAT = 0;
   WCOL = 0;
   SSPOV = 0;
   while (TRUE)
   {
      output_high(PIN_A0);
      //O comando ? Pergunta o estado de uma linha o ! Seta seu estado.
      if ((buff[0] == '?') && (em_processo_i2c_wr == 1))
      {
         /*O CPU Master quer receber o status da linha portb, logo esta funcao
         separa o portb em 2 nibbles referentes ao nible alto e o nible baixo
         logo depois ele vai mandar 2 reads para receber estes valores*/
         em_processo_i2c_wr = 0;
         processa_pergunta();
         comando = '?';
      };
      if ((buff[0] == '!') && (em_processo_i2c_wr == 1))
      {
         em_processo_i2c_wr = 0;
      };
      if (em_processo_i2c_r == 1)
      {
         /*Foi pedida uma leitura se o comando anterior foi um ? esta na hora
         de mandar o nible alto e o nible baixo do comando*/
         em_processo_i2c_r = 0;
      }
      output_low(PIN_A0);
   }
}

And his header
Code:

#include <16F876.h>
#device adc=8
#use delay(clock=20000000)
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use rs232(baud=1200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


/*Como vimos a melhor forma de se implementar um slave I2c é na mao... ou seja
baseado no hardware do pic e o datasheet AN734*/

//Registradores associados ao I2C
#byte SSPADD  =0x93  //Endereco deste modulo Slave
#byte SSPCON1 =0x14  //Reg de Controle 1
#byte SSPCON2 =0x91  //Reg de Controle 2
#byte SSPBUF  =0x13  //Buffer dos dados mandados/recebidos
#byte SSPSTAT =0x94  //Diversos Status

//Bits do Reg de Status
#bit BF    = SSPSTAT.0  /*Em modo de transmissao indica se o recebimento foi
                        completado, em modo de recepcao indica se se a transmi
                        ssao foi completada*/
#bit UA     = SSPSTAT.1  //So e usado em modo de endereco de 10 bits
#bit R_W    = SSPSTAT.2  //Indica se o master mandou uma transacao read ou write
#bit START  = SSPSTAT.3  //Indica que uma condicao Start foi detectada
#bit STOP   = SSPSTAT.4  //Indica que uma condicao Stop foi detectada
#bit D_A    = SSPSTAT.5  /*Indica que o ultimo byte recebido foi um endereco ou
                        dado*/
#bit CKE    = SSPSTAT.6  //Configuracao I2c Specifica
#bit SMP    = SSPSTAT.7  //Configuracao do Slew Rate (para 100khz = 1)

//Bits do Reg de Controle 1
#bit SMPM0  = SSPCON1.0  //Bit 0 a 3 e usado para configurar o modo SSP
#bit SMPM1  = SSPCON1.1
#bit SMPM2  = SSPCON1.2
#bit SMPM3  = SSPCON1.3
#bit CKP    = SSPCON1.4  //Segura ou libera o Clock gerado pelo Master
#bit SSPEN  = SSPCON1.5  //Bit de Enable do modo SSP
#bit SSPOV  = SSPCON1.6  /*Bit de Overflow quando sum byte e recebido e o buffer
                         (SSPBUF) ainda nao foi apagado*/
#bit WCOL   = SSPCON1.7  //Bit de indicador de colisao MultiMaster (Nao usado)

//Bits do Reg de Controle 2
#bit SEN    = SSPCON2.0  /*No modo Slave indica Clock Streching em transmissao
                        ou recepcao em modo Slave e o (Start)*/
#bit RSEN   = SSPCON2.1  //So tem sentido em modo Master (Repeat Start)
#bit PEN    = SSPCON2.2  //So tem sentido em modo Master (Stop)
#bit RCEN   = SSPCON2.3  //Habilita Receive Mode (So tem sentido no Master)
#bit ACKSEN = SSPCON2.4  //Comeca Sequencia de ACK no Master
#bit ACKDT  = SSPCON2.5  //ACK de Bit de Dados
#bit ACKSTAT= SSPCON2.6  //ACK de Status Bit
#bit GCEN   = SSPCON2.7  //Chamada Geral (Usada para chamar todos os CI da BUS)

//Define os Estados possiveis ao Modo I2C Slave (Pegos no Datasheet AN734)

/*Estado 1 O Master comecou uma transacao Write apos um Start ou Restart com
o endereco deste modulo, neste momento SSPBUF esta cheio e contem o endereco
deste modulo passado pelo master SSPBUF deve ser lido para zerar BF mesmo que
o endereco seja descartado*/
#define estado_1 0x09   // D/A=0, S=1, R/W=0, BF=1

/*Estado 2 Depois do endereco tiver sido mandado pela operacao write do master
o master deve mandar um ou mais bytes para o slave. Se SSPBUF nao estiver cheio
devido ao write o Slave vai mandar um ACK no 9š tick do clock se nao vai ser
gerado um NACK devido ao flag SSPOV tiver sido setado*/
#define estado_2 0x29   // D/A=1, S=1, R/W=0, BF=1

/*Estado 3 O master iniciou uma transaco read apos um Start ou Restart depois
de ter mandado o endereco deste modulo. Neste momento o buffer esta esperando
para ser carregado para ser enviado para o master. O bit CKP e zerado para por
o clock do master em espera para dar tempo do slave preparar o byte. O byte
so sera mandado quando o slave soltar o CKP*/
#define estado_3 0x0C   // D/A=0, S=1, R/W=1, BF=0

/*Estado 4 Este estado acontece quando o master leu um byte e quer ler mais um*/
#define estado_4 0x2C   // D/A=1, S=1, R/W=1, BF=0

/*Estado 5 Este estado indica que o master mandou um NACk apos uma leitura
indicando que ele nao quer mais nenhum byte. Este estado reseta entao a logica
I2C Slave*/
#define estado_5 0x28   // D/A=1, S=1, R/W=0, BF=0

//Endereco deste modulo
#define ENDERECO_SLAVE 0x20
#define TAM_BUFF 3

I read on microchip errata that this could hapen on repeated start but I tested on my code and does not work, if someone could help
Thanks anyway

Remember this code works fine if does not have two PIC slaves
Later I would put an Image of the schematic

Obs:
Sorry about my english (Iīm from Brazil)
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Thu Feb 19, 2004 8:30 pm     Reply with quote

Make sure that each of your Slaves has a unique address and that the Master sends the correct addresses out to the I2C bus. You can talk to each Slave, without sending the Stop command, since you only have one Master that has control of the I2C bus.

Ronald
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group