Comunicazione seriale con codifica Manchester

La codifica Manchester permette la trasmissione dei dati e del clock in un unico pattern seriale, per questo viene utilizzata frequentemente nelle trasmissioni digitali in Radio Frequenza a basso costo. E' una particolare tecnica di modulazione bifase (BPSK, Binary Phase Shift Key) che consente di compattare al massimo il volume di dati trasmessi e di inglobare il segnale di sincronismo nello stesso stream dati. La codifica manchester è definita, inoltre, autosincronizzante ed è stata sviluppata come riporta anche il nome, dai ricercatori dell'Università di Manchester. Ecco come funziona e come implementarla su un PIC.

LA CODIFICA MANCHESTER

Il formato Manchester codifica un dato digitale non come livello di tensione statico,  bensì come  transazione da livello alto a livello basso per un ”1” logico e da livello basso a livello alto  per uno  “0” logico. In figura 1 è riportato  un tipico stream dati codificato Manchester.

Figura 1. Una stringa codificata Manchester ed i relativi bit

Figura 1. Una stringa codificata Manchester ed i relativi bit

Il valore della componente continua di uno stream in codifica Manchester è sempre nullo e questo consente di decodificare facilmente i dati oltre che ad implementare un controllo di errore senza troppe difficoltà. Prima della decodifica vera e propria, il segnale viene trattato da un circuito detto data slice che provvede a generare dei livelli di tensione compresi tra 0 ed il positivo di alimentazione. Un data slice è sostanzialmente un comparatore rigenerativo a valle di un filtro passa basso come mostrato in figura 2.

Figura 2. Un circuito data slice di pre-decodifica

Figura 2. Un circuito data slice di pre-decodifica

La costante di tempo del filtro passa basso dovrà essere dimensionata in modo da essere maggiore del periodo del segnale di ingresso. Il  vero  processo di  decodifica  viene fatto  con  un microcontrollore  mediante un algoritmo  che associa “0” o “1” alle varie transazioni del segnale di ingresso.

Gli “Illegal codes”

Per quanto visto, nella codifica Manchester ciascun bit è espresso come una transazione 1-0 o 0-1 quindi a ciascun bit dato corrisponde una coppia di livelli. Ad esempio la stringa dati 0-1-1-1-1-0-0-1 viene codificata come 01-10-10-10-10-01-01-10. Questo porta a due conseguenze fondamentali: la prima è che per la trasmissione di un bit fisicamente ne devono essere trasmessi due e questo comporta una occupazione di banda maggiore; la seconda è che solo le coppie 01 e 10 codificano rispettivamente i bit 0 e 1 quindi le coppie 00 e 11 (cosiddette “illegal codes”) possono essere  utilizzate per il controllo  di  errore nella trasmissione. Nella presente trattazione verrà illustrato come trasmettere una stringa di dati su una linea RS232 ad 8  bit  dati,  utilizzando  la codifica Manchester pertanto potrà essere utilizzata la stringa “00-00-11-11” come controllo start/stop. Si noti che questa stringa ha la particolarità di avere una componente continua nulla ed una sola transazione da 0 a 1.

Come includere  i Manchester  bit nella comunicazione RS232

Per sfruttare la comunicazione RS232 al fine di trasmettere/ricevere dati in codifica Manchester, verrà utilizzata la configurazione 8-N-2 ovvero 8 bit di dati, nessuna parità e 2 stop bit. Il bus seriale sarà quindi caratterizzato da sequenze del tipo:

…MMSDDDDDDDDPPSDDDDDDDDPPMMMM….

dove M indica che il bus non è utilizzato (livello logico “1”), S è lo start bit (livello logico “0”), D è il bit dati, P è lo stop bit (livello logico “1”). Per quanto esposto finora in un byte RS232 verranno quindi codificati 4 bit Manchester.

IMPLEMENTAZIONE SU PIC

Verrà adesso illustrato come inviare e ricevere dati codificati  Manchester  sfruttando  la  RS232 su un microcontrollore PIC. Le routine sono espresse in linguaggio C per il compilatore PICC di CCS. Si supponga di  dover trasmettere il  dato  esadecimale 0x41.  In binario tale dato corrisponde alla stringa 0100 0001 e poiché i bit vengono trasmessi a partire da quello meno significativo, lo stream dati sarà 1000 0010. I 4 bit  meno  significativi del dato  saranno quindi  trasmessi come  1000  e tale  stringa  codificata Manchester diviene: 10-01-01-01 (ovvero 0xA9). I 4 bit  più  significativi vengono  trasmessi come 0100 che,  codificati,  divengono  01-01-10-01 (ovvero 0x9A). Per la trasmissione di 0x41 saranno dunque sufficienti due chiamate della putc():

putc(0xA9); //lower nibble
putc(0x9A); //upper nibble

La codifica vera e propria può essere fatta dalla routine SEND_DATA il cui codice è riportato nel listato 1.

void SEND_DATA(BYTE txbyte)
{
int i,j,b,me;
b = txbyte;
for (i=0; i<2; i++) {
    me = 0;
    for (j=0 ; j<4; j++) {
     me >>=2;
     if (bit_test(b,0) )
      me |= 0b01000000; // 1->0
     else
      me |= 0b10000000; // 0->1
     b >>=1;
    }
   putc(me);
 }
}
Listato 1

