[elektro] PIC, TRMT

Móczik Gábor pm_levlista at progzmaster.hu
Fri Sep 20 23:55:28 CEST 2013


2013.09.20. 15:42 keltezéssel, Balla Zoltán írta:
> Na de éppen ezzel van a bajom...hogy honnan tudom, hogy a soros port okozott megszakítást, hiszen a
> flag már beállt egybe, tehát akármi is lehet, amit ez a megszakítási vektor szolgál ki!
> Feltételezve, hogy több megszakítás is ide fut be, és a flag vizsgálat döntené el, mi is okozta! De
> itt meg mintha ez nem így menne....
> Persze, lehet azt mondani, mivel a többi periféria nem okozott megszakítást, akkor biztos a soros
> port volta az elkövetője...de ez így vicces szerintem...

Nem tudom, én az általad leírt furcsaságokat soha nem tapasztaltam, de 
lehet hogy a te más típusú procit használsz.

Én úgy csináltam, hogy ha küldeni kellett valamit, akkor beírtam egy 
körbufferbe, inkrementáltam a következő üres hely címét és beállítottam 
egy flag-et, hogy a buffer nem üres, majd 1-re állítottam a TXIE bitet.

Ha a TXREG ekkor pont üres volt (azaz a TXIF már 1 volt), akkor azonnal 
keletkezett egy megszakítás. Ha már folyt a kommunikáció, akkor csak 
kicsit később, amikor üressé vált a TXREG.

A megszakítás kiolvasta a bufferből a következő adatot, inkrementálta a 
következő küldendő adat címét, majd beírta a TXREG-be.
Megnézte, hogy a körbufferben lesz-e még további adat, vagy ez volt az 
utolsó. Ha nem, akkor a TXIE=0 -ra állítással letiltotta hogy következő 
megszakítás keletkezzen.

(mivel már úgysincs mit küldeni, és a TXIF flaget nem tudod törölni csak 
a TXREG írásával, tehát ha nem írod a TXREG-et, akkor folyamatosan a 
megszakításba kerülsz, muszáj a TXIE-t tiltani)


Kb. ennyi az egész, nekem ez évek óta működik többféle PIC-en (csak a 
tx_statust cseréltem ki enum-ra a define helyett az évek folyamán):

#define TX_BUF_SIZE     32
#define TX_BUF_NORMAL   0b00000000  /* buffer contains some data */
#define TX_BUF_EMPTY    0b00000001  /* buffer is empty           */
#define TX_BUF_FULL     0b00000010  /* buffer is full            */

// USART transmit buffer and pointers
persistent volatile unsigned char tx_buf[TX_BUF_SIZE];
volatile unsigned char tx_next,tx_free,tx_stat=TX_BUF_EMPTY;


void usart_putch(unsigned char x)
{
     // blocking wait if circular buffer is full
     while(tx_stat & TX_BUF_FULL) continue;
     // disable interrupt during buffer update
     TXIE=0;
     tx_buf[tx_free]=x;
     tx_free++;
     tx_free&=TX_BUF_SIZE-1;
     // clear buffer empty flag
     tx_stat&=~TX_BUF_EMPTY;
     // if buffer is full now, set flag
     if (tx_free==tx_next) tx_stat|=TX_BUF_FULL;
     TXIE=1;
}

static void interrupt low_priority isr_lo(void)
{
     if (TXIF && TXIE) {
	// normally the buffer is never empty when interrupt fired
         // but disable interrupt if it happen
         if (!(tx_stat & TX_BUF_EMPTY)) {
             // we remove one item, so clear buffer full flag
             tx_stat&=~TX_BUF_FULL;
             TXREG=tx_buf[tx_next];
             tx_next++;
             tx_next&=TX_BUF_SIZE-1;
             if (tx_next==tx_free) {
                 // this was the last item, set buffer empty flag
                 tx_stat|=TX_BUF_EMPTY;
                 // disable further interrupts
                 TXIE=0;
             }
         } else TXIE=0;
     }
}



More information about the Elektro mailing list