i2c iletişiminde slave kesme sorunu

Başlatan yasin_arsln, 03 Aralık 2013, 11:16:07

yasin_arsln

Selamlar herkese,

İki pic arasında i2c ile haberleşme yapmaya çalışıyorum. Kullandığım PICler 18F4520 her ikiside osilatör frekanslarım 20mhz. RS485 ile master PIC'e komut gönderip onunda slave PIC'e i2c ile veri göndermesini istiyorum.

İlk olarak master.h pic i2c ve rs485 ayarlarım.
#include <I2C_deneme00.h>
#int_TIMER0
void  TIMER0_isr(void) 
{
   if (glbLedDurum==LED_BLINKING) output_toggle(LED1);
   clear_interrupt(int_timer0);
}
#INT_RDA
void rs232_isr()
{
   char rs_gln_veri;    //rs_gln_veri değişkenin karakter türünde tanımlıyoruz.
   rs_gln_veri=getc();           //gelen veriyi rs_gln_veri'ye atıyoruz.

   if(glbState==START_STATE)        // Eğer glbState START_STATE eşit ise Blok içindeki işlemi yap.
   
   {
       if(rs_gln_veri=='[')             // Eğer rs_gln_veri '[' eşit ise Blok içindeki işlemi yap.
         {
         glbState=FRAME_START_STATE;   // glbState'ye FRAME_START_STATE(MOD_BUS üzerindeki adres seçim yeri)'yi ata.
         }
   }
   
   else if(glbState==FRAME_START_STATE)
   
   {
       if(rs_gln_veri==']')             //Eğer rs_gln_veri ']' eşit ise Blok içindeki işlemi yap.
         {
         glbState=START_STATE;
         }
       else if(rs_gln_veri=='M')        //Eğer rs_gln_veri 'M' eşit ise Blok içindeki işlemi yap.
         {
         glbState=M_STATE;
         }
       else glbState=DEAD_STATE;        //veri bunlardan biri değilse DEAD_STATE de eşitle
   }
     else if(glbState==M_STATE)
  
  {
      if(rs_gln_veri=='L')
      {
      glbState=LED_STATE;
      }
      else if(rs_gln_veri=='H')
      {
      glbState=I2C_STATE;
      }

      else if(rs_gln_veri=='I')
      {
      glbState=INFO_STATE;
      }
      else if(rs_gln_veri==']') 
      {
      glbState=START_STATE;
      }
   
      else 
      glbState=DEAD_STATE;
      
  }
   /************************************************************************
 //LED DURUMLARININ BASLANGİCİ
 ***********************************************************************/
 
  else if (glbState==LED_STATE)
  {
      if(rs_gln_veri=='1')
      {
      glbLedDurum=1;
      glbState=LED_JOB_STATE;
      }
      else if(rs_gln_veri=='0'){glbLedDurum=0;glbState=LED_JOB_STATE;}
      else if(rs_gln_veri=='B'){glbLedDurum=LED_BLINKING;glbState=LED_JOB_STATE;}
      else if(rs_gln_veri==']') {glbState=START_STATE;}
      else glbState=DEAD_STATE;
  }
  
  else if (glbState==LED_JOB_STATE)
  
  {
      if(rs_gln_veri==']'){glbState=LED_DO_JOB_STATE;}                        //LED_DO_JOB_STATE
      else glbState=DEAD_STATE;
  

  }

/***********************************************************
//LED DURUMLARI SONU
***********************************************************/
/**********************************************************
//INFO:HABERLEŞME BİLGİ DURUMU
**********************************************************/
   else if (glbState==INFO_STATE)                                             //INFO_STATE
   {
      if (rs_gln_veri==']') 
      {
         glbState=INFO_DO_JOB_STATE;                                          //INFO_DO_JOB_STATE
      }
      else glbState=DEAD_STATE;                                               
   }
/**********************************************************
INFO:HABERLEŞME BİLGİ DURUMU SONU
**********************************************************/
/**********************************************************
I2C:HABERLEŞME 
**********************************************************/
  
    else if (glbState==I2C_STATE)                                             //INFO_STATE
   {
      if (rs_gln_veri==']') 
      {
         glbState=I2C_DO_JOB_STATE;                                          //INFO_DO_JOB_STATE
      }
      else glbState=DEAD_STATE;                                               
   }
/**********************************************************
I2C:HABERLEŞME 
**********************************************************/
   Else 
   glbState=DEAD_STATE;

}

/*************************************************
**************************************************/
int1 slave_hazirmi()
{
int1 ack;
i2c_start();
ack=i2c_read(0xba);
i2c_stop();
return !ack;
}

void slave_yaz(int veri)
{
while(!slave_hazirmi());
i2c_start();
i2c_write(0xb0);
i2c_write(veri);
i2c_stop();
delay_ms(20);

}
int slave_oku()
{

int veri;
while(!slave_hazirmi());

i2c_start();
i2c_write(adres);
i2c_write(tampon_adresi);
i2c_start();
i2c_write(adres+1);
veri=i2c_read(0);
i2c_stop();
return(veri);
}

/************slave fonksiyonları  ****************
**************************************************/
void init_processor()
   {
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   set_tris_a(0x00);
   Set_tris_c(0xC0);//RS485 aktif ve C portunun 5 pini çıkış olarak ayarlandı.
   SET_TRIS_B(0x00);
   SET_TRIS_D(0x00);
   setup_timer_0(RTCC_DIV_4);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   output_low(RS485_ReceiveTransmit); //Rs484 okuma modunda
   glbState=START_STATE;

   enable_interrupts(INT_RDA);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   
   glbLedDurum=LED_BLINKING;
   glbState= START_STATE;
   output_b(0x00);
   output_d(0x00);

   
   
   }
