Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/ognigiorno.com/wp-content/plugins/math-comment-spam-protection/math-comment-spam-protection.php:1) in /var/www/html/ognigiorno.com/wp-includes/feed-rss2.php on line 8 microcontrollore – OgniGiorno.com https://www.ognigiorno.com insieme tutti i giorni Sun, 29 Apr 2012 20:53:39 +0000 en-US hourly 1 https://wordpress.org/?v=5.8.9 Un’architettura completa https://www.ognigiorno.com/2009/09/08/un%e2%80%99architettura-completa.html https://www.ognigiorno.com/2009/09/08/un%e2%80%99architettura-completa.html#respond Tue, 08 Sep 2009 11:00:29 +0000 http://www.ognigiorno.com/?p=358 Read More »Un’architettura completa]]> Vediamo come realizzare una scheda flessibile e potente utilizzando il PIC16F887. Tramite questa scheda riusciamo a realizzare quasi ogni circuito, basando la struttura su un BUS con cui interfacciare le varie periferiche.
arch

Qui viene presentata l’architettura e descritto il funzionamento di massima. Da qui si può partire poi per la personalizzazione, in base ai desideri di ciascuno.

La mia scelta è stata quella di utilizzare un controllore abbastanza potente, da essere considerata davvero una soluzione universale. Comprato direttamente da microchip spendiamo meno di 3 auro, quindi non considero uno “spreco” quando la realizzazione ci porta a realizzazioni semplici.
Esempi di utilizzo sono i classici ed ormi inflazionati robot, antifurto, centraline di controllo, più o meno tutto, limitatamente alla nostra capacità e voglia di scrivere firmware e pensare a periferiche da collegare.

Lo schema di massima è visibile in figura e mostra una configurazione abbastanza utilizzabile: tastiera e display sono quasi onnipresenti nei nostri circuiti, quindi sono collegati e gestiti direttamente dal controllore. Le altre due porte del processore servono per la realizzazione del BUS e del canale di interrupt. In questo modo realizziamo un BUS multiprotocollo con la gestione di interrupt.

Multiprotocollo perché sono inserite le linee seriali e i2c, ma anche i restanti 4 pin che permettono uno scambio di 4 bit. Ogni connettore al BUS ha inoltre un collegamento ad un diverso pin della porta B che gestisce gli interrupt. busIn questo modo ogni scheda può prevedere un pin di segnalazione e il software sulla mainboard ne riconosce la segnalazione, in base alla posizione.

]]>
https://www.ognigiorno.com/2009/09/08/un%e2%80%99architettura-completa.html/feed 0
Meglio il C o l’assembler? https://www.ognigiorno.com/2009/04/03/meglio-il-c-o-l%e2%80%99assembler.html https://www.ognigiorno.com/2009/04/03/meglio-il-c-o-l%e2%80%99assembler.html#respond Fri, 03 Apr 2009 10:09:38 +0000 http://www.ognigiorno.com/?p=267 Read More »Meglio il C o l’assembler?]]> Questa è una domanda che spesso si pone chi lavora con i controllori e scrive firmware. Vorremmo avere una risposta universalmente applicabile, ma ogni volta che andiamo in una direzione ci torna il dubbio che forse l’altra scelta sarebbe stata la migliore.
Non voglio certo avere la pretesa di dare la soluzione a questo dilemma, mi fa però piacere descrivere la soluzione che ho adottato, che mi sta facendo lavorare molto bene da parecchio tempo, con una buona efficienza nel tempo dedicato alla scrittura del codice. Riporto inoltre alcune informazioni che permettono sicuramente di farsi un’idea migliore e prendere una decisione.

I problemi da affrontare
La scelta non è dettata esclusivamente dal linguaggio in termini di formalismo e sintattico (altrimenti immagino che tutti andrebbero sul BASIC senza troppi dubbi). Le problematiche da affrontare riguardano
– l’ottimizzazione del codice scritto in termini di risorse impiegate (memoria RAM, Program memory, tempi di esecuzione)
– il controllo diretto delle componenti a basso livello (registri, funzionalità speciali,…)
– il controllo diretto sui tempi di esecuzione necessario quando si lavora in real time
– la gestione della memoria
– la riusabilità del codice scritto e la sua portabilità su controllori differenti
– l’ergonomia nella scrittura del codice

