Convertitore automatico di baud rate utilizzando ATTiny2313

Sprite_tm riesce a scoprire il baud rate utilizzando un ATtiny2313 e la scheda FT232. Il firmware assume 8 bits di dati, nessuna parità e 1 bit di stop (8N1). Questo è molto utilizzato tra le porte seriali e quindi dovrebbe funzionare bene, anche se alcuni dispositivi utilizzano diverse configurazioni. Rilasciato sotto GPLv3, il software è fornito in formato esadecimale (codice macchina)

Lo schema della scheda è molto semplice. L'hardware UART dell'ATTiny232 è collegato all'FT232, che fornisce alimentazione all'ATTiny2313. Gli unici componenti restanti sono un condensatore e un cristallo. Non è possibile fa partire l'ATTiny senza dei condensatori sui "crystal pin" ed i 20 MHZ ad un Vcc di 3.3V ma il nostro progettista non ha mai avuto problemi. La CTS-line "dice" al PC di aspettare con l'invio di altri bit fino a che il dispositivo ha inviato i precedenti.

convertitore automatico ATTiny2313

Il software utilizza un timer a 16-bit. Il timer 1 esegue la temporizzazione principale e questo timer a 16 bit viene esteso a 32bits, in modo che il firmware possa rilevare anche baudrates più bassi di 110 baud. La funzionalità "input capture" di questo timer è utilizzata per misurare quanto tempo il segnale ricevuto è basso. Il suo interrupt è utilizzato per avviare la routine UART che riceve un byte quando l'autobauding è riuscito. Il timer viene usato anche per mandare i segnali al dispositivo quando un byte è ricevuto dal PC.

Se vuoi hackerare un'apparecchiatura con microprocessore, la prima cosa che di solito dovresti fare dopo aver distrutto il case ed aver identificato tutti i frammenti è cercare una porta seriale. Nonostante il tipo di apparecchiatura (a base Linux, WinCE, qualche modello di RTOS forse persino senza SO), la maggioranza di essi ha una porta seriale destinata al debugging.

La maggior parte di queste porte presentano anche delle info utili persino con firmware non-debug, così risulta un modo facile e simpatico per imparare di più sul dispositivo. Trovare la porta seriale può essere, tuttavia, un po' problematico. Dopo avere trovato i pin giusti, hai ancora bisogno di sapere su quale "rate" opera il baudrate. Questo di solito significa provare ogni singolo rate sul PC ricevente finché non sei fortunato. Avere un oscilloscopio digitale può semplificare un po’ le cose, ma anche se ne possiedi uno, non è divertente accenderlo e tentare di dedurre il baudrate da una traccia che si riesce a catturare. Come puoi aver dedotto dal resto del mio sito, ho sezionato la mia parte di apparecchiature in passato.

/*
Firmware for an auto-baudrate-detector and -convertor implemented in an
ATTiny2313.
(C) 2009 Jeroen Domburg
*/

#include "io.h"
#include "uart.h"
#include "timer.h"

#include "avr/interrupt.h"
#include "util/delay.h"
#include <stdio.h>

//Sort tickBuff, from smallest to largest.
static void sortList(void) {
	//Plain ole bubble sort, on so little values that shouldn't take too long :)
	char swapped=1;
	long t;
	while (swapped) {
		swapped=0;
		for (char x=0; x<TICKBUFFLEN-1; x++) {
			if (tickBuff[(int)x]>tickBuff[(int)x+1]) {
				t=tickBuff[(int)x+1];
				tickBuff[(int)x+1]=tickBuff[(int)x];
				tickBuff[(int)x]=t;
				swapped=1;
			}
		}
	}
	//Ok, done :)
}

//Calculate 1/baudrate from the contents of tickBuff.
static long calculateDelay(void) {
	unsigned long proposedDelay;
	unsigned long finalDelayAcc=0;
	//Ok, tickBuff is now filled. Sort it first.
	sortList();
	//Sanity check:
	//The largest time measured can be at most 9 bit-times
	//(1 startbit + 8 zero-valued databits). Refuse if this
	//isn't true by a long shot. (take 15x for a good margin)
	if ((tickBuff[0]*15)<tickBuff[TICKBUFFLEN-1]) return -1;
	//Take the smallest value as the initial proposed delay.
	finalDelayAcc=tickBuff[0];
	proposedDelay=tickBuff[0];
	//Now, figure out the delay.
	for (char x=1; x<TICKBUFFLEN; x++) {
		unsigned long rest=tickBuff[(int)x];
		char n=0;
		while (rest>proposedDelay) {
			n++;
			rest-=proposedDelay;
		}
		//Round up -> if tickbuff=proposedDelay*4.6, n=5.
		if (rest>(proposedDelay/2)) n++;
		
		//Ok, we now know how many bit-times the delay was. We can
		//derive a better bit-time estimation from that. Add that estimation
		//to the accumulative estimations.
		finalDelayAcc+=(tickBuff[(int)x]/n);
	
		//Calculate the new proposed delay
		proposedDelay=finalDelayAcc/(x+1);
	}
	//Ok, proposedDelay now is the best estimate of bit-time we have.
	return proposedDelay;
}

int main(void) {
	initIo();
	timerInit();
	sei();
	while (1) { //eternal loop
		
		//Do autobaud.
		tickPos=0; //Reset tickBuff pointer so tickBuff will be filled by ICP int
		//Sleep until we've collected TICKBUFFLEN samples.
		while (tickPos!=TICKBUFFLEN) ;
		//Ok, samples are in. Calculate delay.
		long delay=calculateDelay();
		if (delay!=-1) { //Only if calculation succeeded.
			long baudRate=F_CPU/(unsigned long)delay;
			//Tell user the baudrate.
			serialPutChar('<');
			serialPutInt(baudRate);
			serialPutChar('B');
			serialPutChar('>');
			serialPutChar('\r');
			serialPutChar('\n');
			uartBase=delay;
			
			//Ok, we're synced. Wait till it's probable we're out of sync
			//(much rx errors) and then resync.
			//Until then, just re-send everything we receive.
			do {
				//Reset error & char counter
				swUartRxErrs=0;	swUartRxChars=0;
				//Wait for 8 chars
				while (swUartRxChars<8) {
					if (uartShouldRecv) {
						//We should receive :)
						int b=swUartRecv();
						uartShouldRecv=0;
						swUartRxChars++;
						if (b==-1) {
							//Error in reception :/
							swUartRxErrs++;
						} else {
							//Reception OK :)
							serialPutChar(b);
						}
					}
				}
				//If more than 2 errors in the 8 bytes, resync.
			} while (swUartRxErrs<3);
		}
	}
}

La procedura per la maggior parte di esse includeva la routine descritta sopra per trovare i parametri corretti di porta seriale. Dopo avere fatto ciò per l’ennesima volta , ho deciso di voler automatizzare il processo: se io stesso potessi dedurre il baudrate usando solamente il mio PC o un oscilloscopio, non c'è nessuna ragione per cui un microcontroller non potrebbe fare lo stesso.

Questo progetto e' veramente molto interessante ed utile. La funzionalita' di auto-detect del baud-rate su linea seriale e' generalmente disponibile solo su strumentazione di fascia medio-alta, ma questo progetto consente praticamente a tutti di beneficiare di questa comoda feature.

Scarica subito una copia gratis

Una risposta

  1. Avatar photo Fabrizio87 14 Dicembre 2011

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend