Utilisation du stack USB CDC avec le PIC18F2550

Ayant eu envie de regarder le fonctionnement du bus 1 Wire et en particulier des sondes de températures de type DS18S20, je me suis trouvé devant le problème d'afficher les différents résultats.
N'ayant pas envie d'utiliser un afficheur LCD, je suis parti sur l'idée d'utiliser le stack USB gracieusement ...

Ayant eu envie de regarder le fonctionnement du bus 1 Wire et en particulier des sondes de températures de type DS18S20, je me suis trouvé devant le problème d'afficher les différents résultats.
N'ayant pas envie d'utiliser un afficheur LCD, je suis parti sur l'idée d'utiliser le stack USB gracieusement fourni par Microchip pour afficher les informations sur mon écran de PC. Le stack permet de choisir plusieurs modes de fonctionnement, le plus simple et le plus rapide à mettre en œuvre étant d'implémenter la partie CDC et d'afficher ainsi les résultats sur un simple écran "Hyper Terminal".

Configuration du projet.

Afin de simplifier les explications, j'utilise la suite d'outils Microchip (MPLAB IDE, C18 compileur) installée avec les paramètres et dossiers par défauts.
A l'origine, j'avais juste un fichier main.c contenant l'initialisation et la boucle principale du programme, et de deux fichiers (1wire.c et 1wire.h) pour la gestion de la communication One Wire.
J'ai commencé les tests en allumant une led si je détectai une sonde, et l'éteignai si je la déconnectai. J'ai vite rencontré le problème pour afficher l'identifiant de la sonde, ou même afficher la température.
Pour information, j'ai rencontré un soucis lors des premiers tests. J'avais ajouté les fichiers dans l'environnement de travail, mais j'avais oublié d'ajouter la directive #include "1wire.h" dans le fichier main.c. Le compilateur ne semblait absolument pas troublé par cet oubli, mais le programme ne fonctionnait pas. Le simple fait de corriger cette erreur a permit la détection de la sonde.

Ajout des chemins et fichiers nécessaires dans l'environnement de travail.

Pour créer un projet de base, il faut ajouter les fichiers sources et le fichier linker (.lkr) correspondant au type de micro contrôleur que vous allez utiliser.

project.png

N'oubliez pas de définir le chemin vers les librairies afin que le compilateur puisse trouver le fichier c018.o

lib.png

Par défaut, les fichiers de définitions du stack USB ne sont pas définis dans l'environnement. IL faut alors sélectionner l'option de menu "Projet", puis "Build Options" et sélectionner le projet.
Il faut ensuite ajouter le chemin pour trouver les fichiers include du stack USB

include.png

Ajout des fichiers des fonctions CDC.

Il suffit d'inclure le fichier *** dans le projet.

Construction des fichiers usb_config.c et usb_config.h.

Microchip fournit avec le stack un utilitaire permettant de construire ces deux fichiers permettant de configurer la connexion USB. Voici les copies d'écrans de ma configuration.
AttentionIl faut ensuite créer un fichier device_descriptor.c décrivant les structures ....
Pour l'instant, j'ai simplement récupérer celui d'un exemple. Il faut également créer un fichier "hardwareprofile.h" car il est systématiquement inclus dans les diverses sources fournies par Microchip.

Descriptions des registres de configuration.

Voici donc la configuration que j'utilise pour cette plaque de test :

#pragma config PLLDIV = 5 //Quartz à 20MHz, on le divise par 5 pour avoir 4 MHz pour alimenter la PLL
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2, en interne, je tourne à 48 MHz
#pragma config FOSC = HSPLL_HS
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = ON
#pragma config BORV = 3
#pragma config VREGEN = ON //USB Voltage Regulator
# pragma config WDT = OFF
#pragma config WDTPS = 32768
#pragma config MCLRE = ON
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF

Utilisation de la classe CDC

En tout premier lieu, il faut appeler la fonction USBDeviceInit().
Cette fonction est en général appelé dans la fonction d'initialisation de votre programme.
Dans la boucle principale de votre programme, il faut appeler périodiquement la fonction USBDeviceTasks().
Je travaille en mode polling. Tant que la variable USBDeviceState n'a pas la valeur CONFIGURED_STATE, vous ne pouvez pas utiliser les fonction USB.Avant de lire ou écrire quelque chose, il faut appeler la fonction mUSBUSARTIsTxTrfReady().

Un exemple valant mieux qu'un long discours, voici un exemple de programme :

   while(1)
    {
        USBDeviceTasks();
        cPresent = ResetAndPresence();
        //Tant que l'usb n'est pas configuré, on repart au début de la boucle
        if((USBDeviceState < CONFIGURED_STATE )||( USBSuspendControl == 1)) continue;
        if( mUSBUSARTIsTxTrfReady() )
        {
            cCompt = getsUSBUSART(USB_Out_Buffer,64);
            //On a lu au moins 1 caratère 
            if(cCompt != 0)
            {
                switch(USB_Out_Buffer[0])
                {
                    case 'p':
                    case 'P':
                        cPresent = ResetAndPresence();
                        if(cPresent == 1)
                        {
                            putrsUSBUSART("Device Ready\r\n");
                        }
                        else
                        {
                            putrsUSBUSART("Device not present\r\n");
                        }
                    break;
                    case 'c':
                    case 'C':
                        ResetAndPresence();
                        SkipRomCommand();
                        StartConvert();
                        putrsUSBUSART("Convertion\r\n");
                    break;
                    case 'r':
                    case 'R':
                        ResetAndPresence();
                        ReadRom();
                        for(cCompt = 0; cCompt < 8; cCompt++)
                        {
                            OneWireRead[cCompt] = ReadByte();
                        }
                        //On affiche les 2 premiers bytes
                        sprintf(USB_In_Buffer,"%#04x %#04x\r\n",OneWireRead[0],OneWireRead[1]); 
                        putsUSBUSART(USB_In_Buffer);
                    break;
                    case 't':
                    case 'T':
                        ResetAndPresence();
                        SkipRomCommand();
                        WriteByte(0xBE);
                        for(cCompt = 0; cCompt < 9; cCompt++)
                        {
                            OneWireRead[cCompt] = 0x31;
                            OneWireRead[cCompt] = ReadByte();
                        }
                        //On affiche les 2 premiers bytes 
                        sprintf(USB_In_Buffer,"%#04x %#04x n",OneWireRead[0],OneWireRead[1]);
                        putsUSBUSART(USB_In_Buffer);
                    break;
                    default:
                        putrsUSBUSART("Unknow command\r\n");
                    break;
                }
            }
        }
        //Il faut toujours appeler cette fonction
        CDCTxService();
    }

Haut de page