Picproje Elektronik Sitesi

DERLEYİCİLER => MikroC - PIC => MikroC dsPIC/PIC24/PIC32 => Konuyu başlatan: volkanunal - 23 Ekim 2017, 10:15:56

Başlık: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 23 Ekim 2017, 10:15:56
Merhabalar herkese , pic24fj128ga010 kullanarak pc ile haberleşme yapmaya çalışıyorum.Normal bir şekilde veri basma ve veri alma işlemini yapabiliyorum.Ancak kurduğum rx interrupt'ına sadece 2 kez giriyor , 2den fazla girmiyor , flagları izlediğim de normal gözüküyor

init ettiğim kısım
void UART1Init(const unsigned long int BAUDRATE)
{
    rxBufRdPtr = rxBufWrPtr = &rxBuffer[0]; // Initialize the pointers
    txBufRdPtr = txBufWrPtr = &txBuffer[0];
     unsigned long int BAUDRATEREG = (((SYSCLK/2)+(8ul*BAUDRATE))/16/BAUDRATE-1);
    U1BRG = BAUDRATEREG; // set up baudrate
    U1MODE = 0; // clear mode register
    U1MODEbits.BRGH = 16;  //divider is 16
    U1STA = 0; // clear status
    U1MODEbits.UARTEN = 1; // enable UART
    U1STAbits.UTXEN = 1; // enable reansmit
    _U1RXIF = 0; // clear interrupt flag
UART_RxStart();

}


Interrupt enable kurduğum fonk
void UART_RxStart(void)
{
    IEC0bits.U1RXIE=1;
   
}

void _ISR_NO_AUTO_PSV _U1RXInterrupt(void)
{
    IFS0bits.U1RXIF=0;
    LATA=0xff;
     
}


Çağırdığım service routine içerisinde led yaktırıyorum  sadece 2 defa giriyor bu kısım içerisine.
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: JOKERAS - 23 Ekim 2017, 12:15:02


void UART_RxStart(void) {


    IFS0bits.U1RXIF = 0;  //False İnterrupt.
    IEC0bits.U1RXIE = 1;
   
}

False interrupt gibi.
Kodunuzu yukarıdaki gibi değiştirip deneyin.


Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 08:58:59
Alıntı yapılan: JOKERAS - 23 Ekim 2017, 12:15:02

void UART_RxStart(void) {


    IFS0bits.U1RXIF = 0;  //False İnterrupt.
    IEC0bits.U1RXIE = 1;
   
}

False interrupt gibi.
Kodunuzu yukarıdaki gibi değiştirip deneyin.




Dediğiniz şekilde yaptığımda haberleşme donuyor  , Örnek vermek gerekirse while(1) içerisinde veri basıyorum , interrupt geldiğinde kitleniyor.
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 09:17:14
Sorun çözüldü aynı sorun ile karşılanlar için ekleme yapayım

void _ISR_NO_AUTO_PSV _U1RXInterrupt(void)
{IFS0bits.U1RXIF=0;
    char c=U1RXREG;
}

Burada U1RXREG okuma yapmak gerekiyormuş  , okuma yapmadan sanırım reg doluyor ve işlemi yapmıyor..
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: MrDarK - 24 Ekim 2017, 09:20:57
Alıntı yapılan: volkanunal - 24 Ekim 2017, 08:58:59
Dediğiniz şekilde yaptığımda haberleşme donuyor  , Örnek vermek gerekirse while(1) içerisinde veri basıyorum , interrupt geldiğinde kitleniyor.

Volkan; genelde usart konusunda interrupt'ın gelmemesi veya usart'ın donması bazı donanımsal errorler sebep olabiliyor. Bu flagler clear edilmeden yeni bir data alımı yapamıyor. Tahminim senin sorunun da bunun gibi birşeye benziyor, aşağıda liste olarak belirttim. Değilsede aklında bu error'ler yer tutsun mutlaka bir gün başına gelecektir :)

- Framing Error
- Parity Error (Parity kullanımı aktif ise)
- Overrun Error

Ayrıca ara ara da üreticinin kullandığın chip ile ilgili yazdığı errata dosyalarını da okumakta fayda var :)

10. Module: UART
The Receive Buffer Overrun Error Status bit, OERR (UxSTA<1>), may set before the UART FIFO has overflowed. After the fourth byte is received by the UART, the FIFO is full. The OERR bit should set after the fifth byte has been received in the UART Shift register. Instead, the OERR bit may set after the fourth received byte with the UART Shift register empty.
Work around
After four bytes have been received by the UART, the UART Receiver Interrupt Flag bit, U1RXIF  (IFS0<11>) or U2RXIF (IFS1<14>), will be set, indicating the UART FIFO is full. The OERR bit may also be set. After reading the UART Receive Buffer, UxRXREG, four times to clear the FIFO, clear both the OERR and UxRXIF bits in software.
Affected Silicon Revisions = A2
Kaynak = http://ww1.microchip.com/downloads/en/DeviceDoc/80471b.pdf
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 09:44:25
Teşekkler @MrDarK  abi :) Dikkate alacağım.
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: JOKERAS - 24 Ekim 2017, 11:52:16
volkanunal,


