Esperimenti con la Demo Board Freescale HC08

Un economico kit di sviluppo di Freescale (ora NXP) permette di esplorare in maniera semplice e veloce le possibilità dei micro HCS08. La DEMO9S08QG8  è una scheda di sviluppo a basso costo dedicata al microcontrollore  MC9S08QG8 che mette a disposizione tutto  il necessario per iniziare a sviluppare delle applicazioni per questo microcontrollore  e per testarle. Ecco una serie di esperimenti utili per conoscerli e iniziare ad usarli.

LA DEMO BOARD HC08

La scheda monta un debugger integrato (BDM) accessibile via USB che permette di programmare il microcontrollore ed eseguire il debug in-circuit dei programmi. Con la scheda sono forniti  anche un cavo USB 2.0 A/B, il software di sviluppo CodeWarrior Development Studio e la documentazione sull’hardware e sul software. La scheda, visibile in figura 1, ha dimensioni molto contenute (circa 6x7,5cm) ma alloggia un discreto numero di componenti e periferiche utili per testare le funzionalità del microcontrollore  e la correttezza dei programmi  scritti.

Figura 1. La Demo Board DEMO9S08QG8

Figura 1. La Demo Board DEMO9S08QG8

Più in dettaglio la scheda monta i seguenti componenti  accessibili dal microcontrollore:

  • 2 pulsanti (SW1, SW2), più uno per il reset;
  • 2 LED (LED1, LED2);
  • un potenziometro (RV1);
  • un sensore di luce (RZ1);
  • un’interfaccia RS-232;
  • un oscillatore esterno (opzionale);
  • alcuni jumper di configurazione;

Il collegamento tra i vari dispositivi ed il microcontrollore è mostrato in figura 2 (sarà utile riferirsi a questo schema per comprendere il codice che verrà presentato nei seguenti paragrafi).

Figura 2. Collegamento delle periferiche al microcontrollore

Figura 2. Collegamento delle periferiche al microcontrollore

Sulla scheda sono presenti  inoltre  un  connettore  a  32  pin  (passo 2,54mm),  che permette di collegare ulteriori dispositivi o interfacciare la scheda ad un sistema esterno e il debugger  integrato  P&E USB-BDM, che verrà descritto meglio in seguito. L’interfaccia USB, utilizzata per  la  programmazione  del  micro  e  per  il debug, fornisce anche l’alimentazione alla scheda (è presente comunque anche un connettore per l’alimentazione esterna).

IL MICRO MC9S08QG8

Come già detto la Demo Board monta un microcontrollore MC9S08QG8. Questo dispositivo fa parte dell’ampia famiglia di microcontrollori  ad 8 bit  68HC08 di Motorola/Freescale. In realtà il dispositivo è basato sulla evoluzione HCS08, che pur mantenendo le principali caratteristiche architetturali e la compatibilità  di codice con l’originario core, aggiunge alcune istruzioni e funzionalità dedicate al debug ed alla riduzione del consumo di potenza. Per chi non avesse familiarità con la serie HC08 è il caso di ricordare che si tratta di microcontrollori tipicamente CISC (sullo stile di 8051 o Z80), quindi caratterizzati da istruzioni e modi d’indirizzamento  abbastanza complessi, basati sull’uso di un accumulatore, di registri indice e di uno stack pointer esplicito e dotati di supporto per le interruzioni vettorizzate. Queste caratteristiche li rendono particolarmente adatti ad essere programmati in C e ad essere impiegati in campi i cui è necessario eseguire complessi algoritmi di controllo (più che di elaborazione veloce di segnali). Nonostante le ridotte  dimensioni del package degli MC9S08QG8 (8 o 16 pin), il microcontrollore integra oltre a 8KB di Flash per codice/dati  e 512 byte di RAM, una nutrita serie di periferiche, che confermano l’orientamento di questo dispositivo verso applicazioni di controllo.  Le periferiche integrate, alcune della quali verrano utilizzate negli esempi seguenti, sono:

  • 12 porte di I/O programmabili
  • ADC a 8 canali, 10 bit
  • Comparatore analogico (ACMP)
  • Interfaccia UART
  • Interfaccia IIC ed SPI
  • Modulo PWM a due canali
  • Timer ad 8 bit (MTIM)
  • Real Time Clock per interruzioni periodiche (RTI)
  • Interfaccia per pulsanti/tastiere (KBI)
  • Generatore di clock interno con FLL
  • Watchdog e debugger in-circuit

