{"id":170,"date":"2019-03-04T01:54:07","date_gmt":"2019-03-04T01:54:07","guid":{"rendered":"http:\/\/marcjuneau.ca\/?p=170"},"modified":"2019-04-08T16:19:36","modified_gmt":"2019-04-08T16:19:36","slug":"usart2-avec-classe","status":"publish","type":"post","link":"https:\/\/marcjuneau.ca\/?p=170","title":{"rendered":"USART2 avec Classe"},"content":{"rendered":"\n<p> Il est possible (et pratique) de faire de l&rsquo;orient\u00e9 objet sur les STM32. Cet article pr\u00e9sente un exemple pour le USART2 du Nucl\u00e9o-F446RE. Le <a href=\"https:\/\/sourceforge.net\/projects\/stm32f446re-usart2\/\">code source<\/a> complet est disponible sur sourceForge.  <\/p>\n\n\n\n<p>Voici le UML de la classe STM32F446RE_USART2 que nous allons r\u00e9aliser.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/STM32F446RE_USART2_UML.jpg\" alt=\"\" class=\"wp-image-183\" width=\"388\" height=\"317\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/STM32F446RE_USART2_UML.jpg 330w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/STM32F446RE_USART2_UML-300x245.jpg 300w\" sizes=\"auto, (max-width: 388px) 100vw, 388px\" \/><\/figure><\/div>\n\n\n\n<p> Le contr\u00f4le des donn\u00e9es en entr\u00e9e et en sortie se fera via les interruptions, ce qui explique l&rsquo;amiti\u00e9 pour le gestionnaire d&rsquo;interruption. De plus, la classe impl\u00e9mentera le patron singleton afin de permettre le partage du p\u00e9riph\u00e9rique entre diff\u00e9rents \u00e9l\u00e9ments d&rsquo;un programme. <\/p>\n\n\n\n<p>Il est possible de configurer les p\u00e9riph\u00e9riques des STM32 \u00e0 l&rsquo;aide de la librairie HAL ou des librairies standards.  Je pr\u00e9f\u00e8re configurer directement les registres \u00e0 partir des informations disponibles dans le <a href=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/stm32f446_referenceManual-1.pdf\">manuel de r\u00e9f\u00e9rence<\/a> et la <a href=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/stm32f446_datasheet-2.pdf\">feuille de sp\u00e9cification<\/a>.<\/p>\n\n\n\n<p>Le USART2 du Nucl\u00e9o est reli\u00e9 au lien USB qui pr\u00e9sente un lien s\u00e9rie virtuel sur l&rsquo;ordinateur (pratique pour le d\u00e9bogage).  La figure suivante montre que TX et RX du USART2 sont respectivement reli\u00e9s \u00e0 PA2 et PA3.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/usart2_pinout.png\" alt=\"\" class=\"wp-image-180\" width=\"567\" height=\"353\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/usart2_pinout.png 506w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/usart2_pinout-300x187.png 300w\" sizes=\"auto, (max-width: 567px) 100vw, 567px\" \/><\/figure>\n\n\n\n<p>Le constructeur fera dans un premier temps la configuration des horloges, puis celle des broches E\/S avant de terminer avec la configuration des registres sp\u00e9cifiques au USART2.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">STM32F446RE_USART2::STM32F446RE_USART2()   <br>{     <br>  \/\/ Activer les horloges     <br>  RCC-&gt;AHB1ENR |= RCC_AHB1ENR_GPIOAEN;     <br>  RCC-&gt;APB1ENR |= RCC_APB1ENR_USART2EN;     <br>  \/\/ Configurer IO pour RX et TX     <br>  \/\/ PA2 et PA3 en Alternate fonction     <br>  GPIOA-&gt;MODER    |= GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1;<br>  \/\/ PA2 et PA3 en High speed    <br>  GPIOA-&gt;OSPEEDR  |= GPIO_OSPEEDER_OSPEEDR2;<br>  GPIOA-&gt;OSPEEDR  |=  GPIO_OSPEEDER_OSPEEDR3 ;     <br>  GPIOA-&gt;AFR[0] |=  GPIO_AF_USART2 &lt;&lt; 8 ;   \/\/PA2 en TX = AF7    <br>  GPIOA-&gt;AFR[0] |=  GPIO_AF_USART2 &lt;&lt; 12 ;  \/\/PA3 en RX = AF7    <br>  \/\/ Pour r\u00e9duire le bruit sur l'alimentation    <br>  SYSCFG-&gt;CMPCR |= SYSCFG_CMPCR_CMP_PD;         <br>  \/\/ Par default la configuration est 8N1    <br>  USART2-&gt;CR1 |= USART_CR1_RE | USART_CR1_TE; <br>  \/\/ Active RX et TX    <br>  setBaudRate(9600);        <br>  \/\/ Active l'interruption pour USART2      <br>  NVIC_EnableIRQ(USART2_IRQn);    <br>  \/\/ Interruption de tx activ\u00e9e sur transmission    <br>  USART2-&gt;CR1 |= USART_CR1_RXNEIE;     <br>  USART2-&gt;CR1 |= USART_CR1_UE; \/\/ USART activ\u00e9 <br>}<\/pre>\n\n\n\n<p>Le calcul de la vitesse de transmission (baudrate) utilise la vitesse de l&rsquo;horloge (ici 180MHz) afin de d\u00e9terminer la valeur du registre BRR. Notez que pour les vitesse au del\u00e0 de 2.8Mbps, il sera n\u00e9cessaire de diminuer le sur-\u00e9chantillonnent de 16 \u00e0 8.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">void STM32F446RE_USART2::setBaudRate(uint32_t baudrate) <br>\n{<br>\n    USART2-&gt;BRR = (SystemCoreClock&gt;&gt;2) \/ baudrate;<br>\n}<\/pre>\n\n\n\n<p>La m\u00e9thode <strong><em>getInstance <\/em><\/strong>appel le constructeur si l&rsquo;instance n&rsquo;est pas d\u00e9j\u00e0 cr\u00e9\u00e9e, puis elle retourne l&rsquo;adresse de l&rsquo;instance.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">STM32F446RE_USART2* STM32F446RE_USART2::getInstance() <br>\n{<br>\n    if (instance == 0)<br>\n        instance = new STM32F446RE_USART2();<br>\n    return instance;<br>\n}<\/pre>\n\n\n\n<p>La m\u00e9thode <strong><em>dataAvailable <\/em><\/strong>retourne vrai lorsqu&rsquo;il y a des donn\u00e9es dans le tampon de r\u00e9ception.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bool STM32F446RE_USART2::dataAvailable() const<br>\n{<br>\n    return !rxBuffer.isEmpty();<br>\n}<\/pre>\n\n\n\n<p>La m\u00e9thode <strong><em>read <\/em><\/strong>retourne simplement un octet retir\u00e9 de <strong><em>rxBuffer<\/em><\/strong>. <strong><em>BufferTemplate <\/em><\/strong>g\u00e8re d\u00e9j\u00e0 les demandes lorsque la file est vide et retourne le dernier \u00e9l\u00e9ment.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">uint8_t STM32F446RE_USART2::read()<br>\n{<br>\n    return rxBuffer.rem();<br>\n}<\/pre>\n\n\n\n<p>La m\u00e9thode <strong><em>write <\/em><\/strong>re\u00e7oit un octet \u00e0 transmettre. Elle ajoute donc l&rsquo;octet au tampon de transmission et si le USART2 ne transmettait pas d\u00e9j\u00e0, il active l&rsquo;interruption pour le registre de transmission vide.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">void STM32F446RE_USART2::write(uint8_t data)<br> {<br>     txBuffer.add(data);<br>     if(!isTransmitting)<br>     {<br>         isTransmitting = true;<br>         USART2-&gt;CR1 |= USART_CR1_TXEIE; \/\/ active l'interruption.<br>     }<br>}<\/pre>\n\n\n\n<p>Finalement, le gestionnaire d&rsquo;interruption pour le USART2 traite la r\u00e9ception et la transmission des octets. Le fait qu&rsquo;il soit ami avec USART2 lui permet un acc\u00e8s plus direct et donc plus rapide vers les tampons. Notez que pour am\u00e9liorer les performances, vous pourriez utiliser des tableaux de donn\u00e9es plut\u00f4t que la classe BufferTemplate, ou encore la DMA selon l&rsquo;application vis\u00e9e.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">extern \"C\" <br>{<br>  void USART2_IRQHandler(void)<br>  {<br>     volatile unsigned int isr;<br>     isr = USART2-&gt;SR;<br>     \/\/ RX Data<br>     if (isr &amp; USART_SR_RXNE)<br>     {<br>         USART2-&gt;SR &amp;= ~USART_SR_RXNE;<br>         STM32F446RE_USART2::instance-&gt;rxBuffer.add(USART2-&gt;DR);<br>     }     <br>     \/\/ TX Done<br>     if ((isr &amp; USART_SR_TXE))<br>     {<br>         USART2-&gt;SR &amp;= ~USART_SR_TXE;<br>         if(STM32F446RE_USART2::instance-&gt;txBuffer.isEmpty())<br>         {<br>             STM32F446RE_USART2::instance-&gt;isTransmitting = false;<br>             USART2-&gt;CR1 &amp;= (~USART_CR1_TXEIE);<br>         }<br>         else<br>         {<br>             USART2-&gt;DR = STM32F446RE_USART2::instance-&gt;txBuffer.rem();<br>             STM32F446RE_USART2::instance-&gt;isTransmitting = true;<br>         }<br>     }<br>   }<br>}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Documents<\/h3>\n\n\n\n<div class=\"wp-block-file\"><a href=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/stm32f446_referenceManual-1.pdf\">stm32f446_referenceManual<\/a><a href=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/stm32f446_referenceManual-1.pdf\" class=\"wp-block-file__button\" download>T\u00e9l\u00e9charger<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/stm32f446_datasheet-2.pdf\">Feuille de sp\u00e9cification<\/a><a href=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/03\/stm32f446_datasheet-2.pdf\" class=\"wp-block-file__button\" download>T\u00e9l\u00e9charger<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>USART2 avec Classe<span class=\"more-link\"><a href=\"https:\/\/marcjuneau.ca\/?p=170\">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":[2,10,15],"tags":[],"class_list":["entry","author-mjuneau","has-excerpt","post-170","post","type-post","status-publish","format-standard","category-cc","category-stm32","category-stm32-usart"],"_links":{"self":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/170","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=170"}],"version-history":[{"count":16,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/170\/revisions"}],"predecessor-version":[{"id":221,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/170\/revisions\/221"}],"wp:attachment":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=170"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=170"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=170"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}