Cosa fa un compilatore

“Il compilatore si occupa di tradurre in codice binario (o codice macchina) il programma scritto nel linguaggio che esso interpreta”. Questo è quello che macroscopicamente si associa al concetto di compilatore. In realtà un buon compilatore fa molto di più, soprattutto in relazione a quanto il linguaggio è “distante” dalla macchina. Si parla di generazione del linguaggio, pensando anche alla reale evoluzione storica che hanno avuto i linguaggi di programmazione

  • 1GL (first generation language) è in effetti il codice macchina. Si tratta della rappresentazione binaria che il processore utilizza ed esegue. Nella programmazione dei controllori lo vediamo leggendo i files .hex che trasferiamo sul controllore. Il programma è costituito da una serie di caratteri binari, come descritto nel datasheet del controllore.
  • 2GL (second generation language) di fatto è l’assembler (o assembly) è poco più che una traduzione in codice mnemonico dei comandi binari.
  • 3GL (third generation language) linguaggi di più alto livello solitamente di tipo procedurale (per esempio C o Java). Il compilatore traduce in codice macchina, effettuando operazioni più complesse della semplice traduzione letterale come avviene per i 2GL.
  • 4GL (fourth generation language) si tratta di linguaggi dalla sintassi che tende ad avvicinarsi al linguaggio naturale (SQL ne è un esempio). Lo cito solo per completezza
  • 5GL (fifth generation language). Sono linguaggi di programmazione che utilizzano ambienti grafici o visuali per interfacciarsi col programmatore. Solitamente si basano comunque su linguaggi 3GL o 4GL.

Spesso si può quindi parlare di assembler e codice macchina come se fossero sinonimi.

Si capisce che un linguaggio 3GL porta delle caratteristiche che complicano la traduzione in linguaggio macchina, in particolare, le strutture tipiche di un linguaggio di programmazione:

  • Variabili
  • Tipi di dati complessi
  • Iterazioni (o cicli)
  • Scelta
  • Procedure

Siccome questi linguaggi hanno l’obiettivo principale di mascherare al programmatore la gestione delle risorse a basso livello (gestione RAM e program memory), è il compilatore che si occupa di automatizzare la traduzione.

Ragioniamo per esempio alle variabili. Quando scriviamo un programma in assembler utilizziamo genericamente indirizzi di memoria per apoggiare dei valori. Se non creiamo intrecci, possiamo utilizzare la stessa locazione per scopi differenti in rami diversi del programma. Per comodità ci costruiamo una “mappa” per cui ci è chiaro l’utilizzo di ogni porzione di memoria.
In C ci limitiamo a dichiarare una variabile sapendo quale è il suo scope (la sua visibilità). La gestione della memoria (scegliere quale locazione, decidere con chi può essere condivisa, da quale ramo di codice può essere scritta, ….) è tutte ad opera del compilatore.
Ogni compilatore implementa un suo preciso meccanismo per effettuare tutte queste operazioni. È proprio qui la differenza dei compilatori.

Proviamo a semplificare il lavoro di un compilatore:

  1. Analisi del codice in termini di “albero delle chiamate”. Elenco di tutte le funzioni con le relative dipendenze (chi chiama chi). Utile per vedere le funzioni che convivono e che quindi non possono condividere aree di memoria
  2. Catalogazione di tutti gli oggetti (funzioni) in termini di dimensione del codice e richiesta di memoria.
  3. Analisi dei parametri di input e resultcode.
  4. Creazione della mappa di memoria. Solitamente viene suddivisa in segmenti logici, dedicati a diverse tipologie di esigenza (variabili, parametri, tipi di dati pi lunghi del byte, …)
  5. In caso di limitazioni del compilatore effettua la gestione per mascherare le limitazioni. Ad esempio i processori di fascia bassa della Microchip hanno una limitazione sulla profondità di chiamata delle funzioni (max 2 livelli) il compilatore deve aggirare il problema. Il compilatore picc di HI-TECH si costruisce una jump table che usa per mascherare call/return con coppie di goto.

