Étape 5: Comprendre le code USB
C’est là le plaisir commence!Si vous êtes venu à ce jour, vous devriez avoir un écran qui dit « Afficher initialisé » lorsque vous mettez l’appareil.
Si vous ne l’avez pas déjà fait, téléchargez le code source attaché à cette instructable, et nous devrons regarder de plus près sur la manière dont l’AVR communique avec l’écran et l’ordinateur.
Si vous n’avez jamais travaillé avec V-USB avant, il peut être très déroutant au début. Au moins, c’était pour moi. Faites défiler jusqu'à la fonction usbFunctionSetup et nous aurons un examen approfondi sur la façon dont il fonctionne réellement. Il s’agit de la seule fonction que vous avez besoin de soin sur la modification en dehors de la fonction principale.
usbFunctionSetup est la fonction où vous traitez toutes les données que j’ai envoyé au microcontrôleur via le port USB. Si vous remarquez les instructions IF, ils ont tous vérifient un numéro spécifique à la variable rq -> bRequest . Ce i où sont stockés les codes de la demande. Des codes de demande, vous pouvez considérer comme des commandes. Le logiciel hôte, nous avons une fonction comme ceci : SendData (int demande, données), la valeur que vous mettez dans le paramètre de demande sera transférée au microcontrôleur et stockée dans la rq -> bRequest variable, et vous utilisez ce code demande de faire des choses différentes dans l’usbFunctionSetup.
Je ne font qu’ajouter 6 codes de demande, mais si vous voulez faire un 7e demander code simplement tapez ceci dans un endroit dans la fonction usbFunctionSetup :
Si la demande est 7
si (rq -> bRequest == 7) {/ / commande 7 - SEND_MYCOMMAND
Faire mon code
}
Si vous appelez maintenant la fonction SendData comme ceci : SendData (7, 0) ;
L’instruction IF, que vous venez de créer s’exécute.
Le 2ème paramètre dans la fonction SendData est les données réelles que vous envoyez au microcontrôleur. Ce nombre sera stocké dans le struct rq -> wValue . Il s’agit d’un mot (2 octets), mais si vous voulez seulement utiliser 1 des 2 octets stockés ici, vous pouvez le faire en utilisant le tableau d’octets, comme ceci : rq -> wValue.bytes[0]. Si vous ne souhaitez pas utiliser le mot entier, vous pouvez y accéder comme ceci : rq -> wValue.word. Notez que vous devez utiliser un unsigned int si vous souhaitez utiliser le mot entier.
Vous devriez mettre des fonctions avancées qui prennent beaucoup de temps à faire à l’extérieur de la fonction usbFunctionSetup et à la place de laisser la boucle principale les exécuter. Si vous les avez dans l’usbFunctionSetup et ils utilisent beaucoup de temps pour terminer (50ms), vous risquez de perdre la connexion USB à l’ordinateur. J’ai choisi de les faire dans l’usbFunctionSetup, parce que l’écriture à l’écran est beaucoup plus rapide que l’USB (en fait, nous écrivons un stable 1, 33Mbit/s à l’écran et l’affichage prend en charge jusqu'à 4Mbits/s) donc je ne risque pas de perdre la connexion en prenant trop de temps.
Le reste du code doit être placé en commentaire assez pour que vous compreniez. Si quelque chose n’est pas clair, faites le moi savoir et je vais essayer d’effacer des choses pour vous.