Newsgroup: it.hobby.elettronica.digitale
Titolo: Disabilitare il trasmettitore RS485 nell'interrupt

In una classica RS485 multidrop, ogni nodo deve diligentemente 
disabilitare la sezione di trasmissione del transceiver per evitare di 
bloccare l'intero bus, subito dopo la fine della trasmissione.
 
Ho un micro con UART integrata composta da uno shift-register ed un 
registro dati di trasmissione. Non appena abilito la trasmissione, mi 
scatta un interrupt in cui posso scrivere nel registro dati della UART 
il primo byte da trasmettere. Siccome è il primo byte, esso passa subito 
nello shift-register per la trasmissione vera e propria. Subito dopo lo 
start bit, scatta un altro interrupt perchè il registro dati si è 
liberato. In questo secondo interrupt vado a scrivere nel registro dati 
il secondo byte da trasmettere.
Dopo i primi due interrupt consecutivi, i successivi scatteranno ad una 
cadenza di 10/B (10 considerando 1 bit di start, 8 bit di dati e 1 bit 
di stop e supponendo B il baudrate).
Fin qui mi sembra un meccanismo abbastanza comune a tutti i micro dotati 
di UART.
 
Sarebbe carino poter disabilitare il trasmettitore del transceiver RS485 
alla fine della trasmissione dell'ultimo byte. Purtroppo, però, questo 
evento non genera alcun interrupt (infatti l'interrupt di trasmissione 
scatta prima che il byte precedente sia stato completamento trasmesso, 
cioè troppo presto per disabilitare la trasmissione).
L'unica soluzione da me trovata è aspettare un tempo di circa 10/B 
nell'ISR di trasmissione dell'ultimo byte, per dare il tempo allo 
shift-register di svuotarsi. Dopo posso disabilitare la trasmissione 
della UART e del transceiver.
 
Quella pausa nell'ISR di un tempo pari a 10/B mi dà tremendamente 
fastidio. Avete qualche altra idea geniale che mi sfugge?

 fastidio. Avete qualche altra idea geniale che mi sfugge?
 
Che micro è?
 
Piccio.

 ...Avete qualche altra idea geniale che mi sfugge?
 
Una soluzione può essere quella di far rientrare nell'Rx il dato ed
usare l'interrupt di ricezione per disabilitare il buffer.
Se è una RS485 half-duplex è possibile.
 
Piccio.

fastidio. Avete qualche altra idea geniale che mi sfugge?
 
Una tecnica è scrivere un byte dummy tipicamente 0 dopo la scrittura dell'ultimo
byte valido, in modo da 'girare' il bus quando il carattere precedente è già
uscito.
 
Attenzione che se la UART del µC ha una FIFO i caratteri in buffer possono
essere anche più di uno e allora dovranno esserlo anche i dummy.
 
 
--
ciao
  Stefano

Il Fri, 08 Jun 2012 00:11:39 +0200, pozz ha scritto:
 
non so che micro usi, sull'atmega ci sono due tipi di interrupt in 
trasmissione. Il data register empty e il txcomplete. Io per "girare" la 
485 nell'ultimo byte del pacchetto uso il primo e non ho problemi. Se 
vado a vedere con l'oscilloscopio il DE commuta perfettamente dopo 
l'ultimo bit. 


 Che micro č?
 
Un 16 bit della Fujitsu, famiglia 16LX.
 
-- 
 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it
 
 
 

 Se è una RS485 half-duplex è possibile.
 
In realtà si tratta di un bus a 4 fili, quindi niente echo.
 
Però l'idea non è malvagia per i bus a 2 fili.


 essere anche più di uno e allora dovranno esserlo anche i dummy.
 
Ovviamente.


 fastidio. Avete qualche altra idea geniale che mi sfugge?
 
Invece di fare un delay nell'ISR che è una cosa proprio ignobile, puoi 
armare un timer per farti scattare un altro interrupt e quando scatta, 
nell'isr del timer, spegnere il TX.
 
-- 
  _|/ Francesco Sacchi - Develer S.r.l.
   |\
http://www.develer.com/
 - 
http://www.bertos.org/
 

 l'ultimo bit. 
 
Strano, l'interrupt di "data register empty" dovrebbe scattare quando il
byte precedente č ancora in trasmissione. Disabilitare qui la trasmissione
del transceiver dovrebbe comportare un errore, o almeno l'invio di un
byte errato.



Avevo stesso problema con dei Fujitsu (MB90F54x).
In uno risolto facendo eco sull' RX prima di trasmettere
l' ultimo carattere. Se non puoi farlo, purtroppo
puoi solo usare uno dei timer interni per generare un
interrupt e girare la direzione, oppure (brutto) se
hai dei pull up sulla linea differenziale, gira la
direzione in TX solo quando il segnale di TX va basso
e metti in three-state il driver quando il segnale TX va
alto.
 
AA.
 
 
 

 Per l'idea non malvagia per i bus a 2 fili.
 
 