//!int8 i2c_command=66;
void main()
{
init_processor();
    while(1) {
                        
      switch(glbState) {        

                                
         case(START_STATE)      : 


                                  DELAY_MS(10);
                                  output_low(RS485_ReceiveTransmit); //Rs485 okuma modunda 
                                  delay_ms(10);
                                  break;
                                  
                                  
         case(LED_DO_JOB_STATE) : 
                                  if (glbLedDurum==1) output_high(LED1);
                                  else if (glbLedDurum==0) output_low(LED1);
                                  delay_ms(10);
                                  glbState=START_STATE;
                                  break;
                                  
                                  
         case(INFO_DO_JOB_STATE) :
//!                                  delay_ms(10);
//!                                  
                                  output_high(RS485_ReceiveTransmit); //Rs485 yazma modunda
                                  printf("[M:INFO:OK]\n\r");

                                  delay_ms(15);
                                  output_low(RS485_ReceiveTransmit); //Rs485 okuma modunda 
                                  delay_ms(5);
                                  
                                  glbState=START_STATE;
                                  break;   
                                  
         case(I2C_DO_JOB_STATE)  :
         
                                  i2c_start();
                                  output_high(RS485_ReceiveTransmit); //Rs485 yazma modunda
                                  printf("[M:I2C:OK]\n\r");                                  
                                  i2c_write(0xb0);
                                  i2c_write('[');
                                  i2c_start();
                                  i2c_write(0xb0);
                                  i2c_write('M');
                                  i2c_stop();

                                  glbState=START_STATE;
                                  break;                                  
         case(DEAD_STATE)  :
                                  delay_ms(50);
                                  glbState=START_STATE;
                                  break;                                    
                        }
    }
}


I2C_DO_JOB_STATE kısmında slave adrese veri yazıyorum. Slave adres teki pic ile i2c kesmesi ile veri okumak istiyorum ama çıkış vermiyor.
Slave.c 'de void main() fonksiyonu altında while(1) içinde i2c bilgisini okuyorum ve şartları sağlıyor. Kesmede neden hata alıyorum bilemiyorum.

Slave.h
#include <18LF4520.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //Low power osc < 200 khz
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOXINST                    //Extended set extension and Indexed Addressing mode enabled

#use delay(crystal=20000000)
#define LED PIN_A5

#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include "Tanimlamalar.h"
#use i2c(Slave,slow=100000,sda=PIN_C4,scl=PIN_C3,address=0xb0,FORCE_SW)


Slave.c
#include <slave00.h>
#include <stdlib.h>

#int_TIMER0
void  TIMER0_isr(void) 
{
   if (glbLedDurum==LED_BLINKING) output_toggle(LED1);
   clear_interrupt(int_timer0);
}
//!#INT_SSP
//!VOid ssp_interrupt()
//!{
//!int islem1=i2c_read(0);
//!delay_us(9);
//!int islem2=i2c_read(0);
//!delay_us(9);
//!islem=islem1*32+islem2;
//!int veri1=i2c_read(0);
//!delay_us(9);
//!int veri2=i2c_read(0);
//!delay_us(9);
//!veri=veri1*32+veri2;
//!i2c_stop();
//!CLEAR_interrupt(int_ssp);
//!}

#use delay(clock=20000000)


void main()
{
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   set_tris_a(0x00);
   Set_tris_c(0xC0);//RS485 aktif ve C portunun 5 pini çıkış olarak ayarlandı.
   SET_TRIS_B(0x00);
   SET_TRIS_D(0x00);
   setup_timer_0(RTCC_DIV_4);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   output_low(RS485_ReceiveTransmit); //Rs484 okuma modunda
   enable_interrupts(INT_RDA);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);
   glbLedDurum=LED_BLINKING;
   output_b(0x00);
   output_d(0x00);

while(TRUE)
   {

int islem1=i2c_read();
int islem2=i2c_read();
int islem=islem1*32+islem2;
int veri1=i2c_read();
int veri2=i2c_read();
int veri=veri1*32+veri2;
i2c_stop();
output_High(RS485_ReceiveTransmit); //Rs485 yazma modunda
printf("[Mod]\n\r");
//!delay_ms(100);
if(islem=='['){
if(veri=='M'){
DELAY_MS(500);
output_high(RS485_ReceiveTransmit); //Rs485 yazma modunda
printf("[M\n\r");
}
}
  
}


Tanımlamalar.h
#ifndef __TANIMLAMALAR__
#define __TANIMLAMALAR__


/*Fonksiyonlarda kullanılmak üzere SirenBilisim tarafından yazılan global değerler*/
// [ Begin ] Global Değişkenler
int glbState;
int8 glbLedDurum;  //0:Off, 1:On 2:blinking
char rs_gln_veri;
int8 islem;

#define START_STATE                        0
#define FRAME_START_STATE                  1
#define M_STATE                            2
#define LED_STATE                          3
#define LED_JOB_STATE                      4
#define LED_DO_JOB_STATE                   5
#define INFO_STATE                         6
#define QUERY_STATE                        7
#define INFO_DO_JOB_STATE                  8
#define I2C_STATE                          9

#define I2C_DO_JOB_STATE                   12

#define LED_BLINKING                       111
#define DEAD_STATE                         112


// [ End   ] Global Değişkenler
//PORT A
#define LED1 PIN_A5
#define RS485_ReceiveTransmit PIN_C5

// [End  ] PIN Tanimlamalari
#endif


Kesme 'de ne gibi değişiklikler yapmam gerekiyor. Önerilerinizi bekliyorum.