{"id":68,"date":"2014-08-24T10:34:43","date_gmt":"2014-08-24T09:34:43","guid":{"rendered":"http:\/\/www.jelectronique.com\/?p=68"},"modified":"2014-08-30T13:23:27","modified_gmt":"2014-08-30T12:23:27","slug":"tuto-asf-connexion-usb-cdc-avec-votre-xmega","status":"publish","type":"post","link":"https:\/\/www.jelectronique.com\/?p=68","title":{"rendered":"TUTO XMEGA (ASF) : Connexion USB CDC avec votre XMEGA"},"content":{"rendered":"<blockquote><p>La derniere version de ce tuto est disponible sur le <a href=\"http:\/\/wiki.jelectronique.com\/doku.php?id=avr_studio_6&amp;#usb\">WIKI <\/a><\/p><\/blockquote>\n<p>La classe CDC permet d\u2019\u00e9tablir une communication s\u00e9rie (RS232) via l&rsquo;USB du microcontr\u00f4leur.<br \/>\nLa liaison sera \u00e9quivalente \u00e0 une liaison UART avec les contr\u00f4les de flux en plus.<\/p>\n<p>Cr\u00e9er un projet ASF et ajouter la librairie USB Device (service) dans le menu d\u00e9roulant, s\u00e9lectionner \u201ccdc\u201d<\/p>\n<p><a title=\"avr_studio_asf_usb.png\" href=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/detail.php?id=avr_studio_6&amp;media=avr_studio_asf_usb.png\"><img decoding=\"async\" src=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/fetch.php?w=800&amp;tok=0ec4fd&amp;media=avr_studio_asf_usb.png\" alt=\"\" width=\"800\" \/><\/a><\/p>\n<p>La premi\u00e8re chose \u00e0 faire est de configurer l&rsquo;horloge. Pour fonctionner, le module USB a besoin d&rsquo;une horloge de 12 ou 48Mhz. L&rsquo;oscillateur interne de 32Mhz sera utilis\u00e9. En effet sa fr\u00e9quence peut \u00eatre r\u00e9gl\u00e9e entre 30 et 55Mhz gr\u00e2ce \u00e0 une PLL num\u00e9rique. Nous allons donc le faire fonctionner \u00e0 48Mhz et nous utiliserons une pr\u00e9diviseur \/2 pour fournir une horloge de 24Mhz au CPU.<\/p>\n<p>Editer le fichier conf_clock.h et supprimer toutes les lignes et mettez \u00e0 la place :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#ifndef CONF_CLOCK_H_INCLUDED\r\n#define CONF_CLOCK_H_INCLUDED\r\n\r\n\/\/Horloge USB\r\n#define CONFIG_USBCLK_SOURCE     USBCLK_SRC_RCOSC\t\t\/\/Choix de l'horloge interne pour l'USB\r\n#define CONFIG_OSC_RC32_CAL      48000000UL\t\t\t\/\/Calibration de l'horloge pour qu'elle fonctionne \u00e0 48Mhz\r\n#define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC  OSC_ID_USBSOF\t\/\/Utilisation d'une calibration automatique lors de la reception de la premiere trame USB\t\r\n\r\n\/\/Horloge CPU qui doit \u00eatre &gt; \u00e0 12Mhz pour les applications USB\r\n#define CONFIG_SYSCLK_SOURCE     SYSCLK_SRC_RC32MHZ\t\t\/\/Choix de l'horloge interne (qui fonctionne \u00e0 48Mhz)\r\n#define CONFIG_SYSCLK_PSADIV     SYSCLK_PSADIV_2\t\t\/\/Prescaler A divise la fr\u00e9quence par 2 = 24Mhz\r\n#define CONFIG_SYSCLK_PSBCDIV    SYSCLK_PSBCDIV_1_1\t\t\/\/Prescaler B pas de division. Donc le CPU fonctionne \u00e0 24Mhz\r\n\r\n#endif \/* CONF_CLOCK_H_INCLUDED *\/\r\n<\/pre>\n<p>Ajouter au d\u00e9but du main, les lignes d&rsquo;initialisation suivantes :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/Initialisation syst\u00e8me\r\nsysclk_init();\r\nirq_initialize_vectors();\r\ncpu_irq_enable();\r\n\r\nboard_init();<\/pre>\n<p>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 :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">#define  USB_DEVICE_VENDOR_ID        USB_VID_ATMEL\t\t\/\/VID ATMEL\r\n#define  USB_DEVICE_PRODUCT_ID            USB_PID_ATMEL_ASF_CDC\t\t\/\/PID CDC\r\n#define  USB_DEVICE_MAJOR_VERSION         1\t\t\t\t\/\/Version du p\u00e9riph\u00e9rique\r\n#define  USB_DEVICE_MINOR_VERSION         0\r\n#define  USB_DEVICE_POWER                 100\t\t\t\t\/\/Consommation de notre carte\r\n#define  USB_DEVICE_ATTR                  USB_CONFIG_ATTR_BUS_POWERED\t\/\/La carte est aliment\u00e9e par le bus USB<\/pre>\n<p>Chaque fabricant de p\u00e9riph\u00e9rique achete aupr\u00e8s d&rsquo;usb.org des plages identifiants uniques qui permettent \u00e0 votre ordinateur de l&rsquo;identifier et charger le driver ad\u00e9quate. C&rsquo;est identifiant est compos\u00e9 d&rsquo;un VID vendor ID USB_DEVICE_VENDOR_ID (Num\u00e9ro d&rsquo;identification du fabricant) et d&rsquo;un PID product ID USB_DEVICE_PRODUCT_ID (Num\u00e9ro d&rsquo;identification du produit). Si vous souhaitez avoir votre propre VID\/PID, il vous en coutera environ 2000$.<img decoding=\"async\" src=\"http:\/\/wiki.jelectronique.com\/lib\/images\/smileys\/icon_cool.gif\" alt=\"8-)\" \/> En attendant, nous allons garder les VID\/PID d&rsquo;Atmel. <img decoding=\"async\" src=\"http:\/\/wiki.jelectronique.com\/lib\/images\/smileys\/icon_wink.gif\" alt=\";-)\" \/><\/p>\n<div>Si vous souhaitez faire des essais avec des VIP\/PID diff\u00e9rents, vous pouvez utiliser ceux de <a title=\"http:\/\/www.fourwalledcubicle.com\/files\/LUFA\/Doc\/130303\/html\/_page__v_i_d_p_i_d.html\" href=\"http:\/\/www.fourwalledcubicle.com\/files\/LUFA\/Doc\/130303\/html\/_page__v_i_d_p_i_d.html\" rel=\"nofollow\">LUFA<\/a> qui ont \u00e9t\u00e9 donn\u00e9s par ATMEL. Il est totalement interdit d&rsquo;utiliser ces PID dans un autre cadre que le test. J&rsquo;ai \u00e9galement lu que certains fabricants en fournissent \u00e0 leurs clients sur demande (Microchip, FTDI)<\/div>\n<p>La ligne suivante indique quelle version USB utiliser 1,2 etc \u2026<\/p>\n<p>USB_DEVICE_POWER sera la valeur de consommation de courant max de notre carte. Cette information sera transmise au PC afin qu&rsquo;il adapte sa gestion de courant.<\/p>\n<p>USB_DEVICE_ATTR indique au contr\u00f4leur si le p\u00e9riph\u00e9rique s&rsquo;alimente via le port USB ou s&rsquo;il dispose d&rsquo;une alimentation ind\u00e9pendante. Dans notre cas, il sera aliment\u00e9 par le port USB.<\/p>\n<p>Puis ajouter la ligne ci dessous dans votre fichier main.c pour d\u00e9marrer la pile USB<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">udc_start();<\/pre>\n<p>A ce stade, votre PC doit d\u00e9j\u00e0 pouvoir d\u00e9tecter votre carte et installer les drivers.<\/p>\n<p><a title=\"xmega_usb_detected.png\" href=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/detail.php?id=avr_studio_6&amp;media=xmega_usb_detected.png\"><img decoding=\"async\" src=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/fetch.php?w=300&amp;tok=29e493&amp;media=xmega_usb_detected.png\" alt=\"\" width=\"300\" \/><\/a><\/p>\n<p><a title=\"xmega_usb_detected2.png\" href=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/detail.php?id=avr_studio_6&amp;media=xmega_usb_detected2.png\"><img decoding=\"async\" src=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/fetch.php?w=600&amp;tok=a5886f&amp;media=xmega_usb_detected2.png\" alt=\"\" width=\"600\" \/><\/a><\/p>\n<p>Nous allons voir maintenant comment envoyer et recevoir des donn\u00e9es via cette connexion. Aller dans le fichier conf_usb.f et modifier les lignes suivantes :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/! Interface callback definition\r\n#define  UDI_CDC_ENABLE_EXT(port)\tcallback_cdc_enable()\r\nextern bool callback_cdc_enable(void);\r\n#define  UDI_CDC_DISABLE_EXT(port)\tcallback_cdc_disable()\r\nextern void callback_cdc_disable(void);<\/pre>\n<p>Les fonctions callback_cdc_enable et callback_cdc_disable seront appel\u00e9s d\u00e8s que la connexion sera \u00e9tablie ou rompue.<\/p>\n<p>V\u00e9rifier \u00e9galement les lignes suivantes qui definissent le d\u00e9bit de la liaison :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/! Define it when the transfer CDC Device to Host is a low rate (&lt;512000 bauds)\r\n\/\/! to reduce CDC buffers size\r\n#define  UDI_CDC_LOW_RATE\r\n\r\n\/\/! Default configuration of communication port\r\n#define  UDI_CDC_DEFAULT_RATE             115200\r\n#define  UDI_CDC_DEFAULT_STOPBITS         CDC_STOP_BITS_1\r\n#define  UDI_CDC_DEFAULT_PARITY           CDC_PAR_NONE\r\n#define  UDI_CDC_DEFAULT_DATABITS         8<\/pre>\n<p>Vous pouvez augmenter le baudrate jusqu&rsquo;\u00e0 512 200 bauds. Au del\u00e0, il vous suffit de commenter la ligne #define UDI_CDC_LOW_RATE pour aller plus haut. Il faut savoir sur le debit est limit\u00e9 par la vitesse du CPU et par les fonctions utilis\u00e9s. Atmel fournit <a title=\"http:\/\/www.atmel.com\/Images\/doc8410.pdf\" href=\"http:\/\/www.atmel.com\/Images\/doc8410.pdf\" rel=\"nofollow\">un document montrant les limites de fonctionnement<\/a>. On peut voir figure 6-4 qu&rsquo;en utilisant les fonctions ReadBuf et WriteBuf qu&rsquo;il est possible de monter jusqu&rsquo;\u00e0 environ 900Kbauds\/s.<\/p>\n<p>Dans votre fichier main.c ajouter les deux callback et le petit bout de code suivant qui renvoi \u201cok 1\u201d d\u00e8s que vous taper \u201c1\u201d et \u201cerror\u201d si vous envoy\u00e9 n&rsquo;importe quoi d&rsquo;autre.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">#include &lt;asf.h&gt;\r\n\r\nstatic bool flag_autorize_cdc_transfert = false; \/\/Flag d'autorisation de transfert envoy\u00e9 par l'hote.\r\nchar ch;\t\t\t\t\t\t\t\t\t\t\/\/Caract\u00e8re re\u00e7u\r\n\r\n\/\/Lors de l'\u00e9tablissement de la connexion\r\nbool callback_cdc_enable(void)\r\n{\r\n\tflag_autorize_cdc_transfert = true;\r\n\r\n\treturn true;\r\n}\r\n\/\/Lors de la deconnexion\r\nvoid callback_cdc_disable(void)\r\n{\r\n\tflag_autorize_cdc_transfert = false;\r\n}\r\n\r\nint main (void)\r\n{\r\n\t\/\/Initialisation syst\u00e8me\r\n\tsysclk_init();\r\n\tirq_initialize_vectors();\r\n\tcpu_irq_enable();\r\n\r\n\tboard_init();\r\n\r\n\t\/\/D\u00e9marrage de l'USB\r\n\tudc_start(); \r\n\r\n\twhile(1)\r\n\t{\r\n\t\tif (udi_cdc_is_rx_ready() &amp;&amp; flag_autorize_cdc_transfert) \/\/Si la transmission est autoris\u00e9 et si nous avons re\u00e7u quelque chose\r\n\t\t{\r\n\t\t\tch = udi_cdc_getc();\r\n\t\t\tswitch(ch)\r\n\t\t\t{\r\n\t\t\t\tcase '1':\r\n\t\t\t\t\tudi_cdc_write_buf(&quot;ok 1\\r\\n&quot;, 6);\r\n\t\t\t\tbreak;\r\n\t\t\t\tdefault :\r\n\t\t\t\t\tudi_cdc_write_buf(&quot;error\\r\\n&quot;, 7);\r\n\t\t\t\tbreak;\r\n\t\t\t};\r\n\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>Brancher, Compiler, programmer d\u00e9marrer votre terminal pr\u00e9f\u00e9r\u00e9 (Hyperterminal, putty, etc \u2026). Indiquer le port COM de votre carte et le d\u00e9bit (115200) :<\/p>\n<p><a title=\"xmega_usb_cdc_putty.png\" href=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/detail.php?id=avr_studio_6&amp;media=xmega_usb_cdc_putty.png\"><img decoding=\"async\" src=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/fetch.php?w=300&amp;tok=ae9999&amp;media=xmega_usb_cdc_putty.png\" alt=\"\" width=\"300\" \/><\/a><\/p>\n<p>et taper 1 ou autre chose<\/p>\n<p><a title=\"xmega_usb_cdc_putty2.png\" href=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/detail.php?id=avr_studio_6&amp;media=xmega_usb_cdc_putty2.png\"><img decoding=\"async\" src=\"http:\/\/wiki.jelectronique.com\/lib\/exe\/fetch.php?w=500&amp;tok=93e325&amp;media=xmega_usb_cdc_putty2.png\" alt=\"\" width=\"500\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>La derniere version de ce tuto est disponible sur le WIKI La classe CDC permet d\u2019\u00e9tablir une communication s\u00e9rie (RS232) via l&rsquo;USB du microcontr\u00f4leur. La liaison sera \u00e9quivalente \u00e0 une liaison UART avec les contr\u00f4les de flux en plus. Cr\u00e9er&hellip; <a href=\"https:\/\/www.jelectronique.com\/?p=68\" class=\"more-link\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":69,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-68","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-electronique"],"_links":{"self":[{"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=\/wp\/v2\/posts\/68","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=68"}],"version-history":[{"count":11,"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=\/wp\/v2\/posts\/68\/revisions"}],"predecessor-version":[{"id":105,"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=\/wp\/v2\/posts\/68\/revisions\/105"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=\/wp\/v2\/media\/69"}],"wp:attachment":[{"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=68"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=68"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jelectronique.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=68"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}