PIC interupt

Zuffa Jan ZuffaJ na cgc.sk
Čtvrtek Červenec 24 16:35:01 CEST 2014


Zdravim,

piatok sa blizi tak by som rad nacrtol problem s ktorym uz par vecerov zapasim
a neviem ho vyriesit. Ide o PIC16F648 a UART v asynchronnom mode. Data zo serioveho portu sa citaju
v interupte a spracovavaju v hlavnej slucke
Vsetko funguje ako ma, pokial nezahltim UART vacsim poctom paketov (trebars
10 bez prestavky prejde, vacsi pocet uz nie. Velkost RxBuff je 16 bajtov a v interupte
je osetrene pretecenie.

Pakety su velke 4-5 bajtov velke zakoncene 0x0D
V hlavnej slucke sa dookola cita RxBuff pokial dojde k naplneniu (RxDone == 1)

Pre jednoduchost som hlavnu slucku minimalizoval takze vypada nejak takto

while (1)
{
	BYTE bBuffer[RX_BUFF_SIZE];

	UART_ RecvData (bBuffer);
	__delay_ms(300);
	CLRWDT()  // nastaveny na 2.5 sekundy
}

Pokusmi som zistil, ze sa program zacykli v interupte, pravdepodobne kazdym hodinovym cyklom
sa opatovne vyvola interupt co nedovoluje hlavnej slucke pokracovat v spracovani.
Skratka program sa zasekne a WatchDog resetuje procesor. Ked dam CLRWDT() do interuptu
procesor sa nezresetuje ale hlavna slucka sa nevykonava.

Otazka je, ako sa dostat z tohto stavu? Detekovat v interupte ze sa nespracovavaju prijate
data je jednoduche, nic co som vyskusal ale nezabralo

Tu je rutina interuptu:
(Tx sa pouzije iba pri starte procesora aby som videl ze doslo k resetu)

void interrupt trx_int(void) {

// RECEIVE BUFFER
    if ((RCIF == TRUE) && (RCIE == TRUE))                                           // PIR1 register
    {
            if (OERR == TRUE)
            {                                                                       // overrun, reset UART
                CREN = FALSE;                                                       // disable UART
                CREN = TRUE;                                                        // re-enable UART
                RxRecv = 0;
            }
            else
            if (FERR == TRUE)                                                       // framing error (break?)
            {
                RxRecv = 0;
            }
            else
            {
                RxBuffer[RxRecv] = RCREG;		//global variable
                if(RxBuffer[RxRecv] == 0x0D)
                {
                   RCIE = 0;
                   RxDone = 1;
                }

                RxRecv++;
                
                if (RxRecv >= RX_BUFF_SIZE)                                             // beyond buffer boundary  wrap to begin
                {
                    RxRecv = 0;
                    RCIE = 1;
                    RxDone = 0;
                }
            }
    }
// TRANSMIT BUFFER UNTIL EMPTY
    if ((TXIF == TRUE) && (TXIE == TRUE))                                           // PIR1 register
    {
        if(TxSent < TxXmit)
        {
            bX = TxBuffer[TxSent];
            TxSent++;
            if (TxSent >= TxXmit)                                                    //last byte sent, disable interrupt from TX
            {
                TXIE = 0;
                TxXmit = 0;
                TxSent = 0;
            }
            TXREG = bX;
        }
    }
}
BYTE UART_RecvData(BYTE *bData)
{
    BYTE bCnt;
    BYTE bX;

    if(RxDone == 1)
    {
        for(bCnt = 0; bCnt < RxRecv; bCnt++)
        {
            bData[bCnt] = RxBuffer[bCnt];
        }
        bX = RxRecv;
        RxRecv = 0;
        RxDone = 0;
        RCIE = 1;
        
        return bX;
    }
    else
    {
        return 0;
    }
}


Další informace o konferenci Hw-list