Çözüldü: INT_RDA(rs232) kesmesi aktif olduğu anda veri olmasada kesmeye giriyor

Başlatan tekosis, 01 Ağustos 2015, 12:09:14

tekosis

selamün aleyküm hocalarım. aşağıda temel bir devre kurdum. u1 entegresi ilk açılışta ekrandaki bilgileri veriyor bu arada u2 de rda kesmesi pasif durumda. u2 de beş saniye sonra kesmeyi aktifleştirdiğim anda o sırada u1'den veri yollmadığım halde kesmeye giriyor. sanırım u1 den programın başlangıcında ekranda gösterdiğim bilgiler buna sebep oluyor. bu durumu nasıl engellerim?


İlim ilim bilmektir, ilim kendin bilmektir, sen kendin bilmezsin, bu nice okumaktır.

LukeSkywalker


tekosis

evet hocam yazmayı unutmuşum kesmeyi aktifleştirmeden önce şu kodu yazıyorum; bu arada ccs c kullanıyorum.

         clear_interrupt(INT_RDA);
         enable_interrupts(INT_RDA);
         enable_interrupts(GLOBAL);
İlim ilim bilmektir, ilim kendin bilmektir, sen kendin bilmezsin, bu nice okumaktır.

PROTECH_

Multi-Core ,RTX,ThreadX, FreeRTOS, MODBUS  RTOS - Electronic-Hardware -- BERLIN

tekosis

hocam sürekli o şekilde kullanamam iki işlemci arasında karşılıklı haberleşme var. ancak problem kesme aktif edilmeden önceki gelen verilerden kaynaklanıyor gibi. bunu gidermek için kesmeyi aktifleştirmeden önce rx bufferi nasıl boşaltabilirim? onu araştırıyorum. belki ondan olabilir.
İlim ilim bilmektir, ilim kendin bilmektir, sen kendin bilmezsin, bu nice okumaktır.

RaMu

Veri olmadığı halde kesmeye girse de
problem olmayacak şekilde kod yazmak daha iyi olur.

CcsC de int_rda yı kullandığımda böyle bir problem yaşamadım,
aslında yukarıda söylediğim gibi yaptığım için
problem olamadı zaten.

getc();
dediğinde rxbuffer okunuyor, faydası olabilir.

Aslında öncelikle  int_rda ya girdiğini kesinleştirmek lazım,
buna nereden kanaat getiriyoruz.

mesaj birleştirme:: 01 Ağustos 2015, 14:13:26

Birde 18F46k22 de iki tane uart var,
interrupt için hangisi kullanılacaksa-kurulduysa onun kesmesini kullanmak lazım olabilir,
misal #INT_RDA0 şeklinde.
Yine diğer ayarlardada değişiklikler olabilir.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

tekosis

hocam devrede çeşitli ledler ile programın hangi noktada olduğunu kontrol ediyorum aslında u2 de b1 pinine bağlı bir led var bu kesmeye girdiğinde yanıyor, çıktığında sönüyor. burdan takip ediyorum. kafayı karıştırmasın diye elimden geldiğince sade bir şema yayınladım. 

mesaj birleştirme:: 02 Ağustos 2015, 14:50:44

aşağıdaki kodda clear_intterupt(INT_RDA) komutunu asm olarak inceliyorum. bu arada movf komutunun kullanılışı bana tuhaf geldi. FAEh adresinde RCREG1 EUSART receive registeri bulunuyor. anladığım kadarı ile bu register üzerinden bu bayrağı "0" yapmak için registere 0 yüklenmesi gerekiyor. yanlışmıyım?



