Pouvoir contrôler des processus extérieurs via une carte USB était un projet qui me bottait, je me suis donc lancé dans une première carte permettant de contrôler 16 entrées/sorties, et 4 entrées analogiques. Je préfère préciser tout de suite, qu'il s'agit d'un premier développement en USB, et que le terme USB ne signifie pas que la carte est ultra rapide.

Le port USB étant un port particulier, il ne peut pas être utilisé comme le port parallèle, il est nécessaire d'avoir une puce qui puisse traiter la communication, recevoir les packets et en renvoyer. La première étape était donc de trouver une puce… Ma recherche s'est directement orientée vers Microchip® car je possède un programmateur. La puce retenue est un 18f4550 très simple à mettre en œuvre. En effet 4 capacités, 1 quartz, 3 résistances suffisent pour la faire fonctionner.

schema18f4550

Au centre du schéma, nous retrouvons le PIC18F4550, celui-ci est cadencé par un quartz à 20MHz. Nous avons aussi câblé sur ce schéma 4 entrées analogiques: AN0, AN1, AN2 et AN3. Sur les broches RC0 et RC1 nous plaçons deux leds qui nous servirons pour notre application. Sur la broche RC2 un switch qui servira aussi pour cet exemple. Le port B et D restent inutilisés pour notre article mais nous plaçons la possibilité d'étendre les fonctionnalités de la carte en installant des borniers.

Les capacités C1 et C2 sont de 22pf. Pour R5, R3, R4, R7 nous placerons simplement des résistances de 1k. Attention de ne pas se tromper pour le connecteur USB. Il s'agit d'un connecteur femelle de Type B. Pour la connecter au PC, j'utilise un cordon d'imprimante A vers B, le même que les cordons HP.

Le Firmware

On peut trouver sur le site de microchip des exemples de programmes pour le 18f4550. Il existe trois méthodes pour mettre en œuvre cette puce USB, soit d'utiliser le driver HID (Human interface device, qui est le protocole utilisé dans tout ce qui est souris, clavier, gamepad), soit un driver qui simule le port Com qui rend alors facilement toutes les applications qui fonctionnaient sur port série convertissable en USB sans devoir changer le programme qui l'utilise, soit un driver de Microchip mpusbapi.dll. L'option retenue est cette dernière.

Pour communiquer avec l'ordinateur, la puce échange avec celui-ci un packet d'octet. L'idée pour cette première carte n'est pas d'envoyer un packet par instruction mais d'envoyer une série d'instructions en même temps. Une instruction est par exemple de changer l'état d'un des port, de lancer une conversion analogique vers numérique, de modifier les paramètre des convertisseur, d'effectuer une pause d'autant de nano secondes.

Je me suis donc basé sur un programme d'exemple de microchip pour écrire un premier code. Pour écrire ce code il est impératif d'avoir MPLab muni du compilateur C18 disponible gratuitement pour les étudiants.

L'ordinateur envoie un packet de 64octets au 18f4550, chaque octet est soit une instruction (les codes de celles-ci plus bas) soit le ou les paramètres de ces instructions. Le premier octet est toujours une instruction, les octets suivants ses paramètres, le dernier paramètre est suivi de l'instruction suivante.

Les instructions

0 : rien
1 à 5 suivit d'un paramètre : attribue le paramètre au registre TRIS[A..E]
6 à 10 suivit d'un paramètre : attribue le paramètre au registre PORT[A..E]
11 à 15 suivit d'un paramètre : attribue le paramètre au registre LAT[A..E]
16 à 20 suivit d'un paramètre : ajoute le paramètre au registre TRIS[A..E]
21 à 25 suivit d'un paramètre : ajoute le paramètre au registre PORT[A..E]
26 à 30 suivit d'un paramètre : ajoute le paramètre au registre LAT[A..E]
31 à 35 suivit d'un paramètre : retire le paramètre au registre TRIS[A..E]
36 à 40 suivit d'un paramètre : retire le paramètre au registre PORT[A..E]
41 à 45 suivit d'un paramètre : retire le paramètre au registre LAT[A..E]

50 suivit de trois paramètre : conversion analogique vers numérique sur
l'entrée donnée par le paramètre 1, le paramètre 2 recevra le registre ADRSH
et le paramètre 3 recevra ADRSL. La configuration de la conversion est :

/* 12 TAD FOSC/32 */
ADCON2=42;
/* AN0-15, VREF */
ADCON1 = 0b00001011;
/* Turn on the ADC */
ADCON0bits.ADON = 1;
ADCON0bits.CHS3 = 0;
ADCON0bits.CHS2 = 0;

51 suivit de trois paramètres : conversion analogique vers numérique sur

l'entrée donnée par le paramètre 1, le paramètre 2 recevra le registre ADRSH

et le paramètre 3 recevra ADRSL. La configuration de la conversion aura pu

être configurée préalablement par l'utilisateur, a noter que cette configuration

restera enregistrée tant que la puce sera sous tension et que l'instruction 50

ne sera pas appelée.

52 à 54 suivit d'un paramètre : attribue le paramètre au registre ADCON[0..2]

60 suivit d'un paramètre : effectue une pause de 10 * le paramètre * 200ns.
61 suivit d'un paramètre : effectue une pause de 100 * le paramètre * 200ns.
62 suivit d'un paramètre : effectue une pause de 1000 * le paramètre * 200ns.

101 à 105 suivit d'un paramètre : attribue le registre TRIS[A..E] au paramètre
106 à 110 suivit d'un paramètre : attribue le registre PORT[A..E] au paramètre
111 à 115 suivit d'un paramètre : attribue le registre LAT[A..E] au paramètre

Logiciel

logiciel

Point de vue du logiciel pour la contrôler, j'ai préparer un petit exemple en Delphi. Le programme permet d'envoyer 20 octets à la carte, on peut envoyer 64 octets, mais pour cela fallait que j'ajoute beaucoup de spinedit, et franchement, ça devenait long ;).

La fonction la plus intéressante de ce programme est :

SendReceivePacket(@send_buf,64,@receive_buf,RecvLength,100,100)

Cette fonction envoie en premier paramètre l'adresse d'un tableau de 64 éléments qui contient les octets à envoyer, le deuxième paramètre contient le nombre d'octets à envoyer, attention ne pas changer ces paramètres, le firmware est fait pour recevoir 64 octet et en renvoyer 64. Le troisième paramètre est l'adresse du tableau qui va recevoir les données de la carte, le cinquième est le nombre de données qui doivent être reçues, soit 64. Et les deux derniers sont les délais maximum que l'on veut bien attendre pour envoyer et pour recevoir. Ici les délais sont de 100ms, si vous décidez d'utiliser beaucoup de fois des fonctions pauses il est préférable de monter ce délai à 1000ms.

Une fois les informations envoyées, le résultat apparaît à l'écran dans le MemoText.

On peut aussi remarquer dans le programme, cette ligne-ci :

Const vid_pid : PCHAR = 'vid_04d8&pid_000b' + #0;

Il s'agit d'une ligne très importante, tous les périphériques USB possèdent deux numéros, le Vendor ID et le Product ID, ils permettent de différencier les différents produits USB, attribuer à chaque carte son driver, que chaque programme communique avec le bon périphérique sans mélanger les informations. Dans notre cas, c'est 04d8 et 000b, nous y reviendrons prochainement lors du montage de la carte.

Les codes sources du programme et du firmware sont disponibles en téléchargement, il m'est très compliqué d'en expliquer l'intégralité.