Ciascuna di queste periferiche può essere configurata in maniera estesa e funzionare in diverse modalità. Il modulo di debug integrato merita un approfondimento. Questo dispositivo permette di controllare il microcontrollore attraverso un solo pin e non richiede l’utilizzo  dei  classici programmi  “monitor” da aggiungere al proprio codice. Utilizzando il debugger integrato è possibile effettuare le tipiche operazioni di lettura e scrittura dei registri e della memoria, lo stepping, il tracing e l’inserimento di break-point complessi (con trigger a doppio livello). La cosa interessante è che alcune di queste operazioni possono essere eseguite in maniera totalmente non invasiva, cioè mentre il programma è in esecuzione e senza perturbarlo minimamente.  Questo permette di eseguire le simulazioni del programma direttamente sul dispositivo (In-Circuit Debugging).

L’AMBIENTE DI SVILUPPO

Con la Demo Board viene fornito un cofanetto di CD che contiene l’ambiente di sviluppo CodeWarrior. Si tratta di un ambiente molto  completo ed estremamente potente che ingloba tutto  quello che normalmente è necessario nello sviluppo di applicazioni embedded. In particolare nel sofisticato ambiente grafico sono inglobati il compilatore ANSI/ISO C/C++, l’assembler, il linker ed il debugger, più altri strumenti avanzati. Nonostante la complessità dell’ambiente di sviluppo riuscire a creare un progetto, compilarlo, caricarlo nel microcontrollore  ed eseguire il debug è relativamente semplice. Occorre però un po’ di pratica per iniziare a prendere confidenza e ad apprezzare gli strumenti  più avanzati che CodeWarrior mette a disposizione. Per creare un nuovo progetto è sufficiente selezionare la voce New dal menu File e quindi l’opzione Project Wizard. Occorrerà quindi  rispondere alle richieste delle varie finestre secondo le proprie esigenze. In particolare per provare i codici riportati di seguito sono state scelte le seguenti opzioni: microcontrollore MC9S08QG8, linguaggio  C, nessuno utilizzo del “Processor Export” e del “PC-lint”  (occorrono licenze specifiche), start-up code di tipo minimale o ANSI (è indifferente),  nessun supporto  del  floating  point, modello  di memoria Tiny o Small (è indifferente), debug con Full Chip Simulator e Hardware Debugging (il primo permette la simulazione del dispositivo su PC, il secondo il debugging in-circuit e la programmazione). A questo punto verrà creata una sezione con i dettagli del progetto sulla sinistra e l’area per editare il codice sulla destra (visibile in figura 3).

Figura 3. L’ambiente di sviluppo CodeWarrior

Figura 3. L’ambiente di sviluppo CodeWarrior

Come si può notare nella finestra sulla sinistra sono raggruppati in maniera molto ordinata ed analitica i vari elementi utilizzati per compilare il programma, ed i file ausiliari utilizzati ad esempio per il debug. è possibile modificare manualmente tutti questi files, utilizzando tra l’altro gli strumenti avanzati per l’editing di testo/codice messi a disposizione del programma (che non saranno approfonditi  qui per questioni di spazio). Una volta scritto e compilato il codice con il comando Make (selezionare prima il target P&E ICD nella finestra del progetto) sarà possibile scaricarlo nel microcontrollore  ed  eseguire il  debug,  selezionando la voce di menu o il pulsante Debug. Verrà aperta la finestra del debugger e quella del programmatore, che dopo avere chiesto conferma completerà il lavoro in pochi secondi. Dalla finestra di Debug (figura 4) sarà possibile avviare il programma  sul target,  ed eseguire tutte le azioni di debug descritte in precedenza.

Figura 4. Debugger di CodeWarrior

Figura 4. Debugger di CodeWarrior

Prima di passare alla descrizione di alcuni test da eseguire scheda, è il caso di ricordare che per attivare completamente le funzionalità di CodeWarrior è necessario installare un’apposita licenza. Questo file, chiamato License.dat può  essere  scaricato gratuitamente dal sito di Freescale/NXP (non è necessario richiederla via e-mail come spiegato nel manuale).

ALCUNI ESPERIMENTI

