Les expérimentations menées sur PIC pendant les vacances ont fini par porter leurs fruits. J’ai désormais un schéma fonctionnel qui permet de fabriquer un périphérique USB simple autour d’un PIC 18F2455. Ce billet présente le schéma de la carte de test, qui permet de jouer avec deux LED, ainsi que le programme correspondant.
Le montage a déjà été brièvement introduit dans ce billet. Le présent programme prend une direction un peu différente, notamment au niveau de la vitesse du bus USB (full-speed). La raison en est simple : j’ai récupéré un programme de démonstration fourni par Microchip, qui était conçu pour PIC18F4450, et je l’ai adapté sans retoucher les directives de configuration pour le moment. Je ferai quelques expérimentations lorsque j’aurai le temps, et je posterai des informations le moment venu !
Ce circuit est directement déduit des informations fournies par Microchip. Le connecteur ICSP permet de programmer le PIC sur place, sans même le débrancher du port USB ! La résistance de pull-up R1 permet de maintenir /MCLR (Master Clear Reset, i.e. reset du PIC) à 1. Si vous ne souhaitez pas disposer de la fonction de reset, vous pouvez vous passer de cette résistance, mais dans ce cas, il faudra positionner la directive de configuration MCLRE
(MCLR Enable) à OFF
ci-dessous.
La réalisation de ce circuit sur plaque à trous a déjà été présentée :
J’ai récupéré les programmes de démonstration de Microchip (voir aussi la documentation), et en particulier le firmware CDC, émulation de port série. L’idée est de créer un périphérique de classe Communication Device. Ainsi, un tel périphérique est pris en charge sur l’ordinateur par un driver générique. Et réciproquement sur le PIC, en reprenant le firmware de démonstration de Microchip, tout se passe comme si on utilisait un UART. Ce n’est donc pas très compliqué…
J’ai repris tous les fichiers du firmware de démonstration, et effectué les modifications suivantes.
Le firmware de Microchip est prévu pour PIC18F4450. Il s’agit d’adapter les directives de configuration. J’utilise les directives suivantes pour le 18F2455 (plus de détails à venir au fil des expérimentations) :
#pragma config USBDIV = 2, CPUDIV = OSC1_PLL2, PLLDIV = 5
#pragma config FOSC = HSPLL_HS, FCMEM = OFF, IESO = OFF
#pragma config VREGEN = ON, PWRT = OFF, BOR = ON, BORV = 21
#pragma config WDT = OFF, WDTPS = 32768
#pragma config CCP2MX = ON, PBADEN = OFF, LPT1OSC = OFF, MCLRE = ON
#pragma config STVREN = ON, LVP = OFF, XINST = OFF
J’ai ajouté ces lignes au début de main.c
.
Section ajoutée le 2 décembre 2007, grâce au retour d’Hervé.
Le firmware de Microchip est capable de désactiver l’USB lorsque le câble est débranché. La détection du branchement se fait via un port d’I/O, à relier au +5V de l’USB. Or par défaut, la détection se fait sur l’un des ports où se trouvent nos LED : il nous faut donc obligatoirement désactiver ce mécanisme. Sa configuration se fait dans autofiles/usbcfg.h
. Par défaut, il est activé (#define USE_USB_BUS_SENSE_IO
). Il suffit de changer le #define
en #undef
. Voir aussi la documentation de Microchip (lien ci-dessus).
Ce n’est pas le tout de reprendre le code de chez Microchip, il faut quand-même écrire le code correspondant à notre application ! C’est le rôle du fichier user.c
:
/** I N C L U D E S **********************************************************/
#include <p18cxxx.h>
#include <usart.h>
#include "system\\typedefs.h"
#include "system\\usb\\usb.h"
#include "user\\user.h"
/** V A R I A B L E S ********************************************************/
#pragma udata
char input_buffer[64];
char output_buffer[64];
/** P R I V A T E P R O T O T Y P E S ***************************************/
void InitializeUSART(void);
/** D E C L A R A T I O N S **************************************************/
#pragma code
void UserInit(void)
{
LATA = 0; // clear data latches
TRISA = 0; // direction: output pins
InitializeUSART();
}//end UserInit
void InitializeUSART(void)
{
TRISCbits.TRISC7=1; // RX
TRISCbits.TRISC6=0; // TX
SPBRG = 0x71;
SPBRGH = 0x02; // 0x0271 for 48MHz -> 19200 baud
TXSTA = 0x24; // TX enable BRGH=1
RCSTA = 0x90; // continuous RX
BAUDCON = 0x08; // BRG16 = 1
}//end InitializeUSART
void ProcessIO(void)
{
static unsigned int cnt = 0;
char str[32];
char input_buffer[10];
static int blink = 1;
if( (usb_device_state < CONFIGURED_STATE) || (UCONbits.SUSPND==1) ) return;
// User Application USB tasks
cnt++;
if(blink) { // blink the LED
if(cnt == 32768) PORTA = 1;
if(cnt == 0) PORTA = 2;
}
if(getsUSBUSART(input_buffer,1)) // if a byte has been received from the computer
{
if(input_buffer[0] == 'r') { // r (red) -> light the LED on RA0
blink = 0;
PORTA = 1;
if(mUSBUSARTIsTxTrfReady()) putrsUSBUSART("\RED.\\
");
return;
}
if(input_buffer[0] == 'g') { // g (green) -> light the LED on RA1
blink = 0;
PORTA = 2;
if(mUSBUSARTIsTxTrfReady()) putrsUSBUSART("\GREEN.\\
");
return;
}
if(input_buffer[0] == 'b') { // b (blink) -> blink the two LEDs alternatively
blink = 1;
if(mUSBUSARTIsTxTrfReady()) putrsUSBUSART("\BLINKING.\\
");
return;
}
if(mUSBUSARTIsTxTrfReady())
putrsUSBUSART("\Not understood (b|g|r).\\
");
}
}//end ProcessIO
/** EOF user.c ***************************************************************/
Après réalisation du circuit et programmation, tout devrait fonctionner facilement. Voici ce qui se passe sous Windows lorsqu’on connecte notre périphérique tout neuf :
mchpcdc.inf
) ;r
pour allumer la LED rouge, g
pour allumer la LED verte ou b
pour faire clignoter les LED.Voici donc un exemple complet de création d’un périphérique USB avec le PIC18F2455. Il reste un bug étrange, qui survient parfois : il arrive que les chaînes en mémoire soient légèrement corrompues. Peut-être un problème de débordement de mémoire quelque-part… Quelques idées pour la suite :
J’ai d’ores et déjà réutilisé cette conception de base (élaborée pendant mes loisirs) pour mon travail (donc je n’en partage pas les résultats) afin de réaliser un décodage de trames infrarouges directement sur le PIC.
NB : j’ai copié-collé le programme dans mon système de blog, en faisant à la volée quelques modifications. Il est possible qu’il y ait quelques erreurs : si c’est le cas, merci de me le signaler. Indiquez-moi également si les indications sont trop « rapides ».
HTML5 valide ? © Christophe Jacquet. ✍ Contact. Mentions légales.