Per tutte queste gestioni il codice macchina prodotto da un compilatore contiene molte più istruzioni di quelle strettamente necessarie per eseguire le operazioni a basso livello.
Questo è il motivo per cui genericamente si dice “l’assembler è più performante del C”. Ci si riferisce allo strato di funzionalità base che il compilatore introduce, l’overhead prodotto dal compilatore.
Questo è necessario perché un linguaggio 3GL si propone come linguaggio indipendente dalla macchina fisica su cui viene eseguito. Questa “indipendenza” si paga.
Dopo questa semplificata descrizione, riassumo alcune caratteristiche dei due linguaggi:

Linguaggio C

  • è un linguaggio più comodo. Offre una sintassi e una gestione procedurale che ne agevola la scrittura e la lettura da parte dell’uomo
  • è pressoché indipendente dall’hardware sottostante. Attenzione: questo non significhi che TUTTI i programmi scritti in C sono effettivamente indipendenti dall’hardware. E nel caso di firmware per microcontrollori questo lo si vede spesso ed è una dell considerazioni principali nella scelta del linguaggio. A cosa mi riferisco? L’istruzione RB3 = 1; è un comando C, ma se serve per accendere un LED collegato al piedino 3 della porta B del PIC, questa è una conoscenza hardware necessaria per il funzionamento del programma. Quando programmiamo un microcontrollore non vale l’analogia con il computer. In questo caso, infatti, solitamente il programma C interagisce con il sistema operativo e difficilmente abbiamo la necessità di utilizzare direttamente componenti Hardware.
  • La traduzione in codice macchina perde in efficienza
  • Generalmente la scrittura di codice richiede meno tempo

Assembler

  • permette accesso diretto all’hardware
  • è possibile gestire con precisione i tempi di esecuzione di ogni istruzione
  • la programmazione richiede una buona conoscenza del processore su cui il codice viene eseguito
  • richiede molta attenzione e precisione nella definizione delle strutture.

Indipendentemente dal linguaggio, scrivendo firmware sui controllori è necessario avere la conoscenza del processore con cui stiamo lavorando. Per applicazioni più semplici e avendo a disposizione una buona libreria, con il C possiamo facilmente cavarcela anche senza conoscere i dettagli dell’hardware

La mia scelta
Innanzi tutto va tenuto conto che da hobbista utilizzo strumenti non professionali. Non ho intenzione di spendere migliaia di euro quando con un po’ di lavoro in più (si tratta sempre di passione) posso ottenere ottimi risultati gratis.
I miei strumenti sono MPLAB ed il compilatore Picc di HI-TECH versione freeware.
A meno di intervenire pesantemente su parametri di configurazione del compilatore, avere a disposizione compilatori con buona ottimizzazione e avere una conoscenza del compilatore più dispendiosa della conoscenza del processore, ci sono molte operazioni che non sono di fatto possibili in C.
Cito un esempio: le routine di trasmissione seriale. Scritte in C e compilate per i controllori PIC baseline funzionano senza problemi. Compilando lo stesso codice su controllori di fascia diversa, il compilatore cambia i criteri di ottimizzazione (che sono poi legati a effettive differenze hardware) e smettono di funzionare. C’è una spiegazione. Nella comunicazione seriale (bit banging) è richiesta una precisa gestione del tempo. L’overhead introdotto dal compilatore nel secondo caso è tale per cui sarebbe richiesta una ricalibrazione dei ritardi introdotti nel codice.

Abbiamo un’alternativa, la stessa scelta che è stata fatta nel mondo dei computer. Ormai a costi bassi possiamo trovare controllori sempre più potenti, che offrono come funzionalità base quasi tutto quello che serve, con memoria pressoché illimitata. Quindi per far lampeggiare un LED scriviamo un semplice programma in C e lo facciamo girare su un controllore 1 32bit dotato di porta USB, Ethernet, con 32k di program memory, 256k memoria RAM, gestione nativa del BUS I2C e SPI, 32 convertitori A/D, …
Forse è un po’ eccessivo? È comunque una possibilità. Con i computer hanno fatto così!