Una prima prova da fare, utile per prendere confidenza con l’ambiente di sviluppo e con la scheda e per accertarsi che tutto  funzioni  e sia configurato correttamente è il classico test di lampeggio di un LED. Data la sua semplicità il programma dovrebbe funzionare immediatamente se abbiamo fatto tutto correttamente. Il codice è riportato  nel listato 1.

/*****************************************************************************
*
* Note:         To be used on a MC9S08QG8 demo board.
*               LED and SW are active low.
*               Created using CodeWarrior 3.1 for HC(S)08.
*****************************************************************************/

#include <MC9S08QG8.h> /* include peripheral declarations */


void main(void) {
  int cnt;
  //System init
  SOPT1_COPE = 0;       //Disable watchdog
  ICSC2_BDIV = 3;       //Bus freq. div = 8

  //GPIO init
  PTBD_PTBD6 = 1;       //LED1 off
  PTBDD_PTBDD6 = 1;     //Set PTB6 as an output

/* Infinite loop */
while(1) {
    //Toggle LED1
    PTBD_PTBD6=~PTBD_PTBD6;

    //Delay
    for(cnt=0; cnt<10000; cnt++){
    }
  }
}
Listato 1

Il programma fa lampeggiare il LED1 invertendo continuamente lo stato del pin PTB6, configurato come uscita, ed utilizzando una routine di ritardo software (un semplice ciclo for vuoto). All’inizio viene impostata una frequenza del bus interno  di circa 1MHz (gli  8MHz generati dall’FLL interno  vengono divisi per 8) e viene disabilitato il watchdog (COP). Tutte le definizioni dei registri e dei loro campi sono dichiarate nel file header MC9S08QG8.h, che è stato incluso all’inizio (e che viene fornito con l’ambiente). Seguendo i  passi descritti  prima  dovrebbe  essere possibile compilare, caricare ed avviare il programma sul micro senza problemi.

Uso del timer  e delle interruzioni

Vogliamo provare adesso a fare lampeggiare il secondo LED utilizzando il modulo MTIM (timer ad 8 bit) del micro. In particolare il timer verrà utilizzato per temporizzare il  lampeggio  utilizzando  il  meccanismo delle interruzioni. Ad ogni overflow del timer verrà richiamata l’apposta funzione di servizio (ISR), che provvederà a invertire lo stato del pin. Il timer è incrementato alla frequenza del bus (circa 1MHz in questo esempio) e dispone di un prescaler, in questo caso impostato per dividere per 256. La frequenza di overflow dovrebbe quindi essere di circa 15Hz (occorrono 256 cicli per avere l’overflow). La routine d’interruzione è dichiarata specificando nella funzione la keyword interrupt ed il numero di vettore corrispondente (12 per il modulo MTIM). La routine  provvede soltanto a cancellare il flag di overflow e ad invertire lo stato del pin. Il resto del programma è identico al precedente (il LED1 continuerà a lampeggiare con il ritardo software). Il programma è visibile nel listato 2.

/*****************************************************************************
*
*****************************************************************************/
#include <hidef.h>           /* for EnableInterrupts macro */
#include <MC9S08QG8.h>       /* include peripheral declarations */
void main(void) {
  int cnt;
  EnableInterrupts;          /* enable interrupts */
  //System init
  ICSC2_BDIV = 3;               //Bus freq. / 8
  SOPT1_COPE = 0;               //Disable watchdog
  //GPIO init
  PTBD_PTBD6 = 1;               //LED1 off
  PTBD_PTBD7 = 1;               //LED2 off
  PTBDD_PTBDD6 = 1;             //Set PTB6 as an output
  PTBDD_PTBDD7 = 1;             //Set PTB7 as an output
  //Modulo Timer init
  MTIMCLK_PS = 8;               //Prescaler: /256
  MTIMCLK_CLKS = 0;             //Clock source: ICS
  MTIMMOD = 0;                  //Modulo: 0 (off)
  //Reset and start MTIM + enable IRQ
  MTIMSC = MTIMSC_TRST_MASK|MTIMSC_TOIE_MASK;
  /* Infinite loop */
  while(1) {
    //Toggle LED
   PTBD_PTBD6=~PTBD_PTBD6;
   for(cnt=0; cnt<10000; cnt++){
   }
 }
}

/*** MTIM ISR ***/
interrupt 12 void MTIM_ISR(void) {
   MTIMSC_TOF=0; //clear TOF
   PTBD_PTBD7=~PTBD_PTBD7; //toggle Port
}
Listato 2