Sovente si usa un monostabile esterno che disabilita l'output dopo un
tempo prefissato di inattività della linea.
Questo impone delle temporizzazioni comuni per tutte le stazioni.
Tanto vale usare un timer del micro: lo fai partire in concomitanza
dell'interrupt per l'ultimo carattere e la sua uscita la utilizzi
direttamente per il controllo tri-state.
Il fatto di avviarlo in concomitanza con la trasmissione del chr e di
utilizzare l'uscita dedicata ti permette di non dover appesantire il
software.
A tutti gli effetti, un monostabile retriggerabile.
 
Piccio.

 nell'isr del timer, spegnere il TX.
 
Ad averne uno libero, di timer.  Vedrò cosa si può fare.
 
 
 
 

 alto.
 
Perchè dici brutto? Sicuramente si può perdere qualcosa in velocità,
ma con baudrate "normali" non dovrebbero esserci problemi.
 
Tra l'altro è una tecnica utilizzata in uno standard automotive (non
ricordo quale) per realizzare una "specie di CAN", cioè avere un bit
dominante (0) ed uno recessivo (1), su una RS485.
 
 


E comunque vorrebbe dire fare una modifica hw (bisognerebbe collegare il 
TX del transceiver a massa e la direzione al TX della UART del micro).
 
 


Insomma, non vuoi proprio fare nulla!
Non modifichi l' hardware, non hai timer dedicati, non puoi fare eco....
Hai almeno un timer di sistema a disposizione?
Se si', potresti abbassare il tick a 100/500us e
usarlo come prescaler per timer software, uno dei quali
usato per per girare la direzione :-)
AA.
 
 
 

 usato per per girare la direzione :-)
 
Infatti � la mia prima idea... volevo capire se ce ne fosse un'altra.
 

Ovviamente.
 
Mica tanto...
 
Invece  mi sa che se vedi uno start bit successivo dipende proprio da questo,
fai delle prove con caratteri diversi in uscita per vedere quanti ne tiene il
buffer FIFO.
 
 
 
--
ciao
  Stefano

 buffer FIFO.
 
Da quello che ho capito io, la mia FIFO � formata da un solo byte, il 
registro dati in trasmissione.

registro dati in trasmissione.
 
Se usi un AVR � cos�, e quel metodo a me funziona.
 
 
--
ciao
  Stefano

 Se usi un AVR � cos�, e quel metodo a me funziona.
 
Evidentemente perch� nell'AVR l'ISR di "registro dati vuoto" scatta 
*prima* dello start bit del successivo byte.
 

 Se usi un AVR � cos�, e quel metodo a me funziona.
Non tutti usano gli AVR :-)
E comunque gli AVR (Mega) hanno il bit TXC (Transmit complete)
che rende suplfluo l' uso di un dummy byte :-)
 
AA.
 
 

 Un 16 bit della Fujitsu, famiglia 16LX.
 
provato a tirare giu' il TXE quando sale il TDRE dell' ultimo byte ?
(e fare partire un timer con interrupt, che scatti poco dopo il bit
stop).
 
uart dovrebbe terminare correttamente l' ultimo byte, fino al bit stop,
poi fermarsi;  poi arriva il tuo timer e disabiliti il driver rs485.
 
 
-- 
saluti
  lowcost
 
 

poi la linea in idle per tutto il tempo.
 
Ieri sera ho controllato la cosa dal momento che in collaudo c'è una macchina
che usa quel sisitema di comunicazione.
 
Quello che si vede con un oscilloscopio a memoria è un 'glitch' di qualche
decina di nS sulla linea al momento che il MAX485 si gira, però questo non
influisce sul protocollo di comunicazione perchè la stringa inizia con <STX> =02
e finisce con <ETX>=03 e il BCC.
 
Quindi se sono già arrivati un ETX e il BCC successivo, un eventuale altro 0FFH
verrà ignorato, lo sarebbe comunque perchè la comunicazione avviene in caratteri
ASCII e 0FFH non è un ASCII valido.
 
Inoltre la linea a quel punto non è più impegnata e il dispositivo può
cominciare subito a rispondere sul TXD  (comincia ad elaborare la stringa appena
dopo l' <ETX>)  indipendentemente dal fatto che la parte RX stia credendo di
ricevere un carattere ingannata dal falso start bit.
 
Quindi credo che la soluzione con un 'dummy' per girare il bus qui funzioni
anche perchè il protocollo lo permette, ignorando eventuali caretteri spuri.
 
 
 
--
ciao
  Stefano


Sì, è la soluzione che mi hanno proposto anche altri in questo thread. 
Dovrebbe funzionare. L'unico problema, come dicevo, è che non ho timer 
completamente liberi, devo provare (lo so, ancora) a riutilizzare 
qualcuno che uso per altro.
 
 

 anche perchč il protocollo lo permette, ignorando eventuali caretteri spuri.
 
Infatti, se il protocollo lo permette č una soluzione praticabile, anche 
se lo chiamerei piů un workaround che una soluzione.
 

 qualcuno che uso per altro.
 
non e' rimasto nessun output compare libero di un counter free run ?
e usare ADC o SPI come timer ?
 
 
-- 
saluti
  lowcost