Tutorial → PIC18 in C →
USB

Stesura preliminare

In questa pagina viene mostrato un esempio di codice per utilizzare un
PIC18 come device USB. Microchip rende disponibile un framework USB
all'interno della Microchip Libraries for Applications (MLA)
che semplifica, almeno in parte, la scrittura del software. In questa pagina non viene spiegato come funziona USB: si rimanda al
materiale disponibile in rete e, nello specifico, a quello fornito da
Microchip stassa. Consiglio di iniziare con
USB_primer.pdf.
Nell'esempio qui presentato il PIC18 si limita ad accendere o spegnere un LED dopo
aver ricevuto da un PC host, tramite terminale seriale, un 1 oppure uno 0.
Dopo aver eseguito il comando, risponde con la stringa "Done!".
Un esempio più articolato di codice del PIC è fornito dal programma di
test scaricabile dalla pagina
PIC-USB. Un esempio di codice Java per l'host, forse compatibile con
Linux, Windows e Mac, è scaricabile a fondo pagina
L'hardware
Il codice è stato sviluppato per essere utilizzato con il circuito
stampato PIC-USB, ma è
evidentemente possibile realizzare il circuito su breadboard, semplicemente
seguendo lo schema. Più complesso invece l'adattamento ad un PIC18 diverso dal
PIC18F25K50 in quanto
è necessario riscrivere parti consistenti del codice di esempio.
Per dimostrare il funzionamento viene utilizzato un LED
collegato al pin RA0 (il cavetto blu più a sinistra nella fotografia di
apertura)
Il codice di esempio
Al solito il codice è disponibile a fondo pagina,
diviso in due parti:
- Il framework fornito da Microchip, da non modificare
Nota 1
- Un esempio, scritto semplificando quello fornito da Microchip ed
adattandolo all'hardware disponibile.
La configurazione è piuttosto macchinosa, consiglio quindi di seguire in
modo rigoroso la procedura di seguito mostrata:
- Collegare al solito il PICkit al PIC18
- Creare un normale progetto MPLAB X (per esempio: USB)
- Estrarre il contenuto il contenuto delle MLA in una directory
all'interno di MPLABXProjects. Consiglio di lasciare il nome proposto
- Copiare i file presenti nel file
USB_code.zip nella directory del vostro progetto. Si tratta di
cinque file sorgenti (.c) e sette header file (.h)
- Aggiungere al progetto, nella cartella Source
i cinque file sorgenti
(tasto destro → Add Existing Item → Filtrare per Source file →
selezionare e aggiungere)
- Aggiungere al progetto, nella cartella Header File i sette header
file (tasto destro → Add Existing Item → Filtrare per Header file → selezionare e aggiungere)
- Creare, all'interno della cartella Source
una Logical Foder di nome
qualunque (consiglio: framework, o qualcosa del genere)
- Aggiungere alla Logical Folder appena creata i due file
usb_device.c
e usb_device_cdc.c presenti nella directory
../MLA_v2015_08_10/inc. Il progetto dovrebbe presentarsi come di seguito:

- Esaminare velocemente alcuni dei file del progetto, scoprendo
numerosissimi errori
- Selezionare attraverso la Dashboard le proprietà del progetto e,
nella sezione del compilatore XC8, le directory da includere (vedere lo screenshot seguente)

- Aggiungere le due cartelle ../MLA_v2015_08_10/inc (usare il pulsante
browser) e ../USB.X (da digitare manualmente con il nome
della directory del vostro
progetto). Questo dovrebbe eliminare tutti gli errori presenti
- Compilare il programma (sono presenti numerosissimi warning ma
nessun errore - Nota 2)
- Collegate il connettore mini-USB presente sullo stampato ad un PC
Linux/Windows/Mac, che fungerà da hist (nota 3)
- Trasferire il programma sul PIC18 al solito modo ed eseguirlo. Non è
necessario che il PICkit alimenti il PIC in quanto l'energia può essere
fornita attraverso il cavo USB collegato all'host
- Il PC host dovrebbe rilevare la presenza di una nuova periferica
seriale. Per esempio sulle macchine linux sarà presente un nuovo device
tty:
vv@vv-15rse:~$ ls -l /dev/ttyA*
crw-rw---- 1 root dialout 166, 0 mag 2 22:39 /dev/ttyACM0
- Utilizzare un terminale seriale (per esempio PuTTY
oppure, come nell'esempio, CuteCom) per collegarsi
all'interfaccia seriale e poter inviare i due comandi 0 e 1 che,
rispettivamente spengono ed accendono il LED collegato a RA0. Si noti la
risposta dal PIC18 "Done")