Uso del Keyboard Controller

È possibile associare ai pin della porta B del micro la possibilità di generare delle interruzioni in corrispondenza di cambiamenti specifici. Questa funzione è particolarmente adatta a gestire pulsanti o tastiere. Vogliamo provare a utilizzare il pulsante SW1 per fermare e riavviare il timer nel programma visto prima, in  modo  da fermare o  riattivare  il  lampeggio  del LED2 ad ogni pressione. Per fare questo è sufficiente aggiungere poche linee al codice visto prima. Occorre inizializzare propriamente il modulo  KBI, in modo che possa generare interruzioni in corrispondenza alla pressione di SW1 e scrivere la ISR  corrispondente in modo che neghi il bit di stop del timer. Le linee di codice da aggiungere sono riportate  le listato 3.

   // — Inserire nel main, prima del loop infinito —
   //KBI init (for SW1)
   KBIPE_KBIPE2 = 1;      //Enable Keyboard Pin
   KBISC_KBIE = 1;        //Enable Keyboard Interrupts
   KBISC_KBACK = 1;       //Clear Pending Keyboard Interrupts
   PTAPE_PTAPE2 = 1;      //Enable Pullup for Keyboard pin
…
// — Inserire fuori dal main —
/*** KBI ISR ***/
interrupt 18 void KBI_ISR(void)   {
   KBISC_KBACK = 1;               //clear IRQ flag
   MTIMSC_TSTP=~MTIMSC_TSTP;      //Start/Stop MTIM
}
Listato 3

Uso del Comparatore  Analogico

Il modulo ACMP può essere utilizzato per confrontare un segnale analogico applicato al piedino  PTA1 con un altro applicato a PTA0, oppure con un riferimento interno, al fine di ottenere un valore binario che indica se uno è maggiore dell’altro. Sulla Demo Board questi due piedini sono collegati al potenziometro RV1 e al foto-transistor RZ1, quindi è possibile confrontare le tensioni fornite da questi due dispositivi, oppure l’uscita di RZ1 con il riferimento interno. Nel listato 4 il risultato del confronto viene utilizzato per accendere o spegnere il LED1.

/*****************************************************************************
*
*****************************************************************************/
#include <hidef.h>          /* for EnableInterrupts macro */
#include <MC9S08QG8.h>      /* include peripheral declarations */
/*** main ***/
void main(void) {
  EnableInterrupts;          /* enable interrupts */

  //System init
  ICSC2_BDIV = 3;           //Bus freq. / 8
  SOPT1_COPE = 0;           //Disable watchdog
  //GPIO init
  PTBD_PTBD6 = 1;           //LED1 off
  PTBDD_PTBDD6 = 1;         //Set PTB6 as an output
  //ACMP init
  ACMPSC_ACME = 1;         //Comparator on
  ACMPSC_ACBGS = 1;        //Compare with bandgap
  ACMPSC_ACIE = 1;         //IRQ enable
  ACMPSC_ACMOD = 3;        //Fall&Rise edge
  /*** Infinite loop ***/
  while(1) {}
}
/*** ACMP ISR ***/
interrupt 20 void ACMP_ISR(void) {
  ACMPSC_ACF = 0; //clear IRQ flag
  PTBD_PTBD6 = ACMPSC_ACO; //Turn on/off LED1
}
Listato 4

In particolare è stata utilizzata l’interruzione  generata dal modulo ACMP in corrispondenza dei cambiamenti di stato. Nella ISR viene cancellato il flag di interruzione e viene assegnato all’uscita (LED1) proprio il valore del comparatore.  Avviando il programma  il LED1 si accenderà quando la quantità di luce rilevata da RZ1 scenderà sotto una certa soglia (si provi ad esempio a coprire il sensore con un dito).  In questo caso la soglia è determinata dal riferimento  interno, che è stato selezionato impostando ACMPSC_ACBGS a 1. Se si assegna 0 a questo campo il confronto  verrà eseguito con la tensione presente su PTA0, cioè quella fornita  dal trimmer.  In  questo caso sarà possibile variare manualmente la soglia.

Test dell’ADC