....................    while(true) 
....................    {         
....................    disable_interrupts(INT_RDA); 
00310:  BCF    F9D.5
....................    output_low(pin_b0); 
00312:  BCF    F93.0
00314:  BCF    F8A.0
....................    clear_interrupt(INT_RDA);  
00316:  MOVF   FAE,W
....................    clear_interrupt(INT_RDA);  
00318:  MOVF   FAE,W
....................    clear_interrupt(INT_RDA);  
0031A:  MOVF   FAE,W



mesaj birleştirme:: 01 Ağustos 2015, 14:51:35

Alıntı yapılan: RaMu - 01 Ağustos 2015, 14:01:24
Birde 18F46k22 de iki tane uart var,
interrupt için hangisi kullanılacaksa-kurulduysa onun kesmesini kullanmak lazım olabilir,
misal #INT_RDA0 şeklinde.
Yine diğer ayarlardada değişiklikler olabilir.
hocam denedim işe yaramadı.
İlim ilim bilmektir, ilim kendin bilmektir, sen kendin bilmezsin, bu nice okumaktır.

RaMu

Henüz datasheet e bakmadım, bakıp doğrularım sonra;
muhtemelen durum şöyledir,
FAEh adresindeki RCREG1 okununca
otomatik olarak uart ın kesme bayrağı pic tarafından siliniyordur,
veya ccsc silindiğini kabul ediyordur.
İşin içine girmeden, manuel bir düzeltme için
@LukeSkywalker hocamızın dediği gibi interrupt bayrağını (RXIF) kendimiz sıfırlarız.
RXIF nerede ise bulunup sıfırlanacak
bit_clear(rxif_nin_bulundugu_register,RXIF);
daha sonra kesme aktifleştirilecek.

MOVF   FAE,W
komutu sadece RCREG1 i okuyor,
Move File (_register) to W
FAE adresindeki değeri W'ya(akümülatöre) kopyala,
(Ayrıca MOVF STATUS registerını etkileyen bir komuttur,
yukarıda bahsettiğim gibi, movf ile bir register okunduğunda
otomatik olarak interrupt bayrağı sildirme gibi bir özelliğide olabilir.)

Olabilir vs. dediğim yerler net bilgi değil,
gerekirse daha sonra bakar netleştiririm.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

sadogan

proteus similasyonunu ve ccs yazılımını bir yerlere yüklersen biraz kurcalayalım.

tekosis

hocalarım şu an inceleme halindeyim. durumu çözemezsem dosyaları yükleyeceğim. ilginize çok teşekkür ederim.
İlim ilim bilmektir, ilim kendin bilmektir, sen kendin bilmezsin, bu nice okumaktır.

tekosis

yardımlarınız için çok teşekkür ederim hocalarım. yönlendirmeleriniz yardımıyla problem halloldu.

sorun OERR - "Receive Overrun Error" hatası imiş. bu durum şundan kaynaklanıyor; diyelimki bendeki gibi iki cihaz haberleşiyor. ama alıcı devre veri beklemiyorken, RDA kesmesi pasifken verici cihaz rasgele bilgiler gönderiyor. bu durumda FIFO tamponu 2 byte dan daha fazla veriye maruz kaldığı için taşıyor, bu hata oluşuyor ve bu hata giderilip, FIFO boşaltılmadan rx bloğu çalışmıyor. bu durumu gidermek için de RCSTAX kayıtçısındaki OERR bayrağı sıfırlanmalı ve CREN biti önce "0" sonra tekrar "1" yapılarak rx modülü resetlenmeli. bu şekilde sistem hatası giderilip normal çalışmaya dönülüyor.

bu durum 18f46k22 data sheetinde "16.1.2.6 Receive Overrun Error" başlığında belirtilmiş.

kullanıdığım kodlar;
#include <18F46K22.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PROTECT                  //Code protected from reads
#FUSES XT

#use delay(crystal=25000000)
#use RS232(baud=4800,parity=N,xmit=pin_C6,rcv=pin_C7,bits=8,stream=PORT1)

#byte PIR1 = 0xF9E
#byte RCREG = 0xFAE 
#byte RCSTA1 = 0xFAB

#define buton_1   pin_d0
#define buton_2   pin_d1

#define evet 1
#define hayir 0

unsigned int      genel_sayac=0;

int1              veri_geldimi=0;

char              gelen_veri[30]      ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char              komut_okey[4] ={'o','k','y','\r'};

#int_rda
void  kesme(void) 
{   
   disable_interrupts(int_rda);   
   output_high(pin_b1);
   veri_geldimi=evet;    
   for(genel_sayac=0;genel_sayac<=29;genel_sayac++)
   {
   gelen_veri[genel_sayac]=getc();
   if(gelen_veri[genel_sayac]=='\r') goto kesme_cikis;
   } 
kesme_cikis:
   genel_sayac=0;
   output_low(pin_b1);
   enable_interrupts(int_rda);
} 
//********************** STRCMP KOMUTU ****************************************
signed int8 strcmp(unsigned char *s1, unsigned char *s2)
{
   for (; *s1 == *s2; s1++, s2++)
      if (*s1 == '\r')
         return(0);
   return((*s1 < *s2) ? -1: 1);
}
//*****************************************************************************
void ram_bellek_kurulum()
{
veri_geldimi=0;
gelen_veri[0]=0;
gelen_veri[1]=0;
gelen_veri[2]=0;
gelen_veri[3]=0;
gelen_veri[4]=0;
gelen_veri[5]=0;
gelen_veri[6]=0;
gelen_veri[7]=0;
gelen_veri[8]=0;
gelen_veri[9]=0;
gelen_veri[10]=0;
gelen_veri[11]=0;
gelen_veri[12]=0;
gelen_veri[13]=0;
gelen_veri[14]=0;

}
//*****************************************************************************
void main()
{
   setup_adc_ports(NO_ANALOGS);
   disable_interrupts(INT_RDA);
   disable_interrupts(GLOBAL); 

   set_tris_b(0x00);
   output_b(0x00);
   set_tris_d(0xff);   
   ram_bellek_kurulum();
//  enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);             
                                                  
   while(true)
   {        
   
   bit_clear(RCSTA1,4);//seri portun rx modülü pasif, reset durumunda tutuluyor.
   disable_interrupts(INT_RDA);
   output_low(pin_b0);
   
      if(input(buton_1)==1)//1 numaralı ledi yakar
         { 
         output_high(pin_b0);//???????????????????????????????????????????????????????????????????
         delay_ms(10);
         while(input(buton_1)==1) {} 
         delay_ms(100);  
         
lmb1yak_tekrar_yollama:            
         printf("l1yk\r");
                 
         bit_clear(RCSTA1,4);//seri portun rx modülü pasif, reset durumunda tutuluyor.
         delay_ms(2);// bu arada 2 byte değeri olan fifo boşaltılıyor.
         bit_clear(RCSTA1,1);//OERR overrun error bayrağı sıfırlanıyor.         
         bit_set(RCSTA1,4);// rx alıcı modül tekrardan çalıştırıldı
         enable_interrupts(INT_RDA);// rda kesmesi aktif edildi
         
         veri_geldimi=hayir;
         while(veri_geldimi==hayir) {}
         disable_interrupts(INT_RDA);
         veri_geldimi=hayir;
         if(strcmp(komut_okey,gelen_veri)!=0) goto lmb1yak_tekrar_yollama; 
         }
         
      if(input(buton_2)==1)//1 numaralı ledi söndürür
         { 
         output_high(pin_b0);//???????????????????????????????????????????????????????????????????
         delay_ms(10);
         while(input(buton_2)==1) {} 
         delay_ms(100);   

lmb1son_tekrar_yollama:   
         printf("l1sn\r");
         
         bit_clear(RCSTA1,4);
         delay_ms(2);
         bit_clear(RCSTA1,1);
         bit_set(RCSTA1,4);                  
         enable_interrupts(INT_RDA);
         
         veri_geldimi=hayir;
         while(veri_geldimi==hayir) {}
         disable_interrupts(INT_RDA);
         veri_geldimi=hayir;
         if(strcmp(komut_okey,gelen_veri)!=0) goto lmb1son_tekrar_yollama; 
         }                    
     }
}
İlim ilim bilmektir, ilim kendin bilmektir, sen kendin bilmezsin, bu nice okumaktır.