{"id":129,"date":"2017-11-29T01:33:28","date_gmt":"2017-11-29T01:33:28","guid":{"rendered":"http:\/\/marcjuneau.ca\/?p=129"},"modified":"2017-12-06T21:10:32","modified_gmt":"2017-12-06T21:10:32","slug":"avr-uart-avec-un-arduino-uno","status":"publish","type":"post","link":"https:\/\/marcjuneau.ca\/?p=129","title":{"rendered":"AVR USART avec un Arduino UNO"},"content":{"rendered":"<p>Cet article explique comment utiliser le lien\u00a0s\u00e9rie asynchrone (lire USART) pr\u00e9sent sur le Atmega328p du Arduino UNO.<\/p>\n<p>Dans cet article, nous utiliserons une boucle pour la transmission et la r\u00e9ception des octets. Je ferai un autre article qui expliquera comment faire avec les interruptions, ce qui est recommand\u00e9 afin de lib\u00e9rer le programme principal.<\/p>\n<p><strong>\u00c9tape 1 : Initialisation du\u00a0USART<\/strong><\/p>\n<p>Il faut d&rsquo;abord \u00e9tablir les param\u00e8tres du port s\u00e9rie. Dans le cas pr\u00e9sent, nous allons configurer le port pour une des configurations les plus communes.<\/p>\n<table width=\"251\">\n<tbody>\n<tr>\n<td style=\"text-align: center;\" width=\"163\"><strong>Vitesse<\/strong><\/td>\n<td style=\"text-align: center;\" width=\"88\">9600 bauds<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center;\"><strong>Longueur des donn\u00e9es<\/strong><\/td>\n<td style=\"text-align: center;\">8 bits<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center;\"><strong>Parit\u00e9<\/strong><\/td>\n<td style=\"text-align: center;\">Aucune<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center;\"><strong>Nombre de bit STOP<\/strong><\/td>\n<td style=\"text-align: center;\">1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Les explications d\u00e9taill\u00e9es des registres utiles du Atmega328p sont disponibles dans la feuille de sp\u00e9cification suivante : <a href=\"http:\/\/www.atmel.com\/images\/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf\">ATMEGA328P<\/a><\/p>\n<p>Le premier registre que nous allons configurer est\u00a0en fait deux registres. C&rsquo;est le UBRR qui est s\u00e9par\u00e9 en deux parties UBRR0L et\u00a0UBRR0H. Ce registre configure la vitesse du port s\u00e9rie. La valeur de UBRR d\u00e9pend donc de l&rsquo;horloge du microcontr\u00f4leur et la vitesse d\u00e9sir\u00e9e. Dans notre cas, puisque nous utilisons le mode normal du USART. L&rsquo;\u00e9quation qui permet de d\u00e9terminer UBRR est :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-134 aligncenter\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_7.png\" alt=\"Screenshot_7\" width=\"421\" height=\"106\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_7.png 680w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_7-300x75.png 300w\" sizes=\"auto, (max-width: 421px) 100vw, 421px\" \/><\/p>\n<p>O\u00f9 fosc est la fr\u00e9quence d&rsquo;op\u00e9ration du CPU et BAUD est la vitesse d\u00e9sir\u00e9e.<\/p>\n<p>Pour \u00e9tablir cet valeur, il est possible de calculer la valeur et d&rsquo;utiliser un <strong><em>define<\/em> <\/strong>ou vous pouvez utiliser une macro qui calculera automatiquement la valeur en fonction des param\u00e8tres. Dans le premier cas, avec nos param\u00e8tres le r\u00e9sultat serait 103 (le CPU du Arduino utilise un cristal externe de 16MHz). Cependant, je recommande plut\u00f4t la seconde mani\u00e8re, plus facile \u00e0 maintenir. Voici le code de la macro en question :<\/p>\n<pre>#define BAUD_PRESCALE(fcpu,br) ((fcpu \/ 16 \/ br) - 1)<\/pre>\n<p>Les 8 bits les moins significatifs sont dans le registre UBBR0L et les 4 derniers bits dans UBBRoH. Voici la repr\u00e9sentation des registres en question:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-131\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_6.png\" alt=\"Screenshot_6\" width=\"1121\" height=\"181\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_6.png 1121w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_6-300x48.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_6-768x124.png 768w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_6-1024x165.png 1024w\" sizes=\"auto, (max-width: 1121px) 100vw, 1121px\" \/><\/p>\n<p>Pour UBRR0H, il faut simplement utiliser un d\u00e9calage comme ceci :<\/p>\n<pre> UBRR0H = (BAUD_PRESCALE(F_CPU,baudRate) &gt;&gt; 8); \r\n UBRR0L = BAUD_PRESCALE(F_CPU,baudRate);<\/pre>\n<p>Un autre registre d&rsquo;int\u00e9r\u00eat est le UCSR0C, qui permet de configurer le nombre de bits des donn\u00e9es, le bit de polarit\u00e9 ainsi que le nombre de bits STOP.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-135\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_8.png\" alt=\"Screenshot_8\" width=\"1124\" height=\"189\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_8.png 1124w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_8-300x50.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_8-768x129.png 768w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_8-1024x172.png 1024w\" sizes=\"auto, (max-width: 1124px) 100vw, 1124px\" \/><\/p>\n<table width=\"310\">\n<tbody>\n<tr>\n<td width=\"104\">UMSEL<\/td>\n<td width=\"206\">D\u00e9termine le mode\u00a0du port<br \/>\n00 est le mode asynchrone<\/td>\n<\/tr>\n<tr>\n<td width=\"104\">UPM<\/td>\n<td width=\"206\">D\u00e9termine la parit\u00e9<br \/>\n00 est aucune parit\u00e9<\/td>\n<\/tr>\n<tr>\n<td width=\"104\">USBS<\/td>\n<td width=\"206\">D\u00e9termine le nombre de bit STOP<br \/>\n0 est 1 bit<\/td>\n<\/tr>\n<tr>\n<td width=\"104\">UCSZ<\/td>\n<td width=\"206\">Est la longueur des donn\u00e9es<br \/>\n011 est 8bits. (valeur par d\u00e9faut)<br \/>\nNotez que UCSZ2 est dans un autre registre<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Voici donc le code qui permet de configurer le registre selon la configuration d\u00e9sir\u00e9e :<\/p>\n<pre>UCSR0C = (1&lt;&lt;UCSZ00)|(1&lt;&lt;UCSZ01);<\/pre>\n<p>Le dernier registre \u00e0 configurer sera le UCSR0B, qui active les \u00e9l\u00e9ments du port s\u00e9rie. Il contient \u00e9galement le dernier bit pour la configuration de la longueur des donn\u00e9es (UCSZ2).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-136\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_9.png\" alt=\"Screenshot_9\" width=\"1114\" height=\"189\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_9.png 1114w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_9-300x51.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_9-768x130.png 768w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2017\/11\/Screenshot_9-1024x174.png 1024w\" sizes=\"auto, (max-width: 1114px) 100vw, 1114px\" \/><\/p>\n<table width=\"310\">\n<tbody>\n<tr>\n<td width=\"104\">RXCIE<\/td>\n<td width=\"206\">Active l&rsquo;interruption de fin de r\u00e9ception d&rsquo;une donn\u00e9e. Pas utilis\u00e9 dans cet article.<\/td>\n<\/tr>\n<tr>\n<td width=\"104\">TXCIE<\/td>\n<td width=\"206\">Active l&rsquo;interruption de fin de transmission d&rsquo;une donn\u00e9e. Pas utilis\u00e9 dans cet article.<\/td>\n<\/tr>\n<tr>\n<td width=\"104\">RXEN<\/td>\n<td width=\"206\">Active la r\u00e9ception de donn\u00e9e<\/td>\n<\/tr>\n<tr>\n<td width=\"104\">TXEN<\/td>\n<td width=\"206\">Active la transmission de donn\u00e9e<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Voici donc le code de la fonction uartInit au complet (F_CPU est un define utilis\u00e9 par la librairie delay.h. Il vaut 16000000UL dans le cas pr\u00e9sent) :<\/p>\n<pre>void usartInit(uint32_t baudRate)\r\n{\r\n UBRR0L = BAUD_PRESCALE(F_CPU,baudRate);\r\n UBRR0H = (BAUD_PRESCALE(F_CPU,baudRate) &gt;&gt; 8); \r\n UCSR0B = ((1&lt;&lt;TXEN0)|(1&lt;&lt;RXEN0);\r\n UCSR0C = (1&lt;&lt;UCSZ00)|(1&lt;&lt;UCSZ01);\r\n}<\/pre>\n<p><strong>\u00c9tape 2\u00a0:\u00a0Envoyer une donn\u00e9e<\/strong><\/p>\n<p>Envoyer une donn\u00e9e est simple, il suffit d&rsquo;\u00e9crire dans le registre\u00a0UDR0 et la transmission d\u00e9bute automatiquement si la transmission est activ\u00e9e dans le registre UCSR0B. Avant d&rsquo;\u00e9crire, il faut cependant s&rsquo;assurer que le registre est vide, avec le bit\u00a0UDRE0 du registre\u00a0UCSR0A. Voici \u00e0 quoi peut ressembler la fonction de transmission d&rsquo;une donn\u00e9e.<\/p>\n<pre>void usartSendByte(uint8_t data)\r\n{\r\n while((UCSR0A &amp; (1&lt;&lt;UDRE0)) == 0);\r\n UDR0 = data;\r\n}<\/pre>\n<p><strong>\u00c9tape 3\u00a0:\u00a0R\u00e9ception d&rsquo;une donn\u00e9e<\/strong><\/p>\n<p>Pour lire une donn\u00e9e re\u00e7ue, il suffit de lire le registre UDR0. Cependant, pour s&rsquo;assurer que le contenu est bien une donn\u00e9e re\u00e7ue, il faut v\u00e9rifier que le bit RXC0 est activ\u00e9 dans le registre UCSR0A. Pour \u00e9viter\u00a0que le programme se bloque, il est pr\u00e9f\u00e9rable d&rsquo;utiliser une fonction qui valide la pr\u00e9sence d&rsquo;une donn\u00e9e avant de lancer la lecture. \u00a0Voici\u00a0les deux fonctions recommand\u00e9es pour cette \u00e9tape :<\/p>\n<pre>bool usartDataAvailable()\r\n{\r\n return (UCSR0A &amp; (1&lt;&lt;RXC0));\r\n}\r\n\r\nuint8_t usartGetRxByte()\r\n{\r\n \/\/ Option pour attendre la r\u00e9ception d'une donn\u00e9e... risque de blocage\r\n \/\/ while (!usartDataAvailable());\r\n return UDR0;\r\n}<\/pre>\n<p>Finalement, il restera \u00e0 v\u00e9rifier que l&rsquo;on peut recevoir et envoyer des donn\u00e9es \u00e0 l&rsquo;aide des fonctions. Je vous recommande <a href=\"http:\/\/www.der-hammer.info\/terminal\/\">HTerm<\/a> \u00a0pour v\u00e9rifier votre programme.<\/p>\n<p>Voici un petit programme qui utilise les fonctions pr\u00e9c\u00e9dentes et valide le fonctionnement. Les fonctions sont mises dans un fichier usart.cpp et les d\u00e9clarations de fonctions dans usart.h.<\/p>\n<pre>#include &lt;avr\/io.h&gt;\r\n  #ifndef F_CPU\r\n    #define F_CPU 16000000UL\r\n  #endif\r\n#include &lt;util\/delay.h&gt;\r\n#include \"usart.h\"\r\n\r\nvoid main(void)\r\n{\r\n  usartInit(19200);\r\n  while(1)\r\n  {\r\n    if(usartDataAvailable())\r\n      data = usartGetRxByte();\r\n    usartSendByte(data);\r\n    _delay_ms(1000);\r\n  }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cet article explique comment utiliser le lien\u00a0s\u00e9rie asynchrone (lire USART) pr\u00e9sent sur le Atmega328p du Arduino UNO. Dans cet article, nous utiliserons une boucle pour la transmission et la r\u00e9ception des octets. Je ferai un autre article qui expliquera comment faire avec les interruptions, ce qui est recommand\u00e9 afin de<span class=\"more-link\"><a href=\"https:\/\/marcjuneau.ca\/?p=129\">Continue Reading<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,11,2],"tags":[],"class_list":["entry","author-mjuneau","post-129","post","type-post","status-publish","format-standard","category-arduino","category-avrstudio","category-cc"],"_links":{"self":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/129","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=129"}],"version-history":[{"count":8,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/129\/revisions"}],"predecessor-version":[{"id":142,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/129\/revisions\/142"}],"wp:attachment":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=129"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=129"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=129"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}