Per provare il convertitore analogico/digitale (ADC) è possibile utilizzare uno dei due segnali analogici presenti sulla scheda, ossia il segnale proveniente dal sensore ottico RZ1 o quello proveniente dal trimmer RV1. Sarà possibile selezionare il canale desiderato impostando il suo valore nel registro apposito (il campo ADCH di ADCSC1). Nel programma proposto non sono state utilizzate le interruzioni dal momento che le operazioni eseguite hanno tempi abbastanza rilassati. La maggior parte di registri relativi all’ADC sono impostati con i valori di default, soltanto il registro ADCSC1 ed il registro ADCRL verranno utilizzati per selezionare il canale, avviare la conversione e per leggere il valore convertito. La conversione eseguita in questo modo risulta ad 8 bit, avviata via software e sincronizzata dal clock del bus. Il programma  in pratica utilizza il valore letto dall’ADC per regolare la velocità di lampeggio  del LED1. Il valore letto dall’ADC, moltiplicato  per 32, viene utilizzato come limite di conteggio del loop di ritardo. Più è grande il valore letto, più lunga sarà l’attesa. Proprio per il fatto che tra l’inizio della conversione e la lettura del valore c’è il loop di ritardo, non è necessario eseguire il polling per controllare se la conversione è completa (dovrebbe esserlo sempre). Il codice del programma è riportato nel listato 5.

/*****************************************************************************
*
*****************************************************************************/
#include <MC9S08QG8.h>  /* include peripheral declarations */


/*** main ***/
void main(void) {
   int cnt, lim;

   //System init
   ICSC2_BDIV = 3;                 //Bus freq. / 8
   SOPT1_COPE = 0;                 //Disable watchdog

   //GPIO init
   PTBD_PTBD6 = 1;                 //LED1 off
   PTBDD_PTBDD6 = 1;               //Set PTB6 as an output

lim=1000;

/*** Infinite loop ***/
while(1) {
   ADCSC1_ADCH=0;                 // Sel channel/start ADC
                                  // Ch. 0 = Pot RV1
                                  // Ch. 1 = Sensor RZ1
                                  // Ch. 26 = temp sensor
   PTBD_PTBD6=~PTBD_PTBD6;        //Toggle LED

   //Software delay
   for(cnt=0; cnt<lim; cnt++){
   }
   lim=(ADCRL<<5);                //Read from ADC and x32
  }
}
Listato 5

Si può notare che cambiando il valore assegnato ad ADCH è possibile selezionare differenti  canali dell’ADC, in particolare il valore 0 seleziona il trimmer RV1, mentre altri valori selezionano gli altri piedini, i riferimenti di tensione o il sensore di temperatura interno del micro. Quest’ultima possibilità può risultare utile in alcune applicazioni sul campo, ma bisogna ricordare che il sensore in questione non è molto preciso e risente molto delle resistenze e della capacità termica del package.

Prova UART ed RTI

Come ultimo esperimento con la Demo Board HC08 presentiamo un’applicazione  abbastanza realistica: un semplicissimo datalogger. Il programma utilizza il generatore di interruzioni Real-Time per campionare un valore analogico ad intervalli regolari e per inviarlo ad un computer via RS-232. La periferica UART (che nel datasheet è chiamata SCI, Serial Communication Interface) viene programmata per funzionare ad una velocità di 2400 baud, ed in modalità polling (interruzioni TX ed RX disabilitate), ed è usata soltanto per trasmettere i dati. La periferica RTI invece è programmata in modo da generare un’interruzione ogni 256 ms. Il loop principale del programma è vuoto e le uniche funzioni svolte sono contenute nella ISR relativa all’RTI. In questa routine viene cancellato il flag d’interruzione, invertito lo stato del LED1, inviato il dato al PC attraverso la UART e avviata la nuova conversione dell’ADC. Per convertire il dato binario in una stringa esadecimale viene utilizzata la routine bin2asc, mentre l’invio di tutti i caratteri ASCII è gestito dalla funzione SendMsg. Il canale ADC da convertire è impostato tramite la macro CH, in questo caso posta uguale a 0 (trimmer)  ma facilmente modificabile. Il codice è riportato  nel listato 6.

