La derniere version de ce tuto est disponible sur le WIKI
La classe CDC permet d’établir une communication série (RS232) via l’USB du microcontrôleur.
La liaison sera équivalente à une liaison UART avec les contrôles de flux en plus.
Créer un projet ASF et ajouter la librairie USB Device (service) dans le menu déroulant, sélectionner “cdc”
La première chose à faire est de configurer l’horloge. Pour fonctionner, le module USB a besoin d’une horloge de 12 ou 48Mhz. L’oscillateur interne de 32Mhz sera utilisé. En effet sa fréquence peut être réglée entre 30 et 55Mhz grâce à une PLL numérique. Nous allons donc le faire fonctionner à 48Mhz et nous utiliserons une prédiviseur /2 pour fournir une horloge de 24Mhz au CPU.
Editer le fichier conf_clock.h et supprimer toutes les lignes et mettez à la place :
#ifndef CONF_CLOCK_H_INCLUDED #define CONF_CLOCK_H_INCLUDED //Horloge USB #define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC //Choix de l'horloge interne pour l'USB #define CONFIG_OSC_RC32_CAL 48000000UL //Calibration de l'horloge pour qu'elle fonctionne à 48Mhz #define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC OSC_ID_USBSOF //Utilisation d'une calibration automatique lors de la reception de la premiere trame USB //Horloge CPU qui doit être > à 12Mhz pour les applications USB #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC32MHZ //Choix de l'horloge interne (qui fonctionne à 48Mhz) #define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_2 //Prescaler A divise la fréquence par 2 = 24Mhz #define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1 //Prescaler B pas de division. Donc le CPU fonctionne à 24Mhz #endif /* CONF_CLOCK_H_INCLUDED */
Ajouter au début du main, les lignes d’initialisation suivantes :
//Initialisation système sysclk_init(); irq_initialize_vectors(); cpu_irq_enable(); board_init();
Nous allons maintenant nous occuper de la configuration USB. Informations qui seront transmises au controleur USB du PC afin de pouvoir identifier notre carte. Ouvrez le fichier conf_usb.f et indiquer les informations suivantes :
#define USB_DEVICE_VENDOR_ID USB_VID_ATMEL //VID ATMEL #define USB_DEVICE_PRODUCT_ID USB_PID_ATMEL_ASF_CDC //PID CDC #define USB_DEVICE_MAJOR_VERSION 1 //Version du périphérique #define USB_DEVICE_MINOR_VERSION 0 #define USB_DEVICE_POWER 100 //Consommation de notre carte #define USB_DEVICE_ATTR USB_CONFIG_ATTR_BUS_POWERED //La carte est alimentée par le bus USB
Chaque fabricant de périphérique achete auprès d’usb.org des plages identifiants uniques qui permettent à votre ordinateur de l’identifier et charger le driver adéquate. C’est identifiant est composé d’un VID vendor ID USB_DEVICE_VENDOR_ID (Numéro d’identification du fabricant) et d’un PID product ID USB_DEVICE_PRODUCT_ID (Numéro d’identification du produit). Si vous souhaitez avoir votre propre VID/PID, il vous en coutera environ 2000$. En attendant, nous allons garder les VID/PID d’Atmel.
La ligne suivante indique quelle version USB utiliser 1,2 etc …
USB_DEVICE_POWER sera la valeur de consommation de courant max de notre carte. Cette information sera transmise au PC afin qu’il adapte sa gestion de courant.
USB_DEVICE_ATTR indique au contrôleur si le périphérique s’alimente via le port USB ou s’il dispose d’une alimentation indépendante. Dans notre cas, il sera alimenté par le port USB.
Puis ajouter la ligne ci dessous dans votre fichier main.c pour démarrer la pile USB
udc_start();
A ce stade, votre PC doit déjà pouvoir détecter votre carte et installer les drivers.
Nous allons voir maintenant comment envoyer et recevoir des données via cette connexion. Aller dans le fichier conf_usb.f et modifier les lignes suivantes :
//! Interface callback definition #define UDI_CDC_ENABLE_EXT(port) callback_cdc_enable() extern bool callback_cdc_enable(void); #define UDI_CDC_DISABLE_EXT(port) callback_cdc_disable() extern void callback_cdc_disable(void);
Les fonctions callback_cdc_enable et callback_cdc_disable seront appelés dès que la connexion sera établie ou rompue.
Vérifier également les lignes suivantes qui definissent le débit de la liaison :
//! Define it when the transfer CDC Device to Host is a low rate (<512000 bauds) //! to reduce CDC buffers size #define UDI_CDC_LOW_RATE //! Default configuration of communication port #define UDI_CDC_DEFAULT_RATE 115200 #define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 #define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE #define UDI_CDC_DEFAULT_DATABITS 8
Vous pouvez augmenter le baudrate jusqu’à 512 200 bauds. Au delà, il vous suffit de commenter la ligne #define UDI_CDC_LOW_RATE pour aller plus haut. Il faut savoir sur le debit est limité par la vitesse du CPU et par les fonctions utilisés. Atmel fournit un document montrant les limites de fonctionnement. On peut voir figure 6-4 qu’en utilisant les fonctions ReadBuf et WriteBuf qu’il est possible de monter jusqu’à environ 900Kbauds/s.
Dans votre fichier main.c ajouter les deux callback et le petit bout de code suivant qui renvoi “ok 1” dès que vous taper “1” et “error” si vous envoyé n’importe quoi d’autre.
#include <asf.h> static bool flag_autorize_cdc_transfert = false; //Flag d'autorisation de transfert envoyé par l'hote. char ch; //Caractère reçu //Lors de l'établissement de la connexion bool callback_cdc_enable(void) { flag_autorize_cdc_transfert = true; return true; } //Lors de la deconnexion void callback_cdc_disable(void) { flag_autorize_cdc_transfert = false; } int main (void) { //Initialisation système sysclk_init(); irq_initialize_vectors(); cpu_irq_enable(); board_init(); //Démarrage de l'USB udc_start(); while(1) { if (udi_cdc_is_rx_ready() && flag_autorize_cdc_transfert) //Si la transmission est autorisé et si nous avons reçu quelque chose { ch = udi_cdc_getc(); switch(ch) { case '1': udi_cdc_write_buf("ok 1\r\n", 6); break; default : udi_cdc_write_buf("error\r\n", 7); break; }; } } }
Brancher, Compiler, programmer démarrer votre terminal préféré (Hyperterminal, putty, etc …). Indiquer le port COM de votre carte et le débit (115200) :
et taper 1 ou autre chose
j’ai suivi les memes instructions mais ça ne marche pas
j’ai aucun message de retour sur l’hyperteminal et quand je debug ch=0 toujours