Aynen öyle oluyor.Donanımsal yapıların veri giriş çıkışlarını,Registerlerini
özellikle kontrol etmek gerekiyor.
MrDark'ın söylediği Errorlar da olacaktır.
Kodu yazarken Önce hata kontrolleri yapılır,sonra veri okunur.
Over,Frame gibi Errorlarda da RX Buffer okunmalı.


Registeri Atama yapmadan Sadece Okumak bile Bufferi boşalttır.
RXREG; yazdığınızda da RX buffer okunmuş olur.



False interrupt için önerdiğim kısmı kalsın.
Onu yapmadan RX interrupt'ı Enable yaptığınız anda RXIF logic 1 olup İnterrupt Rutinine zıplar.
Eğer Frame,Over,Party hatası vermeden geçerse Korsan bir veri ile karışı karşıya kalırsınız.

Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 12:16:26
Alıntı yapılan: JOKERAS - 24 Ekim 2017, 11:52:16
volkanunal,


Aynen öyle oluyor.Donanımsal yapıların veri giriş çıkışlarını,Registerlerini
özellikle kontrol etmek gerekiyor.
MrDark'ın söylediği Errorlar da olacaktır.
Kodu yazarken Önce hata kontrolleri yapılır,sonra veri okunur.
Over,Frame gibi Errorlarda da RX Buffer okunmalı.


Registeri Atama yapmadan Sadece Okumak bile Bufferi boşalttır.
RXREG; yazdığınızda da RX buffer okunmuş olur.



False interrupt için önerdiğim kısmı kalsın.
Onu yapmadan RX interrupt'ı Enable yaptığınız anda RXIF logic 1 olup İnterrupt Rutinine zıplar.
Eğer Frame,Over,Party hatası vermeden geçerse Korsan bir veri ile karışı karşıya kalırsınız.

Teşekkür ederim katkılarınız için.
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 15:29:00
Şöyle bir sorunum var şimdi de ,

TX interrupt yapımı şu şekilde kurdum
void _ISR_NO_AUTO_PSV _U1TXInterrupt(void)
{   
  if (txBufRdPtr != txBufWrPtr)                 
    {
     U1TXREG = *txBufRdPtr++;
    IFS0bits.U1TXIF = 0;
     LATAbits.LATA1=1;
   if(txBufRdPtr > &txBuffer[SIZE_TxBuffer-1])
            txBufRdPtr = &txBuffer[0];             
    }
    else
     IEC0bits.U1TXIE = 0;                   
     
}

Veri basma kısmım şöyle
void WriteTxBuffer(unsigned char TxByte)         
{
    *txBufWrPtr++ = TxByte;
 
    if (txBufWrPtr > &txBuffer[SIZE_RxBuffer - 1]) 
        txBufWrPtr = &txBuffer[0]; 
 
      UART_TxStart();
}



While içerisinde çağırıyorum
WriteTxBuffer('A');
        WriteTxBuffer('B');


Tek sefer interrupt içerisine girip A'yı gönderiyor , B gönderme işlemini yapmıyor neden olabilir acaba?
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: JOKERAS - 24 Ekim 2017, 15:46:46



Kullandığınız işlemcinin Registerlerini bilmiyorum.
Transmit buffer'ın boşaldığını-gittiğini belirten bir Flag olmalı.




Ayrıca TXIF her halukarda Sıfırlanmalı.
Else bloğundaki TXEnable ile İf bloğundaki TXIF yer değiştirip deneyin.






Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 15:49:16
Alıntı yapılan: JOKERAS - 24 Ekim 2017, 15:46:46


Kullandığınız işlemcinin Registerlerini bilmiyorum.
Transmit buffer'ın boşaldığını-gittiğini belirten bir Flag olmalı.




Ayrıca TXIF her halukarda Sıfırlanmalı.
Else bloğundaki TXEnable ile İf bloğundaki TXIF yer değiştirip deneyin.

Evet şu an çalışıyor , teşekkür ederim.
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 15:57:00
Benim kurduğum mantıkta , yeni data yok ise uart tx interrupt'ını disable etmekti ve o şekilde yaptığım da çalışmadı .Sizin dediğiniz şekilde yaptığımda çalıştı ama mantığıma tam yatmadı şunları sorayım

Farklı data -> veriyi bas ->uart inter disable et
Aynı data -> tx interrupt flag  temizle

Benim mantığım

Farklı data->veriyi bas -> flagları temizle
Aynı data -> uart inter disable et


Benim mantığıma göre tek sefer veriyi bastıktan neden ikinci sefer veriyi basmıyor , debug ettiğimde else düşme işlemi de olmuyor farklı data gelirse. Kafam karıştı :) Biraz daha çalışmam gerek sanırım
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: JOKERAS - 24 Ekim 2017, 16:01:03
Yeni verimi?Yeni veri olup olmadığınımı yoksa farklı veri olup olmadığınımı sorguluyorsunuz?
İnterrupt, Farklı farksız veriye bakmaz,İnterrupt oluşmuşmu oluşmamışmı ona bakar.
Diyelimki Aynı veriyi yolladınız, ne olacak Fark yok diye TXIF sıfırlanmadan TXE kapanmış olacak.


Bu mesajı,mesajınızın editlenmemiş haline yazmıştım.



Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: JOKERAS - 24 Ekim 2017, 16:07:51
TXE kapatıyorsunuzya.Bir data yolladınız sonra TXE kapattınız.
Bir sonraki data nasıl gidecek?
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 19:19:45
WriteTxBuffer fonk içerisinde Tekrardan start ediyordum zaten , farklı data mı onu kontrol ediyor orada ki işlemde.Else bloguna düştüğünde disable oluyor ancak her WriteTxBuffer da tekrar enable ediyordum.
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 24 Ekim 2017, 19:25:21
Sanırım şöyle bir durum oluşuyordu  , interrupt meydana geldiğinde flag 1 'e çekiliyordu benim mantığımda farklı bir veri olması gerekiyor ki if içerisine girsin  veriyi bassın ve flagı temizlesin ancak bu if içerisine giremediği için flag 1'e de kalıyor ve temizlenmediği için interrupta izin vermiyordu.
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: JOKERAS - 25 Ekim 2017, 15:29:42



volkanunal,sizin işlemcinin pdf'ni inceliyorum gözlerim ağrıdı:)


FiFo(İlk giren İlk çıkar) Buffer var.
Fifodan sonra Shift register var.
Yani Fifoya yüklenen Paralel değeri/leri seri şekilde Shift edip dışarıya gönderiyor.


Burada bazı şartlar var.UTXBF ve TRMT.
UTXBF Fifo bufferın dolu olup olmadığını gösteriyor.
TRMT ise Shift edilen yani gönderilen Data varmı diye kontrol ediyor.


mesela 'A' karakterini yollayalım.


TXREG = 'A'; dediğimiz anda ISR isteği gelmiş İnterrupt bayrağı set olmuş demektir.
Interrupt açıksa Pc İnterrupt rutinine zıplayacak.
İnterrupt Bayrağını temizledik çıktık.'A' Fifo bufferda daha gitmedi bekliyor...
Peşinden 'B','C', 'D' yolladık.Buffer Full doldu.
Bundan sonra göndereceğiniz veriler uçar gider yalan olur.


Onun için Veri gönderimi yapmadan önce Fifo Buffer dolumu yer varmı diye kontrol etmek gerekiyor.
Bunu da UTXBF Regi yapıyor.


UTXBF 0'mı?Evet! Fifo'da hala boş yer var.
UTXBF 1'mi?Evet! Fifo dolmuş,Bloke durumda beklemek gerekiyor.


Fifodaki Verileri kızağa almadan önce veri kaydırması varmı yokmu?
Bunu da kontrol etmek gerekli.
Bunu kontrol eden Reg ise TRMT.


TRMT 1'se Kızak boş,0 ise Kızak dolu.Yani bir önceki veri hala shift ediliyor.
Fifodaki datalar,TRMT 0'a düştüğü her an  'A' 'B' 'C' 'D' şeklinde Kızağa,yani Shift registere düşer.


TXEN = 1; demeden önce
TRMT Registerini sorgulamak gerekiyor.


while(TRMT == 0)   //Shift işlemin bitmesi bekleniyor.
;                 //Sfiht bitti,kızak boş.


      TXEN = 1;    //Yeni Veri Kızağa düştü.Shift başladı.




while(UTXBF == 1); //Fifo Full,Boş yer yok,mecburen bekleyecek.     
     
      TXREG = Ch;  // Sıradaki gelsin Fifo'da boş yer var.


Bu kodlar bloke çalışır,zaten Donanımla çalışılıyorsa Bloke çalışmadan işin
içinden çıkmak zor.Ya bloke çalışmak yada Time Out sayıp karar vermek gerekir.


TXIE ile TXEN farklı Registerler.Kafa karıştırmasın!


Şimdi bunu niye böyle yapmış bu vatandaşlar.
Veri gönderim ve alımlarında hata olmasın,veya en az hata ile işi kurtarmak ve hızlı bir şekilde
yollamak için yapmış olabilirler.



Aslında bu iş için İnterrupt'a gerek yok,interrupt'sızda olur.
Sonuçta Donanım bu.Donanımı İnterrupt ile kontrol ederek işlemciyi meşgıl etmemişler.
Bu sayede işlemci gerekli gereksiz yere zaman harcamamış oluyor.
Bir kaç Flag kontrol edilerek Donamım kontrol edilmiş.
Aksi takdirde Aynı kontrolleri ana programda yapmak gerekecek ve bu da özellikle kod büyüdükçe
Zaman farkı oluşturacaktı.








Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: volkanunal - 25 Ekim 2017, 21:13:18
Teşekkürler hocam :) zahmet ettirdim yordum sizi :) @JOKERAS
Başlık: Ynt: UART HABERLEŞME INTERRUPT SORUNU
Gönderen: JOKERAS - 26 Ekim 2017, 11:24:48
Rica ederiz efenim:)