Io preferisco identificare il processore più adatto allo scopo e dimensionarlo correttamente, disegnare il circuito e dimensionare il tutto in base alle effettive esigenze.
Come linguaggio utilizzo insieme il C e l’assembler: ho costruito una buona libreria di funzioni base in assembler che utilizzo chiamandole da funzioni C. Solitamente il main lo scrivo in C, scrivo in C funzioni che non richiedono particolare ottimizzazione, uso le funzioni assembler e sto sempre attento alla percentuale di risorse utilizzate. Quando sforo, mi tocca sempre convertire in assembler alcune delle funzioni C.

]]>
https://www.ognigiorno.com/2009/04/03/meglio-il-c-o-l%e2%80%99assembler.html/feed 0
Registratore di temperatura https://www.ognigiorno.com/2009/04/01/registratore-di-temperatura.html https://www.ognigiorno.com/2009/04/01/registratore-di-temperatura.html#respond Wed, 01 Apr 2009 07:02:14 +0000 http://www.ognigiorno.com/?p=259 Read More »Registratore di temperatura]]> Il progetto qui descritto è un termometro/orologio con funzionalità di campionatore della temperatura. Il dispositivo funziona stand alone ed ha la possibilità di interfacciarsi via seriale (RS232) con un pc per effettuare il trasferimento dati. Lo stesso collegamento serve per impostare i parametri di configurazione. Il circuito è dotato di RTC (real time clock) con batteria tampone per mantenere l’ora impostata anche in assenza di batteria. La visualizzazione avviene tramite display lcd 2 righe x 16 caratteri.
Nella foto è visibile lo schema a blocchi.

regtemp

Come si può vedere, ho utilizzato il PIC 16F84 come controllore del dispositivo. Questo controlla tramite BUS I2C le tre periferiche attive:

  • RTC: PCF8563 della Philips.
  • Sensore di temperatura: DS1775. Effettua la rilevazione della temperatura impostato alla massima risoluzione. La precisione arriva a 0.0625?C
  • EEPROM seriale utilizzata per la memorizzazione delle informazioni.

regtemperatura

Al controllore è inoltre collegato il MAX232 che si occupa di adattare i livelli per la seriale del computer (converte da TTL del PIC a +/-12v utilizzati dal PC)

Firmware
Il codice che allego è scritto in jal, un linguaggio ormai non più mantenuto. È infatti mia intenzione riscrivere in C (utilizzo il compilatore picc di HI-TECH) tutto il codice.

Ritengo questo progetto interessante anche per la completezza delle periferiche: modificando il programma è possibile utilizzare i dispositivi per qualsiasi altro scopo per cui siano necessari un RTC, un rilevatore di temperatura, un display, la connessione seriale e la EEPROM.

]]>
https://www.ognigiorno.com/2009/04/01/registratore-di-temperatura.html/feed 0
Come pilotare i display LCD tipo HD44780 https://www.ognigiorno.com/2009/03/30/come-pilotare-i-display-lcd-tipo-hd44780.html https://www.ognigiorno.com/2009/03/30/come-pilotare-i-display-lcd-tipo-hd44780.html#respond Mon, 30 Mar 2009 08:12:13 +0000 http://www.ognigiorno.com/?p=254 Read More »Come pilotare i display LCD tipo HD44780]]> Un valido dispositivo di output quando si lavora con i controllori è il display LCD. Ne esistono diversi per dimensioni (numero di righe e lunghezza righe). Quello mostrato nella foto è 2×16, ma l’interfacciamento è lo stesso anche con altre dimensioni. Il protocollo qui descritto (con allegato codice sorgente in C) prevede un interfacciamento di 4 bit di dati (oltre ai 3 di controllo).

hd44780

I collegamenti del display
(Fare comunque riferimento alla documentazione tecnica del produttore. Nel mio caso si tratta di Hitachi HD44780)

Pin Nome
1 Vss
2 Vdd
3 Contrasto (collegare a massa)
4 RS
5 RW (di solito a massa)
6 E
7 D0 (n.c. per interfacciamento a 4 bit)
8 D1 (n.c. per interfacciamento a 4 bit)
9 D2 (n.c. per interfacciamento a 4 bit)
10 D3 (n.c. per interfacciamento a 4 bit)
11 D4
12 D5
13 D6
14 D7

Dalla tabella vediamo che per utilizzare un collegamento a 4 bit dobbiamo utilizzare i 4 più significativi del display, il register Select (RS) e il pin Enable (E)

