[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