Analisi del codice
Il codice è decisamente complesso per una analisi approfondita. Alcuni
aspetti che è utile osservare almeno superficialmente:
- il file usb_descriptors.c contiene,
evidentemente i descrittori previsti dallo standard USB. Sono facilmente
individuabili elementi quali il numero e la dimensione degli endpoints,
il VID ed il PID, alcune stringhe identificative, la classe di
appartenenza... Questi elementi sono trasmessi all'host e visibili con
comandi tipici del sistema operativo in uso. Per esempio con linux:
vv@vv-15rse:~$ lsusb
Bus 003 Device 005: ID 04d8:000a Microchip Technology, Inc. CDC RS-232
Emulation Demo
vv@vv-15rse:~$ lsusb -d 04d8:000a -v
Bus 003 Device 005: ID 04d8:000a Microchip Technology, Inc. CDC RS-232
Emulation Demo
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 2 Communications
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x04d8 Microchip Technology, Inc.
idProduct 0x000a CDC RS-232 Emulation Demo
bcdDevice 0.01
iManufacturer 1 Microchip Technology Inc. - www.VincenzoV.net
iProduct 2 PIC-USB demo and testing code - 18F25K50
...
- La funzione SYSTEM_Tasks(); (nota
4) viene eseguita regolarmente all'interno del superloop e
in essa vanno inseriti compiti specifici dell'applicazione ed
indipendente dall'USB
- La funzione CustomCDCTasks() esegue
regolarmente i compiti legati all'USB. Nell'esempio:
- verifica la presenza
di byte inviati dall'host con la funzione getsUSBUSART()- Nota
5
- procede con i compiti specifici dell'appliczione: accensione/spegnimento del LED,
a seconda del comando 1/0 inviato dall'host
- trasmette all'host la risposta al
comando (funzione putUSBUSART(). nell'esempio
sempre la stringa "Done\n\r"
- Da notare che è necessario invocare con una certa frequenza la
funzione CDCTxService() che ha il compito di
gestire le comunicazioni tra device e host, attivando le transizioni tra
gli stati della macchina a stati finiti che sovraintende al
funzionamento del framework
- La funzione SYSTEM_Initialize();
inizializza il PIC18, sia nella parte relativa all'USB (parte
interamente gestita dal framework) che nella parte specifica dell'applicazione
(TRISA nell'esempio)
- Disponendo di una utenza con i permessi di root è possibile
analizzare gli eventi legati all'enumerazione:
root@vv-15rse:~# tail /var/log/messages -f
May 2 20:53:39 vv-15rse kernel: [18221.673409] usb 3-3.1: new full-speed
USB device number 24 using xhci_hcd
May 2 20:53:39 vv-15rse kernel: [18221.777897] usb 3-3.1: New USB device
found, idVendor=04d8, idProduct=000a
May 2 20:53:39 vv-15rse kernel: [18221.777903] usb 3-3.1: New USB device
strings: Mfr=1, Product=2, SerialNumber=0
May 2 20:53:39 vv-15rse kernel: [18221.777907] usb 3-3.1: Product:
PIC-USB demo and testing code - 18F25K50
May 2 20:53:39 vv-15rse kernel: [18221.777909] usb 3-3.1: Manufacturer:
Microchip Technology Inc. - www.VincenzoV.net
May 2 20:53:39 vv-15rse kernel: [18221.778769] cdc_acm 3-3.1:1.0:
ttyACM0: USB ACM device
May 2 20:53:39 vv-15rse mtp-probe: checking bus 3, device 24: "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.1"
May 2 20:53:39 vv-15rse mtp-probe: bus: 3, device: 24 was not an MTP
device
- L'ultima versione disponibile al momento della stesura di queste
note è la 2.13, del 10 agosto 2015; essa è solo parzialmente compatibile
con i settaggi predefiniti del compilatore XC8 c1.37 (la compilazione ha
successo, ma vengono segnalati numerosi warning)
- Se la cosa vi "infastidisce", potete impostare il Warning level del
compilatore ad un livello maggiore di -3
- Servono quindi due cavi USB, uno per il PICkit usato per la
programmazione ed il debug ed un altro per la connessione device-host,
gestito dal programma appena scritto. Probabilmente è utile usare due
cavi USB di diverso colore e, se possibile, due PC separati
- Nel codice di esempio è semplicemente un place-holder
- Un aiuto alla comprensione di questa e altre funzioni è disponibile
nei commenti del codice, cliccando sul nome della funzione mantenendo
premuto <Ctrl>
Data di creazione di questa pagina: settembre 2014
Ultima modifica: 2 maggio 2016