Protocollo di comunicazione

  1. Portare RS a 1 per invio dati, 0 per invio di comando
  2. Portare E a 1
  3. Valorizzare i 4 bit più significativi
  4. Portare E a 0
  5. Portare E a 1
  6. Valorizzare i 4 bit meno significativi
  7. Portare E a 0

In caso di interfacciamento a 8 bit, i dati vanno inviati tutti in una volta
Inserire un ritardo di almeno 2ms tra ogni operazione

Inizializzazione del display
Appena acceso, il display, va inizializzato, inviando i comandi base. Primo fra tutti la selezione del modo di comunicazione a 4 o 8 bit.
La sequenza esatta è visibile dal codice sorgente scaricabile qui

Inviare caratteri al display
Dopo l’inizializzazione è possibile inviare i caratteri trasmettendo il loro valore ASCII.
Il display incrementa automaticamente la posizione, quindi non è necessario fare nulla tra un carattere ed il successivo

Il codice allegato
Il codice che allego l’ho testato con controllori PIC (!6f506, 16F84, 16F689 e 16F887), ma è utilizzabile con tutti i controllori che hanno almeno 6 piedini disponibili.

]]>
https://www.ognigiorno.com/2009/03/30/come-pilotare-i-display-lcd-tipo-hd44780.html/feed 0
Routine I2C per controllori PIC implementate in C https://www.ognigiorno.com/2009/03/28/routine-i2c-per-controllori-pic-implementate-in-c.html https://www.ognigiorno.com/2009/03/28/routine-i2c-per-controllori-pic-implementate-in-c.html#respond Fri, 27 Mar 2009 23:08:42 +0000 http://www.ognigiorno.com/?p=245 Read More »Routine I2C per controllori PIC implementate in C]]> Lavorando con i PIC possiamo aver bisogno di utilizzare il protocollo I2C dovendolo implementare a basso livello in C o in assembler (bit banging). Questo capita se lavoriamo con un controllore di fascia base che non offre nativamente tale funzionalità.

Purtroppo mi sono trovato in questa necessità e le routine fornite di esempio con il compilatore PICC di Hitech (il compilatore che utilizzo di solito) non sono riuscito a farle funzionare. Non so se perché errate, o se per colpa dell’ottimizzazione che nella versione freeware non è garantita.

Lavorando a basso livello è infatti avere la massima ottimizzazione.
Pazienza: dovendo lavorare con il 16F506 per il mio progetto, le ho dovute riscrivere. Il file i2c.h è scaricabile qui e contiene il codice che implementa le funzioni di base in linguaggio C.
Va notato l’utilizzo del registro TRIS. Essendo un registro in sola scrittura nel 16F506, per valorizzarlo ho utilizzato una variabile di appoggio in cui memorizzo il valore (m_TRIS). Con processori differenti è necessario modificare la gestione del registro. Per questo motivo nel file si trova nella parte iniziale e modificabile agendo sulle definizioni di SCL_IN, SCL_OUT, SDA_IN e SDA_OUT.
Ecco un esempio di come utilizzare la libreria:
i2c_init();

i2c_start();
i2c_tx(0xA2);
i2c_tx(0x02);
i2c_tx(0x00);
i2c_stop();

L’esempio riportato mostra come scrivere un valore nella EEPROM. La lettura avviene in modo analogo:
i2c_start();
i2c_tx(0xA2);
i2c_tx(0x02);

i2c_start();
i2c_tx(0xA3);
Putch (i2c_rx(1));
Putch (i2c_rx(1));
Putch (i2c_rx(0));
i2c_stop();

Questo codice invece legge dalla memoria e trasmette i valori letti sulla seriale utilizzando le librerie RS232 qui descritte

