Sistema a Microcontrollore 16F877A per usi generali
Ultimo aggiornamento: 9/01/2011
Tutto il materiale, dove non diversamente specificato, e' coperto dalla licenza Creative Commons Attribuzione-Non commerciale-Condividi
allo stesso modo.
PROGETTO
Sistema a Microcontrollore 16F877A per usi generali
NOTA: dato che qualcuno ha chiesto,
ecco una breve cross-reference tra
Arduino e 877 System.
Recentemente e' stato realizzato un sistema demo. Maggiori informazioni in
questa pagina.
La scheda CPU, il cui progetto iniziale risale al 2005, presenta queste caratteristiche:
bus dati a 8 bit
bus indirizzi a 4 bit (16 indirizzi, 3 occupati da IDLE, Tastiera, Display))
tutte e 9 le linee analogiche del MCU disponibili su strip
linea INT disponibile su connettore
pin CCP1 e CCP2 disponibili su connettore
tastiera a matrice a 16 tasti collegabile, + 4 tasti sdoppiati on-board
display alfanumerico LCD collegabile (interfaccia a 4 od 8 bit), con controllo luminosita' automatico e contrasto manuale
porta seriale con MAX232 on-board / In alternativa porta USB con bridge USB-Seriale FT232BL on-board
porte SPI e I2C disponibili su connettore (nella versione specifica)
alimentazione 12-24VCA, 15-30VDC
uscita ausiliaria 5V + 12V (1A max in totale)
Utilizzando dei buffer 74HC574 sono disponibili fino a 104 linee di I/O, indirizzabili a gruppi di 8.
Ognuna delle schede periferiche dispone dell'intero connettore del bus indirizzi. Per "programmare" l'indirizzo hardware di una scheda
e' sufficiente saldare un filo tra l'apposita piazzola presente sul PCB e il pin del connettore riportante l'indirizzo desiderato.
E' inoltre possibile sostituire l'MCU 16F877A sia con il modello successivo 16F887 che con un piu' performante (in termini sia di velocita' che di dotazione hardware) 18F4680.
NOTA 1: nella versione USB, i 3 led aggiuntivi indicano alimentazione del chip USB (verde), trasmissione dati al PC (giallo), ricezione dati dal PC (rosso). NOTA 2: nella versione SPI+I2C, il pin Serial Slave della porta SPI e' condiviso con il pin 6 del connettore analogico. NOTA 3: sebbene sia possibile sostituire il 16F877A con il 16F887 o il 18F4680, alcune funzioni evolute di queste MCU non
saranno disponibili. A meno che non si ricerchi un vantaggio puramente economico o di dotazione di memoria e clock (18F4680),
l'MCU originale e' (ovviamente) la piu' integrata nella piattaforma hardware. NOTA 4: tutte le schede del sistema sono realizzate in singola faccia, con eventualmente dei jumpers sul lato
componenti in caso di necessita'. In questo modo e' possibile realizzare le schede facilmente anche a livello "casalingo".
Se si intendesse eseguire la produzione delle schede a livello industriale, si consiglia di utilizzare una configurazione a
4 strati con piano di massa. NOTA 5: nella versione 2.4 (USB+SPI+I2C) i pin del bus indirizzi S1,S2,S3 sono stati spostati da RC3,RC4,RC5 a
RE0,RE1,RE2. Occorre modificare di conseguenza le definizioni nel firmware. Inoltre, l'integrato U10 e' stato sostituito
dal gruppo Q2-R40-R41.
La scheda backplane fornisce i connettori - per un massimo di 10 periferiche - dei bus Dati e Indirizzi, dei segnali
di controllo e dei comandi PWM. Le linee dati ed indirizzi sono portate a massa con delle resistenze da 100K.
La scheda e' progettata in modo da poter essere montata sopra alla scheda CPU con dei distanziali standard.
NOTA: le linee dati ed indirizzi sono gia' portate a massa o VDD nella scheda CPU e/o nelle periferiche, quindi
si possono tralasciare le 3 reti resistive o nella scheda CPU o nella scheda Backplane.
La sezione I/O e' composta da due moduli, uno per l'output ed uno per l'input:
La scheda di output possiede 8 uscite a rele' pilotate tramite fotoaccoppiatori. I valori attualmente inseriti nel circuito
prevedono l'utilizzo di rele' a 9V con alimentazione in ingresso alla scheda a 12V, ma e' ovviamente possibile utilizzare
altre combinazioni (tipicamente tra 5 e 24V) adattando di conseguenza i valori.
La scheda di input dispone di 8 ingressi fotoaccoppiati. I valori delle resistenze di ingresso sono da calcolare in base
alle tensioni in gioco ed al tipo di fotoaccoppiatore utilizzato. In particolare, per gestire ingressi in tensione alternata
e' sufficiente sostituire i fotoaccoppiatori TLP523-2 con degli altri modelli bidirezionali, ad esempio il KB824 della
Kingbright. Ogni linea di ingresso/uscita dispone di un led indicatore per il controllo visivo del funzionamento.
La sezione Display e' disponibile in alternativa al display LCD, ed e' anch'essa composta da due moduli:
Un modulo contiene tutta la logica di controllo, ed e' in grado di gestire fino a 8 digit di display, oppure un numero inferiore di digit piu'
dei led discreti. Sono presenti allo scopo 3 connettori identici per il dato a 8 bit (JP5,JP6,JP7) e due separati per la selezione (JP8,JP9),
connessi in modo da fornire le prime sei linee di selezione su JP8 e le ultime due su JP9.
NOTA: questo display richiede due linee di indirizzo, una per il dato e l'altra per la selezione del digit.
La sezione Switcher e' composta da un generatore PWM in grado di fornire, nella sua configurazione attuale, fino a 4A in corrente
continua, con un ingresso in tensione alternata a 36V (di potenza adeguata) ed un'uscita compresa tra 0 e 40V.
In serie al generatore e' presente un ponte a MOS, con cui e' possibile invertire la polarita' della tensione in uscita, generando anche delle
onde quadre o delle sinusoidi quantizzate. Al lato basso del ponte puo' essere collegato uno shunt resistivo di valore adeguato alle misure
da effettuare (qualora non si intendesse utilizzare questa possibilita', occorre cortocircuitare i pin del connettore JP7).
Al connettore JP9 dovrebbe invece essere collegato un carico resistivo di valore adeguato a mantenere sempre un minimo di corrente circolante
nel sistema. In caso non venisse collegato alcun carico a tale connettore, il sistema potrebbe funzionare in modalita' discontinua.
Il condensatore C14 e' stato aggiunto per poter gestire in modo separato la stabilizzazione della tensione continua rispetto a quella alternata.
Infatti, mentre per stabilizzare la continua si puo' collegare direttamente il positivo del condensatore al pin 1 di JP9, se si vuole generare
una tensione alternata tale condensatore distorce eccessivamente il segnale. In caso sia necessario poter generare entrambi i tipi di tensione,
occorrera' quindi gestire il collegamento del condensatore al rail positivo dell'uscita tramite un rele'.
NOTA: lo switcher puo' essere utilizzato con la massa di potenza sia collegata che scollegata alla massa del sistema. Il jumper JP10
ha questa funzione. Ovviamente se si intende misurare tensione o corrente dello switcher senza che le due masse siano connesse,
occorrera' utilizzare un sensore Hall, un fotoisolatore, o altri sistemi di misura isolati, non presenti sulla scheda stessa.
Per applicazioni di potenza fino ad 1A, tuttavia, verifiche sperimentali hanno stabilito che il collegamento delle masse e la misura
non isolata comportano un disturbo sull'alimentazione relativamente basso.
Il firmware completo del sistema non e' fornito. Questo perche', essendo il sistema progettato per usi generali, possono essere implementate molte funzioni
differenti.
Vengono invece rese disponibili le porzioni di codice utili al pilotaggio delle varie schede. Per ottenere un sistema funzionante, occorrera' creare le
routines di controllo generali (vedere ad esempio la demo nella apposita sezione).
Tutto il codice, come di consueto, e' ampiamente commentato. Per eventuali dubbi, fare riferimento alla sezione PICLinux.
Firmware base - mod 27/11/2009. NOTA: la precedente release del firmware conteneva un bug relativo all'utilizzo della macro ADDLW nella gestione interrupts.
L'ordine degli operandi nella macro non e' Literal,Register ma Register,Literal. Di conseguenza il tempo di ciclo era fisso a
circa 13ms qualsiasi fosse l'impostazione, e i registri all'indirizzo puntato dai literal venivano resettati ad ogni overflow
del timer. (questo succede quando si scrive codice troppo di fretta)
Timer
Contiene la gestione dei timer di sistema.
Nella configurazione riportata sono utilizzati un timer a 16 bit (sistema) ed uno a 8 (generazione AC). E' anche presente un
timer software utilizzabile per operazioni particolarmente lente (impostato a 500ms).
Il tempo di ciclo e' impostato a 5ms, valore che si consiglia di non superare per poter gestire il display in modo adeguato. NOTA: il secondo timer a 8 bit e' utilizzato per la generazione del PWM, quindi non e' disponibile per altre operazioni.
Le routines presenti sono:
Timer_Init: Inizializza variabili e registri, ed attiva il timer di sistema.
I/O
Tutte le routines di lettura/scrittura dei bus dati ed indirizzi, nonche' delle altre linee di controllo, sono contenute in
questa sezione.
Nel file include sono presenti tutte le definizioni necessarie alla configurazione dei pin del microcontrollore, ed anche gli
indirizzi hardware delle varie periferiche (ovviamente modificabili a seconda del caso).
Le routines presenti sono:
IO_Init: Inizializza variabili e registri, azzera il contenuto dei buffers di uscita;
IO_SETADD: Imposta indirizzo periferica sul bus;
IO_CLRADD: Riporta in Idle il bus indirizzi;
IO_CLK: Da un colpo di clock sul pin CK. La durata dell'impulso e' di 1μs con un clock di sistema di 20MHz;
IO_WRTDATA: Scrive un dato all'indirizzo indicato. Chiama da sola le altre routines necessarie all'operazione;
IO_RDDATA: Legge un dato dall'indirizzo indicato. Chiama da sola le altre routines necessarie all'operazione.
Display
La gestione del display 7segmenti impiega ben 30 bytes di RAM. Di questi, due bytes vengono utilizzati per il controllo,
8 (in due variabili da 4 ciascuna) memorizzano il dato attualmente presente sul display, e gli altri 20 sono utilizzati
per visualizzare messaggi a scorrimento. E' stata scritta cosi' perche' il messaggio puo' essere composto al volo in base
alle scelte dell'utente, e questo rende difficile utilizzare dei semplici puntatori. Se si intende utilizzare la EEPROM o
la FLASH per memorizzare i messaggi, conviene utilizzare i puntatori e leggere di volta in volta la porzione di memoria
desiderata. Al posto di 20 bytes se ne occupano solo 2 o 3.
Nel file include relativo e' anche presente la mappa dei caratteri.
Le routines presenti sono:
Disp_Init: Inizializza variabili e registri e disattiva tutti i digit;
Disp_Write: Scrive sul display il dato in sincronia con il digit attivo;
Disp1_Shift: Esegue lo scorrimento delle scritte sul display 1, utilizzando il contenuto degli appositi registri;
Disp_Bcd: dato in ingresso un valore BCD, restituisce il valore da visualizzare sul display.
Questo driver gestisce un display alfanumerico standard LCD (tipo HD44780), e contiene tutte le routines di base per la gestione:
Disp_Init: Inizializza variabili e registri, avvia display e attiva retroilluminazione (FlowChart);
Disp_WrCmd: Invia al display un comando;
Disp_WrData: Invia al display un carattere;
Disp_SetAdd: Invia al display la posizione del cursore;
Disp_WaitBF: Attende che il display si liberi (utilizzo interno);
Disp_Wait: Ritardo 16 cicli (utilizzo interno).
Anche in questo caso, nel file include relativo e' presente la mappa dei caratteri.
NOTA: e' in sviluppo un driver per display grafici con controller tipo T6963C Toshiba.
Keyboard
Contiene la gestione dei pulsanti.
Nella configurazione riportata sono gestiti solo i 4 pulsanti presenti sulla scheda CPU, ma la logica di comando e' identica
per gli altri 12.
Le routines presenti sono:
Keyb_Init: Inizializza variabili e registri;
Keyb_Read: Aggiorna lo stato di tutti i pulsanti. Sono presenti un controllo anti rimbalzo e la ripetizione del
tasto se lo si mantiene premuto.
Questo driver gestisce tutti e 16 i pulsanti, e con un minimo di modifica e' possibile utilizzarlo per gestire combinazioni
differenti, tipo 4x3, 2x2, 2x4, ecc... Le due routines presenti sono le stesse del driver precedente, ma ovviamente i bytes
occupati sono di piu' (FlowChart).
PWM
A questa sezione appartengono tutte le funzioni base per la gestione della scheda Switcher, sia in DC che in AC.
La frequenza del PWM e' impostata a 78,12KHz, valore per cui e' stata ottimizzata la scheda.
Le routines presenti sono:
PWM_Init: Inizializza variabili e registri, ed attiva la generazione del PWM a zero;
PWM_ACPos: Imposta il ponte sulla polarita' positiva dell'onda sinusoidale;
PWM_ACNeg: Imposta il ponte sulla polarita' negativa dell'onda sinusoidale;
PWM_ACClr: Azzera l'uscita AC;
PWM_DCPos: Imposta il ponte sulla polarita' positiva dell'uscita in continua;
PWM_DCNeg: Imposta il ponte sulla polarita' negativa dell'uscita in continua;
PWM_Set: Imposta il valore del duty cycle AC nei registri appositi;
PWMD_Set: Imposta il valore del duty cycle DC nei registri appositi;
Questa sezione del firmware e' stata posta in pagina 3 per motivi di suddivisione funzionale della memoria programma. Ovviamente
nulla vieta di metterla in pagina 0, 1 o 2. NOTA: la gestione della seriale avviene senza l'utilizzo degli Interrupts. E' possibile modificare il firmware in
modo da attivarli, ma con questo sistema la velocita' e' comunque sufficiente per gestire la EEPROM. Con un tempo di ciclo
di 5ms, ad esempio, si legge una cella in circa 10ms, e si scrive in circa 30ms.
Le routines presenti sono:
Ser_Init: Inizializza variabili e registri, ed attiva ricezione seriale;
Ser_Comm: Gestione comunicazioni seriali (lettura, scrittura, ping), da inserire nel ciclo principale (FlowChart);
Ser_Reset: Gestione timeout comunicazione, da chiamare in modo lento (almeno 100ms);
E2_Read: Lettura dato da memoria EEPROM;
E2_Write: Scrittura dato su memoria EEPROM;
Le operazioni previste sono:
Lettura: Lettura in modo sequenziale di tutta la memoria;
Scrittura indirizzo 1 byte: Scrittura di una singola cella di memoria su MCU con EEPROM fino a 256 bytes;
Scrittura indirizzo 2 bytes: Scrittura di una singola cella di memoria su MCU con EEPROM oltre i 256 bytes;
dalla directory src-local, quindi tornare alla directory superiore e lanciare il software con il comando ./PIC-232
oppure ./PIC-232 -? per avere l'elenco dei parametri da riga di comando.
Schermata principale del software di comunicazione
Main
Ciclo principale di base. Contiene la gestione degli interrupts, l'init delle varie funzioni, la gestione della generazione
AC ed i cicli veloce/lento.
Come dovrebbe essere chiaro dal codice, il ciclo cosi' come e' non fa altro che inizializzare il sistema e restare in loop.
Gli autori non si assumono alcuna responsabilita' per eventuali danni di ogni tipo che possano essere causati dall'utilizzo del materiale qui' presente.