La fine di una trasmissione viene segnalata inviando il byte 0xF0 ovvero la stringa di controllo 00-00-11-11 vista precedentemente. La trasmissione di tale stringa viene fatta semplicemente con la chiamata putc(0xF0). Per quanto riguarda la decodifica, il data slice viene fatto via software quindi vengono decodificati i bit. La routine che provvede a questo è la DECODE_DATA il cui codice è riportato nel listato 2.

BYTE DECODE_DATA(BYTE encoded)
{
BYTE i,dec,enc,pattern;
enc = encoded;
if (enc == 0xf0)
return 0xf0;
dec = 0;
for (i=0; i<4; i++) {
dec >>=1;
pattern = enc & 0b11;
if (pattern == 0b01) // 1
bit_set(dec,3);
else if (pattern == 0b10)
bit_clear(dec,3); // 0
     else
return 0xff; // illegal code
enc >>=2;
}
return dec;
}
Listato 2

GESTIONE DELLA CODIFICA MANCHESTER IN MIKROBASIC

Anche il popolarissimo mikroBASIC prevede la gestione della comunicazione dati con codifica Manchester su RS232. Le routine disponibili sono sette:

Man_Receive_Config

Prepara il PIC alla ricezione di un segnale. I parametri da specificare sono la porta e il pin sul quale arriverà il segnale seriale. Nel caso si verifichino errori in ricezione  è  necessario richiamare  la  funzione Man_Receive_Init al fine di ristabilire la sincronizzazione.

Man_Receive_Init

È  analoga alla precedente, ma necessita solo della porta di comunicazione come parametro. Il pin di ricezione è sempre il pin 6.

Man_Receive

Ritorna il byte opportunamente  decodificato. Come parametro richiede un byte che viene utilizzato come flag di errore (vale 255 in caso di errori in ricezione).

Man_Send_Config

Prepara il  PIC per una trasmissione dati.  Richiede come parametri la porta e il pin usato come output. Il baud rate è fissato a 500bps.

Man_Send_Init

È  analoga alla precedente, ma necessita solo della porta di comunicazione come parametro. Il pin di uscita è per default il pin 0 della porta specificata. Il baud rate è fissato a 500bps.

Man_Send

Invia il byte specificato come parametro

Man_Synchro

Ritorna   la   metà   della   lunghezza   di   un   bit Manchester. La lunghezza è data in multipli  di 10 microsecondi. Come esempio di applicazione delle routine mikroBASIC, il listato 3 riporta un semplice programma per la trasmissione di  un messaggio in codifica Manchester.

program RF_TX
dim i as byte
dim msg as string[20]
main:
  msg = “Hello World!”
  PORTB = 0 ‘ Initialize port
  TRISB = %00001110
  ClearBit(INTCON, GIE) ‘ Disable interrupts
  Man_Send_Init(PORTB) ‘ Initialize Manchester sender
  while TRUE
   Man_Send($0B) ‘ Send start marker
   Delay_ms(100) ‘ Wait for a while
   for i = 1 to Strlen(msg)
    Man_Send(msg[i]) ‘ Send char
    Delay_ms(90)
  next i
  Man_Send($0E) ‘ Send end marker
  Delay_ms(1000)
 wend
end.
Listato 3

Il messaggio deve essere delimitato dai codici 0x0B e 0x0E. Il listato 4 riporta invece la routine di ricezione del messaggio. L’hardware a cui fare riferimento è illu- strato in figura 3.

Figura 3. I moduli RF, RR3 e RT4

Figura 3. I moduli RF, RR3 e RT4

Il micro utilizzato sia dal trasmettitore che dal ricevitore è un PIC16F877A ed il dato viene inviato in RF  a 433MHz utilizzando un trasmettitore  RT4 e ricevuto  da un  modulo  RR3. Il dato ricevuto viene visualizzato sul un diplay LCD alfanumerico.

program RRX
dim error, ErrorCount, temp as byte
main:
  ErrorCount = 0
  TRISB = 0
  CMCON = 7
  Lcd_Init(PORTB) ‘ Initialize LCD on PORTB
  Lcd_Cmd(LCD_CLEAR)
  Man_Receive_Config(PORTA,3) ‘ Configure and synchronize receiver
  while true do
    Lcd_Cmd(Lcd_FIRST_ROW)
    while true do ‘ Wait for the start marker
      temp = Man_Receive(error)
      if temp = $0B then
        break
      end if ‘ We got the starting sequence
      if error then ‘ Exit so we do not loop forever
        break
      end if
  wend
  do
    temp = Man_Receive(error) ‘ Attempt byte receive
    if error = true then
       Lcd_Chr_Cp(63) ‘ ASCII for ‘?’
       Inc(ErrorCount)
       if ErrorCount > 20 then
         Man_Receive_Init(PORTA)
        ‘ alternative:
        ‘ temp = Man_Synchro
         ErrorCount = 0
       end if
     else
       if temp <> $0E then ‘ Don’t print the end marker on LCD
       Lcd_Chr_Cp(temp)
       end if
     Delay_ms(20)
      end if
    loop until temp = $0E
  wend
end.
Listato 4

 

 

Una risposta

  1. Maurizio Di Paolo Emilio Maurizio 12 luglio 2016

Scrivi un commento