#include <hidef.h>               /* for EnableInterrupts macro */
#include <MC9S08QG8.h>           /* include peripheral declarations */
// Set ADC channel
#define CH 0
// *** Function prototypes ***
void SendMsg(char *msg);
char * num2asc(byte n);
char n_str[8]; //Hex string
/*** main ***/
void main(void) {
  EnableInterrupts;             /* enable interrupts */
  //System init
  ICSC2_BDIV = 3;               //Bus freq. / 8
  SOPT1_COPE = 0;               //Disable watchdog
  //GPIO init
  PTBD_PTBD6 = 1;               //LED1 off
  PTBDD_PTBDD6 = 1;             //Set PTB6 as an output
  //UART init
  SCIBD = 1000000/16/2400;     // Baud rate divider
  SCIC1_M = 0;                 //Mode: start+8 bit+stop
  SCIC2_RIE = 0;               //RX IRQ off
  SCIC2_TCIE = 0;              //TC IRQ off
  //RTI init
  SRTISC_RTIS = 5;            // RTI clk div: 256ms
  SRTISC_RTIE = 1;            // RTI IRQ enable
  ADCSC1_ADCH = CH;           //Start first ADC conversion
  /*** Infinite loop ***/
  while(1) {};
}
// *** RTI ISR ***
interrupt 23 void RTI_ISR(void) {
  SRTISC_RTIACK = 1;           //clear IRQ flag
  PTBD_PTBD6=~PTBD_PTBD6;      //Toggle LED
  SendMsg(num2asc(ADCRL));     //TX value
  ADCSC1_ADCH=CH;              //Start next conversion
}
// Send a string via RS-232
  void SendMsg(char *msg) {
  byte ix=0;                  // String pointer
  byte dummy;                 // dummy var for reading SCIS1
  byte nxt_char;
  SCIC2 = 0x08;               // enable Tx
  dummy = SCIS1;              // 1st half of TDRE clear procedure
  nxt_char = msg[ix++];
  while(nxt_char != 0x00) {
    SCID = nxt_char;         // 2nd half of TDRE clear procedure
    nxt_char = msg[ix++];
    while(!SCIS1_TDRE){ };
  }
  while(!SCIS1_TC){};
  SCIC2_TE = 0;
}
// Convert a byte to an hex string
char * num2asc(byte n) {
  n_str[0] = (n>>0x04)+0x30;     // convert MSN ‘n’ to ascii
  if(n_str[0]>0x39)              // if MSN is $a or larger...
    n_str[0]+=0x07;              // ...add $7 to correct
  n_str[1] = (n&0x0f)+0x30;      // convert LSN ‘n’ to ascii
  if(n_str[1]>0x39)              // if LSN is $a or larger...
  n_str[1]+=0x07;                // ...add $7 to correct
  n_str[2] = ‘\r’;
  n_str[3] = ‘\n’;
  n_str[4] = 0x00;               // add null
  return n_str;
}
Listato 6

Per visualizzare i dati sul PC è possibile utilizzare qualsiasi programma in grado di ricevere dati dalla porta seriale (va bene anche l’HyperTerminal di Windows), impostando 2400 baud, 1 bit di start, 8 bit dati, 1 bit di stop, nessuna parità e nessun controllo  di flusso come mostrato in figura 5.

Figura 5. Impostazioni di Hyperterminal e dati ricevuti dalla scheda

Figura 5. Impostazioni di Hyperterminal e dati ricevuti dalla scheda

La velocità di trasmissione può essere anche maggiore di 2400 baud, però occorre fare i conti con la precisione della frequenza che si ottiene dividendo per un fattore intero la frequenza del bus, e con la precisione e la stabilità intrinseca di quest’ultima (che ricordiamo è generata da un  riferimento  interno  oscillante a circa 32KHz). È  possibile ovviare a questo inconveniente agendo sul registro di tuning  dell’oscillatore interno. Per maggiori dettagli su questi aspetti è possibile consultare il datasheet del microcontrollore  e studiare il codice di uno dei due esempi forniti con la scheda (DEMO9S08QG8_APP), che è stato appositamente pensato per esercitare tutti di dispositivi di cui è dotato il microcontrollore.

Conclusione

Gli esempi presentati dovrebbero fornire un’idea delle possibilità offerte dalla scheda di sviluppo, delle caratteristiche  del  potente  ambiente  di  sviluppo della Metrowerks e delle potenzialità dei microcontrollori  HCS08 di Freescale/NXP. I programmi  presentati inoltre possono essere considerati un utile punto di partenza per chi decidesse di avvicinarsi all’utilizzo ed alla programmazione di questi dispositivi e possono essere utilizzati come template per iniziare a scrivere i propri.

 

Scarica subito una copia gratis

Una risposta

  1. Maurizio 21 Aprile 2016

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend