UART HABERLEŞME INTERRUPT SORUNU

Başlatan volkanunal, 23 Ekim 2017, 10:15:56

volkanunal

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.
Primum nil nocere

JOKERAS


void UART_RxStart(void) {


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

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



volkanunal

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.
Primum nil nocere

volkanunal

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..
Primum nil nocere

MrDarK

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
Picproje Eğitim Gönüllüleri ~ MrDarK

volkanunal

Primum nil nocere

JOKERAS

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.


volkanunal

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.
Primum nil nocere

volkanunal

Şö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?
Primum nil nocere

JOKERAS




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.







volkanunal

#10
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.
Primum nil nocere

volkanunal

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
Primum nil nocere

JOKERAS

#12
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.




JOKERAS

#13
TXE kapatıyorsunuzya.Bir data yolladınız sonra TXE kapattınız.
Bir sonraki data nasıl gidecek?

volkanunal

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.
Primum nil nocere