Pour plus d'informations sur la programmation sur microcontrôleur PIC, consultez la section PIC.
Carte de test PIC18F/USB
Le samedi 29 avril 2006 à 16:53 - Lien permanent
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 !
Le circuit électronique
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 :
Le programme
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.
Configuration du PIC
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
.
Adaptation du firmware à notre montage
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).
Programme applicatif
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("\rRED.\r\n"); return; } if(input_buffer[0] == 'g') { // g (green) -> light the LED on RA1 blink = 0; PORTA = 2; if(mUSBUSARTIsTxTrfReady()) putrsUSBUSART("\rGREEN.\r\n"); return; } if(input_buffer[0] == 'b') { // b (blink) -> blink the two LEDs alternatively blink = 1; if(mUSBUSARTIsTxTrfReady()) putrsUSBUSART("\rBLINKING.\r\n"); return; } if(mUSBUSARTIsTxTrfReady()) putrsUSBUSART("\rNot understood (b|g|r).\r\n"); } }//end ProcessIO /** EOF user.c ***************************************************************/
Utilisation
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 :
- Windows affiche la boîte de dialogue de détection d'un nouveau périphérique. Pourquoi ne reconnaît-il pas sa classe directement, je ne le sais pas ! Il faut donc lui indiquer quel driver utiliser, et pour cela, lui indiquer un fichier INF tout simple fourni par Microchip (
mchpcdc.inf
) ; - un port COM supplémentaire est créé ;
- on peut alors s'y connecter, par exemple avec l'Hyperterminal : taper
r
pour allumer la LED rouge,g
pour allumer la LED verte oub
pour faire clignoter les LED.
Conclusion
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 :
- dans l'immédiat, faire fonctionner la chose sous Linux (edit : fait) ;
- réécrire tout le firmware, pour me passer complètement de code copyrighté Microchip ;
- faire fonctionner le mode « classe » (pour éviter d'avoir à spécifier un driver) (edit : rien à faire) ;
- implémenter mon propre protocole, et donc le driver correspondant sur l'OS.
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 ».
Commentaires
Bonjour ,
effectivement , tu es un peu rapide.
j'ai , pour ma part , exploré ca
www.holger-klabunde.de/us...
il y a un bootloader USB qui ne peut que t'interesser.
il y a aussi un pgme de test en CDC mais quand je l'ai
testé il marchait trop rarement.
je pense aussi à un bug , mais ou et comment diagnostiquer?
on est loin de la rs232...
"bien sûr qu'on pourrait faire sans USB , mais avec , c'est tellement plus compliqué ..."
nb : dans Electronique Pratique de ce mois ci il y a la description d'un oscillo USB a base de PIC.
en conclusion je pense qu'il y a dela demande sur ce sujet "USB et PIC".
a+
bonjour
sur votre schéma. Je ne vois pas la résistance Pull ups pour choisir la vitesse de transfert de l'usb. vous avez due dont l'activer en interne. puis je savoir la (les) ligne(s) de code pour cette fonction
merci
Pour « Pic du fou » :
L'activation des résistances internes de pull-up à 3,3V (voir schéma du périphérique USB page 163 du manuel) se fait grâce au registre UCFG (configuration de l'USB, voir p. 166 du manuel). Il y a deux bits à définir :
Bonjour,
2 petites erreurs au niveau de la config (FCMEM = OFF et BORV=21 non reconnus).
Sinon j'ai réussi à faire marcher tout ça en suivant scrupuleusement vos indications, non sans mal. Seulement quelques temps plus tard, le montage ne fonctionnait plus. J'ai des soucis de détection USB. Quand je réussie à installer le pilote, je n'arrive plus à configurer mes leds PA0 et PA1 en sortie sans que le processus hyperterminal ne s'emballe (curieusement lorsque les leds ne sont pas en sortie, ça fonctionne, mais la détection USB reste aléatoire !). Il doit y avoir un conflit avec le firmware et le programme du user.c !?! J'essaie de solutionner ce problème sans grand succès pour l'instant. Une idée ?
Je voulais aussi savoir si cette émulation RS232 autorise le débit full-speed de l'usb (même avec la config de 19200 baud dans InitializeUSART() ) ?
Merci
Bonjour,
Quel PIC utilisez-vous ? Si ce n'est pas le même que le mien, cela peut expliquer les incompatibilités des directives.
Avez-vous bien, soit mis la résistance R1 de pull-up entre /MCLR et Vdd, soit mis la directive MCLRE à OFF ? Vos problèmes ressemblent un peu à des instabilités que l'on aurait si le PIC faisait des « reset » inconsidérés...
Quant à l'USB full-speed, je ne sais pas...
N'hésitez pas à me tenir au courant de l'avancement de vos manips !
Bonjour,
J'utilise bien le PIC 18F2455 et la résistance de pull-up entre +5V et /MCLR est bien en place
(le reset reste à Vdd même lors des multi-détections USB).
Le plus étonnant et étrange est que : si j'enlève les lignes TRISA = 0 et/ou InitializeUSART() et/ou if( (usb_device_state < ....), mon COM3 est bien détecté et les commandes "r", "g" et "b" fonctionnent (je reçois l'acquittement dans Hyperterminal), seulement je visualise rien sur les leds vu que mon port n'est pas en sortie. Dès que réécris la ligne TRIS = 0, le COM3 n'est plus détecté (ou mal) !
Dans votre programme le fichier io_cfg.h n'est en plus pas sollicité, donc normalement pas de conflit possible au niveau de la config des ports entrées/sorties...
Je vous tiendrais au courant si évolution il y a.
Merci pour votre aide.
Bonjour,
Après de longues tentatives et de sérieuses prises de tête, j'ai enfin réussi à cerner le problème majeur (je devais avoir en plus des soucis de connectique USB) !
Je rectifie mon précédent post, dans la fonction principale (main.c), l'appel à InitializeSystem() sollicite bien le fichier io_cgf.h. Or dans ce dernier, il existe une section "USB" qui définit 2 paramètres sur PA1 et PA2 (configurés en entrée !). Il s'agit respectivement de "usb_bus_sense" et "self_power" qui dépendent de USE_USB_BUS_SENSE_IO et USE_SELF_POWER_SENSE_IO définis, eux, dans usbcfg.h. Je ne sais pas trop à quoi servent ces 2 paramètres et je me suis permis de supprimer leur définition pour ne plus risquer de conflit sur le port A du PIC. Depuis, l'USB est bien détecté et votre programme fonctionne à nouveau correctement (qui utilise PA0 et PA1 en sortie pour les leds rouge et verte).
Ceci devrait me permettre de poursuivre mon projet de sniffer réseau X25.
Je verrai en temps voulu si le débit full-speed de l'USB est exploité.
Merci pour votre montage. Cordialement.
Bonsoir Hervé,
Je vous dois des excuses. Vos conclusions m'ont rappelé des choses, et j'ai fait un diff complet de mon code par rapport à l'AN de Microchip... Bilan : j'avais bel et bien modifié usbcfg.h, dans lequel j'avais fait un #undef USE_USB_BUS_SENSE_IO ! Cela m'était sorti de la tête lorsque j'ai rédigé l'article.
USE_USB_BUS_SENSE_IO permet au firmware de désactiver l'USB lorsque le device est déconnecté. Pour cela, il faut (par exemple) relier le Vcc de l'USB à un port d'entrée du PIC, avec une résistance de pull-down. La valeur lue passe à 1 lorsqu'on branche le câble. Or la broche du PIC en question est celle sur laquelle j'ai mis une LED dans le montage... Cela explique donc le comportement complètement aléatoire que vous avez observé.
Je vais modifier l'article pour corriger ce point ! Merci de votre retour. Cordialement.
Bonjour
J'ai développé des application à base de PIC 16C745 que je désire migrer vers PIC 18F4550 ou mieux 18F2455. L'application microchip tourne très bien sur le 18F4550 mais sur le 2455, après un démarrage normal, le programme plante au bout de quelques secondes. Je pense pourtant avoir enlevé tout ce qui pouvait causer ce plantage ( Watch dog, MCLR... ) avec 20Mhz ou 4Mhz le résultat est le même. J'ai mis une capa de découplage + 1µf sur l'alim, rien n'y fait.
Si il n'y avait rien, je pouurai peut-être chercher mais un plantage au bout de 5 à 10s je ne sais pas.
Faut-il tirer le bus à 1 sur quel fil en full speed? Ce qui est le plus curieux c'est que sur le 18F4550 ça marche bien. Si vous avez une idée, je suis preneur.Merci
Alain
Si ça ne marchait pas du tout je pourrai peut-être chercher mais pla
Bonjour,
Je n'ai pas vraiment d'idée pour expliquer ce plantage... Essayez peut-être de mettre les mêmes directives de compilation que moi : est-ce que ça change quelque-chose ?
D'après « USB in a Nutshell », c'est D+ qu'il faut tirer à 3,3 V en full-speed. Mais le PIC comporte en interne les bonnes résistances de pull-up.
bonjour
j'ai un programme de controle pour un capteur avec un pic18F4550, le programme fonctionne bien mais je n'arrive pas monter en fréquence (12KHz max) avec la carte d'essai de microchip
existent-ils des configurations partculières pour augmenter la frequence
merci d'avance
Bonjour,
La fréquence du PIC dépend de deux choses : le quartz utilisé, et les directives de configuration données dans le programme. Je vous réfère à un autre article de ce blog, qui contient des explications et un programme d'exemple pour une configuration donnée. Cela devrait vous aider à comprendre comment cela fonctionne. Ensuite, avec les tableaux du manuel du PIC, vous devriez pouvoir vous en sortir.
Cordialement.
Bonjour,
Dans le cadre d'un projet, je dois communiquer entre mon PIC et mon PC. J'ai donc testé votre programme mais lorsque j'envoie le r avec l'hyperterminal, la led ne s'allume pas. De plus, dès que j'envoie une valeur, celle-ci mets renvoyé. Je ne comprend pas d'où vient le problème car j'utilise un 18f2455 avec un quartz 20MHz donc le programme devrai fonctionner.
Merci d'avance.
Bonjour Laurent,
Est-ce qu'au moins le PIC fonctionne ? Est-il bien détecté en USB, la LED clignote-t-elle correctement ? Vous êtes-vous bien connecté sur le bon port COM depuis l'Hyperterminal ? Si vous tapez une autre lettre que b, g ou r, avez-vous un message d'erreur ? (ce qui prouverait que la connexion USB fonctionne bien...). Pour le phénomène d'écho, c'est peut-être dû à une configuration de l'Hyperterminal (type « echo local »).
Bonjour,
Dans le cadre de mon stage j'ai fabriquè cette carte qui doit communiquer avec nimporte-quelle machine sous linux. Votre rubrique m'a beaucoup aidé. J'ai donc utilisé votre user.c en l'adaptant au port B (6 LED en vue de les remplacer par 3 moteur CC) mais cela fonctionne de façon aléatoire (sous windows comme sous linux), elle est reconnue quand elle veut... J'utilise un 18F4550, un quartz de 20MHz et une résistance de pull up entre D+ et le 3,3V. Je ne comprend pas d'ou vient ce problème.
Merci d'avance
Romain
Bonjour,
Je me suis appercu que lors du test « if( (usb_device_state < CONFIGURED_STATE) || (UCONbits.SUSPND==1) ) return; », j' ai usb_device_state < CONFIGURED_STATE donc on sort a ce momment la du programme. Je ne comprend pas trop pourquoi ce test n' est pas concluant, aurriez-vous une idee ?
Romain : usb_device_state contient un numéro qui croît lorsque le device passe par les étapes successives à partir de la connexion physique du périphérique. Pour avancer, il faudrait repérer le moment où cette variable n'est pas incrémentée normalement, cela donnerait une idée de ce qui ne va pas...
bon soir,
je suis un bricoleur et j'aimerai utilisé l'interface USB.
le pic que je vais utiliser est le 18F2550.
j'ai realisé la carte comme indiqué dans le schéma ci dessus avec les changement mentionné dans le programme(dans le fichier io_cfg.h j'ai changé le portD par le PORTB) pour l'adapté au PIC 18F2550.
la phase de compilation est faite sans erreur.
j'ai utilisé le winpic800 pour programer le pic.
le circuit que j'ai fait est identique a celle mentionné en haut (brochage du pic).
lorsque j'ai connecté ma carte au PC elle n'est pas reconnu par le pc "peripherique non reconnu".
S'il vous plait quelqu'un peut m'aider.
je peut vous envoyer le code que j'ai fait.
Bonjour,
Je cherche à communiquer avec un PIC18F26J50. J'ai réalisé un code à partir de l'exemple ci-dessus et de la doc Microchip. Lorsque je branche mon montage à l'ordi en USB, il détecte un périphérique USB mais au bout d'un moment il me marque "impossible d'installer le pilote". Même en le forçant à installer le bon pilote microchip, il refuse d'écouter et n'installe rien... J'ai tout essayé je ne sais plus quoi faire ! Avez vous déjà rencontré ce genre de soucis, avez vous des pistes pour résoudre ce soucis car là je suis bloqué !
Merci d'avance,
Thomas
Thomas :
Sous Windows, vous pouvez déjà vous assurer que le PIC est correctement reconnu en allant voir dans le gestionnaire de périphériques : est-ce que le périphérique apparaît, est-ce qu'il a le bon couple VID/PID. Si oui, c'est sûrement juste un problème de pilote.
Il faut bien dire qu'on veut installer le pilote manuellement, et lui montrer le fichier INF. Il faut aussi avoir la bonne version (je ne crois pas que ce soit la même version sous XP et Vista). J'ai récemment installé le pilote pour mon montage sous Vista : après un temps très long de recherche automatique sur Windows Update, l'assistant m'a proposé (dans des termes pas très clairs) de passer en mode manuel et j'ai pu lui montrer le fichier INF.
Bonjour Christophe et merci pour votre réponse.
J'ai enfin réussi à tout faire marcher. C'était en fait une mauvaise configuration de l'oscillateur du PIC ; il ne communiquais donc pas correctement. Dès que j'ai corrigé l'erreur, le montage a été détecté par le PC (comme avant) mais cette fois windows m'a demandé quel pilote je souhaitais installer et tout est rentré dans l'ordre.
Bonjour,
Je tente également d'établir une liaison série par le biais de l'USB pour pouvoir me familiariser avec le protocole sur les microcontrôleurs. J'ai donc suivi toutes les étapes décrites si dessus, mais lorsque je branche le cordon relié à la carte sur le PC, et bien le µcontroleur n'est pas detecté, rien ne se passe, la carte est juste alimentée en 5V...
Après quelques tests, j'ai pu voir que dans la fonction ProcessIO la fonction ne dépasse jamais ce test : if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;
J'ai vu que quelqu'un d'autre avait eu ce problème mais je n'ai pas bien compris la réponse de ChrisJ à ce sujet.
Merci d'avance.
BONJOUR,
je suis en stage dans une entreprise pour mon bts et je m'appuie sur votre prog pour mon proget
il y a deux erreur dans les config:
BORV ne peut être égal a 21 car il est def sur deux bits.
et se n'est pas FCMEM mais FCMEN
J'ai une application spécifique pour des personne handicapées qui tourne avec un PIC 16C745. Il s'agit d'une souris HID un peu spéciale...
Le soft est écrit en assembleur à partir d'un exemple microchip.
Que faut - il pour passer en PIC18F2550 ? Normalement il est compatible hard et soft or si je met directement mon .hex dans le 18F2550, ça ne marche pas...
J'utilise un PICstart plus pour programmer ou l'ICD2 pour programmer in situ les 18Fxx.
bjr tous le monde,j'ai entré par hasard a votre site,j'ai trouvé des choses très intéressantes.j'ai un projet et j'ai besoin d'aide.
mon projet consiste a réaliser un système de détection des trous entre un émetteur et récepteur infrarouge avec un pic.est ce que quelqu'un peut m'aider.
Merci d'avance
salut,comment programmer port usb pour qu'il prend de l'information d'une base de donnée à travers une application VB et l'envoyer vers une carte électronique auquel le circuit intégré PIC18F prend l'information et l'afficher au afficheur lcd ou 7-segment
Bonsoir Mr Jacquet, je me nomme Arnaud ,je suis étudiant en TELECOM et je réside à Abidjan en Côte d'ivoire. Je me suis familiarisé aux PIC16F puis PIC18F depuis 2 ans. Je dispose d'un PIC18F2455 dont je voudrais l'interfacer à un PC pour différentes applications. J'ai lu les démarches que vous avez décrites sur votre page mais je ne sais pas quel fichier HEX envoyé via le programmateur au PIC. SVP aidez moi. Merci d'avance.
Bonjour Arnaud,
Cela se passe « comme d'habitude » : vous écrivez votre programme, en C ou assembleur. Vous le compilez, ce qui vous donne un fichier HEX. Il ne vous reste plus alors qu'à programmer le PIC avec ce fichier HEX.
Il existe aussi une autre approche, que je n'ai jamais expérimentée personnellement : utiliser un bootloader. Ici le principe est de programmer le PIC une fois pour toutes avec le fichier HEX fourni avec le bootloader que vous choisissez. Ensuite, la programmation du PIC avec un programme « utilisateur » (votre HEX à vous) se fait via USB, en utilisant le logiciel de programmation propre au bootloader. Attention cependant, utiliser un bootloader impose certaines contraintes sur l'écriture des programmes utilisateur.
Bonjour ,
Je suis entrain de créer une carte électronique faisant la transcription de l'usb en port parallèle à travers un PIC18F4455.Suis-je obligé de mettre un dispositif pour éviter les surtensions entre le pic et le connecteur usb??
bonjour Mr jacquet j'ai besoin de votre aide je veux le code en C j'utilise le CCS pour la communication USB avec pic 18F4550 s'il vous plaît c urgent et merci d'avance
Le code C est sur cette page ; si vous suivez les indications vous devez y arriver !
Je te remercie fortement de faire partager ton expérience… mais on est un peut déférent , moi j’ai utiliser (CCS compiler, pic18f4550, labview, proteus) par simulation tout est fonctionnel, mais quant je met la carte réalisé au pc w7 ou xp, le message (périphérique non reconnu )apparait. mais moi j’ai utilisé USB-hid (pas CDC) aves vous une aidée ??
Cordialement
A+