Con questa libreria è possibile quindi controllare tutti i dispositivi I2C (RTC, memorie EEPROM, …)

]]>
https://www.ognigiorno.com/2009/03/28/routine-i2c-per-controllori-pic-implementate-in-c.html/feed 0
Il sensore di temperatura DS1775 https://www.ognigiorno.com/2009/03/26/il-sensore-di-temperatura-ds1775.html https://www.ognigiorno.com/2009/03/26/il-sensore-di-temperatura-ds1775.html#respond Thu, 26 Mar 2009 12:42:38 +0000 http://www.ognigiorno.com/?p=240 Read More »Il sensore di temperatura DS1775]]> Il DS1775 prodotto da Dallas Semiconductors è un sensore di temperatura/termostato che può essere utilizzato nei nostri circuiti, pilotato da un controllore tramite il protocollo I2C.
Le applicazioni sono molteplici: termometro digitale, termostato, controllo di temperatura interna al circuito, registratore di temperatura, …
Purtroppo è disponibile solo nel package SOT23, quindi per utilizzarlo va necessariamente realizzato un circuito stampato abbastanza preciso. Suggerisco il metodo con il ferro da stiro e carta patinata.
dspr1775

Come tutti i dispositivi I2C, dobbiamo ragionare per locazioni di memoria: scriviamo o leggiamo valori da indirizzi precisi. Questo sensore di temperatura utilizza 4 locazioni differenti:
00h – contiene il valore della temperatura. Il valore è a 12 bit, quindi dobbiamo effettuare due letture

i2c_put_read_address(temp_addr + a)
i2c_get_data(tempMSB)
i2c_put_ack
i2c_get_data(tempLSB)
i2c_put_nack
i2c_put_stop

01h – registro di configurazione. Lo scriviamo con la configurazione desiderata (di seguito il dettaglio)

Gli altri due servono per controllare il termostato e hanno entrambi la stessa struttura a 12 bit del registro temperatura
02h – temperatura isteresi del termostato. Rappresenta la soglia di intervento. Il termostato è attivo al di sotto della temperatura impostata. Si disattiva al raggiungimento di tale valore per riattivarsi quando la temperatura scenda al di sotto del valore di isteresi.
03h – Valore della temperatura del termostato

Codifica della temperatura
Il valore della temperatura viene rappresentato in questo modo:
1775_temperatura

Questo significa che la parte intera la otteniamo dal primo byte che leggiamo. Il valore letto nel byte meno significativo va shiftato di 4 a destra e moltiplicato per 0.0625 per ottenere la parte decimale della temperatura. I bit sono effettivamente utilizzati in base alla risoluzione impostata. Di default la risoluzione è a 9 bit, quindi abbiamo letture valide solo per il primo bit (0.5?C)

Byte di configurazione (02h)

1775_configurazione
SD: quando portato a 1 il convertitore va in stand-by, restando in ascolto solo sul BUS I2C. A 0 (default) il dispositivo effettua continuamente rilevazione della temperatura

TM: seleziona il modo operativo del termostato. 0 funziona nella modalità descritta nell’esempio che ho fatto parlando di isteresi. A 1 il funzionamento è “a interrupt”, cioè partendo dal valore alto che indica la situazione normale, l’uscita viene abbassata ad ogni evento significativo (temperatura sopra la soglia o sotto l’isteresi). Il valore resta basso fino a che non viene effettuata una lettura I2C.

POL indica il significato di “attivo” dell’uscita. Se POL vale 1, attivo significa 1, altrimenti 0

F0-F1 indica il numero di letture da effettuare prima di considerare valido il cambio stato quando si opera in modalità interrupt.

1775_letture

R0-R1 indica la risoluzione del termometro
1775_risoluzione

Indirizzi
Trattandosi di un dispositivo I2c, dobbiamo parlare di indirizzo. L’indirizzo è necessario per effettuare la comunicazione. Diversamente da quanto solitamente avviene per altri dispositivi (per esempio le EEPROM seriali) per il DS1775 l’indirizzo è unico e cablato nel processore, composto da due parti.

  • una parte fissa: 1001
  • altri 3 bit determinabili dal part number dell’integrato, in particolare:
    DS1775R/TRL 000
    DS1775R/TR1 001
    DS1775R/TR2 010
    DS1775R/TR3 011
    DS1775R/TR4 100
    DS1775R/TR5 101
    DS1775R/TR6 110
    DS1775R/TR7 111

Va quindi prestata attenzione al momento dell’acquisto

]]>
https://www.ognigiorno.com/2009/03/26/il-sensore-di-temperatura-ds1775.html/feed 0