Jak nejrychleji přepínat směr u MAX481(TTL-485)

Zdravím kolegové,

potřeboval bych vylepšit(zrychlit) přepínání směru toku dat přes převodník 485 na TTL a naopak u MAX481. Do převodníku je přiveden RX, TX a DE, který ovládá směr toku. Při DE = 1 je převodník ve vysílacím režimu a při DE = 0 je v příjímacím režimu. Takže povětšinu času je DE = 0 a přijímám data a pouze když chci něco odeslat, tak přepnu DE = 1 a mohu vysílat. Problém ale je, kdy přepnout DE zpět do nuly. Musí se to provést co nejdříve, aby jsem nepřicházel o data.

První způsob je, že po vložení dat do TXREG hlídám smyčkou TRMT a nepokračuji dál dokud není TRMT = 1. Toto čekání ale neumožňuje provádět jiné operace během vysílání. A když vysílám paket o desítkách bajtů není tato čekací doba zanedbatelná.

Druhý způsob je, že vložím data do TXREG a dělám běžnou rutinu. TRMT pak testuji během čekacích smyček nebo v proceduře MAIN nebo v proceduře přerušení a podle toho nuluji DE. Problém je pak v tom, že DE může být nějakou dobu v 1 a já nestihnu přijmout celou odpověď na odeslaný paket, která přichází hned v zápětí.

Neměl by někdo nápad, jak přepínat DE přímo při odeslání posledního bitu vysílaného paketu?

Díky za rady…

je to sice možné - musíš samozřejmě používat přerušení od TXIF - měl by se nastavovat, když se TXREG vyprázdní - tedy po tom posledním odeslaném bitu - musíš ale taky kontrolovat kdy posíláš ten poslední znak.

Jen tak v ryclosti jsem upravil pro PIC co používám na AVRku - asi by to chtělo trochu doladit, ale pro představu to snad postačí.

[code]//----------------------------------------------------------------------------
// High priority interrupt vector

#pragma code InterruptVectorHigh = 0x08
void
InterruptVectorHigh (void)
{
_asm
goto InterruptHandlerHigh //jump to interrupt routine
_endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerHigh

void
InterruptHandlerHigh ()
{
if (PIR1bits.TXIF)
{
PIR1bits.TXIF = 0; //clear interrupt flag
if(tx_write_index)
{
TXREG=tx_buffer[tx_write_index];
tx_write_index–;
}
else DE=0; //prepne na prijem
}
}

//----------------------------------------------------------------------------

unsigned char tx_buffer[20];
unsigned char tx_write_index;

void main()
{
/* vysilani */
posli_data(tx_buffer,sizeof(tx_buffer));
}

//----------------------------------------------------------------------------
void posli_data(*data,lenght)
{
DE=1; // prepne na vysilani
tx_write_index=lenght;
TXREG=tx_buffer[tx_write_index]; //prvni naplneni TXREG - kazde dalsi obstara obsluha preruseni
}[/code]
ale já být tebou , tak tolik nepospíchám - ono totiž i když ti odejde poslední bit z TXREG, tak to ještě neznamená, že už dorazil k adresátovi a už vůbec ne, že ho stihl jeho USART zpracovat. Nakonec stejně dojdeš na to, že musíš nějaký čas (odvislý od peřnosové rychlosti) počkat. Nehledě na to, že slave musí ten jak píšeš -paket o desítkách bajtů nějak zpracovat a připravit odpověď což taky nějaký čas trvá.

No ale tady jde právě o to, že flag TXIF je nastaven(a provede se přerušení) ještě před odesláním posledního bajtu - Jakmile dojde k přesunu bajtu z TXREG do posuvného registru. Takže bych o poslední bajt vždycky přišel… Přerušení od TXIF už využívám na napnění TXREG bajtem z bufferu.

Jinak nejde mi o čekání na odpověď od slave, ale musím obsluhovat další periférie. Mezitím třeba obsluhuji komunikaci SPI, počítám impulsy od inkrementálních čidel, monitoruji stisk několika tlačítek + ošetření zákmitů a komunikuji s čidly po OneWire. Je toho spousta, co se dá stihnout za uplynutí odesílací doby jednoho bajtu protože taktuji na 64MHz.

Rád bych co nejvíce využíval přerušení a o to mín pak čekací smyčky. Je na to nějaké řešení?

Predpokladám, že problém je v tom že procesor nemá prerušenie od ukončenia vysielania na UARTe. Podobný problém som vyriešil tak, že vysielané údaje som zároveň aj prijímal. V prerušení od RXIF som počítal prijaté (odoslané) bajty paketu a po poslednom bajte som vypol vysielač.

To je tedy dost nepříjemná vlastnost PICů a i když s nimi taky občas dělám tak čím dál víc zjišťuju, že jsem dobře udělal, když jsem se nakonec přiklonil k AVRkům - taky sice mají své mouchy, ale jak to tak sleduju, tak by jeho použití (AVR) zatím řešilo většinu tvých (myslím Notíka)problémů.

Takže zatím nejlepší způsob na který jsem přišel je dát za poslední platný odesílaný bajt jeden neplatný. Tím mi vznikne přerušení přímo po odeslání posledního platného bajtu a já mohu přepnout převodník do přijímacího režimu. Bity neplatného bajtu jsou pak sice vysílány z PICky, ale protože je převodník v přijímacím režimu, nedostanou se na sběrnici RS485. Je ale důležité, aby přepnutí převodníku bylo provedeno co nejrychleji od přerušení, protože se jinak dostane kus start bitu neplatného bajtu na sběrnici. Řeším to blokem příkazů v ASM hned na první pozici v přerušení.

Zatím jsem nepřišel na nedostatky tohoto postupu, takže jsem takhle spokojený.