{"id":225,"date":"2019-04-20T00:07:25","date_gmt":"2019-04-20T00:07:25","guid":{"rendered":"http:\/\/marcjuneau.ca\/?p=225"},"modified":"2020-03-19T15:46:07","modified_gmt":"2020-03-19T15:46:07","slug":"stm32-adc-de-base","status":"publish","type":"post","link":"https:\/\/marcjuneau.ca\/?p=225","title":{"rendered":"STM32 ADC de base"},"content":{"rendered":"\n<p>Cet article pr\u00e9sente la configuration de base d&rsquo;un ADC sur le STM32F446. Dans un <a href=\"#exemple1\">premier exemple<\/a>, l&rsquo;ADC1 sera configur\u00e9 sur le canal 0 pour une lecture d\u00e9marr\u00e9e dans l&rsquo;interruption du timer 2. Dans un <a href=\"#exemple2\">second exemple<\/a>, la lecture sera d\u00e9marr\u00e9e automatiquement par l&rsquo;\u00e9v\u00e9nement CC2 (Capture\/Compare canal2) du timer 2.  Tous les exemples utiliseront l&rsquo;interruption de fin de conversion. Le <a href=\"#codeComplet\">code complet<\/a> se trouve \u00e0 la fin de l&rsquo;article.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Avant de d\u00e9buter les exemples, nous allons regarder d&rsquo;un peu plus pr\u00e8s les registres \u00e0 consid\u00e9rer pour configurer l&rsquo;ADC1.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>RCC<ul><li>Pour l&rsquo;horloge de l&rsquo;ADC<\/li><\/ul><\/li><li><a href=\"#ADCx_CR1\">CR1 (control register 1)<\/a><ul><li>R\u00e9solution (nous utiliserons 8bits mais l&rsquo;ADC peut en fournir 12)<\/li><li>Activation de l&rsquo;interruption de fin de conversion<\/li><\/ul><\/li><li><a href=\"#ADCx_CR2\">CR1 (control register 2)<\/a><ul><li>D\u00e9clenchement manuel de la lecture<\/li><li>Activation de l&rsquo;ADC<\/li><\/ul><\/li><li><a href=\"#ADCx_SQR3\">SQR3 ( regular sequence register 3)<\/a><ul><li>Num\u00e9ro du canal \u00e0 lire<\/li><\/ul><\/li><li>SR (status register)<ul><li>Pour d\u00e9sengager le bit EOC apr\u00e8s une conversion compl\u00e9t\u00e9e <\/li><\/ul><\/li><\/ul>\n\n\n\n<p class=\"has-medium-font-size\"> <a name=\"ADCx_CR1\"><\/a><strong>ADCx_CR1 <\/strong> <\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"907\" height=\"549\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-2.png\" alt=\"\" class=\"wp-image-228\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-2.png 907w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-2-300x182.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-2-768x465.png 768w\" sizes=\"auto, (max-width: 907px) 100vw, 907px\" \/><\/figure>\n\n\n\n<p class=\"has-medium-font-size\"> <a name=\"ADCx_CR2\"><\/a><strong>ADCx_CR2 <\/strong>  <\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"911\" height=\"543\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-3.png\" alt=\"\" class=\"wp-image-235\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-3.png 911w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-3-300x179.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-3-768x458.png 768w\" sizes=\"auto, (max-width: 911px) 100vw, 911px\" \/><\/figure>\n\n\n\n<p class=\"has-medium-font-size\"><a name=\"ADCx_SQR3\" class=\"mce-item-anchor\"><\/a><strong>ADCx_SQR3  <\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"911\" height=\"382\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-4.png\" alt=\"\" class=\"wp-image-236\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-4.png 911w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-4-300x126.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-4-768x322.png 768w\" sizes=\"auto, (max-width: 911px) 100vw, 911px\" \/><\/figure>\n\n\n\n<p class=\"has-medium-font-size\"><a name=\"exemple1\" class=\"mce-item-anchor\"><\/a><strong>Exemple 1 :  Lecture ADC1 ch0 avec d\u00e9clenchement manuel<\/strong><\/p>\n\n\n\n<p>Le canal 0 du ADC 1 est reli\u00e9 \u00e0 PA0 comme le montre cette partie de la table 10 de la feuille de sp\u00e9cification.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"915\" height=\"567\" src=\"http:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-5.png\" alt=\"\" class=\"wp-image-239\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-5.png 915w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-5-300x186.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2019\/04\/image-5-768x476.png 768w\" sizes=\"auto, (max-width: 915px) 100vw, 915px\" \/><\/figure>\n\n\n\n<p class=\"has-medium-font-size\"> <strong>Configuration de PA0<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ Active horloge sur GPIOA\nRCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;\n\n\/\/ Configure PA1 en sortie\nGPIOA->MODER |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER0_0;<\/pre>\n\n\n\n<p class=\"has-medium-font-size\"><strong> Initialisation de ADC1<\/strong> <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ Activation de l\u2019horloge sur ADC1\nRCC->APB2ENR|= RCC_APB2ENR_ADC1EN;\n\n\/\/ R\u00e9solution \u00e0 8 bits + interruption EndOfConversion\nADC1->CR1 |= ADC_CR1_RES_1 | ADC_CR1_EOCIE;\n\n\/\/ Active l\u2019ADC1\nADC1->CR2 |= ADC_CR2_ADON;\n\n\/\/ Canal \u00e0 lire = canal 0\nADC1->SQR3 |= 0;\n\n\/\/ Active IRQ du ADC\nNVIC_EnableIRQ(ADC_IRQn);<\/pre>\n\n\n\n<p class=\"has-medium-font-size\"> <strong>Gestion de l\u2019interruption TIM2 <\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">extern \"C\"\u00a0 \/\/ si en c++\nvoid TIM2_IRQHandler(void)\n{\n   if (TIM2->SR & TIM_SR_UIF) \n   {\n      TIM2->SR &= ~TIM_SR_UIF; \n      \/\/ D\u00e9marre la lecture ADC1\n      ADC1->CR2 |= ADC_CR2_SWSTART;\n   }\n}<\/pre>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Gestion de l&rsquo;interruption ADC1<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">extern \"C\" \/\/ si en c++\nvoid ADC_IRQHandler(void)\n{\n  if (ADC1->SR & ADC_SR_EOC) \n  {\n    ADC1->SR &= ~ADC_SR_EOC; \n    adcValue = ADC1->DR;\n    GPIOA->ODR ^= (1<<5);\n  }\n}<\/pre>\n\n\n\n<p class=\"has-medium-font-size\"><strong><a name=\"exemple2\"><\/a>Exemple 2 :  Lecture ADC1 ch0 avec d\u00e9clenchement automatis\u00e9<\/strong><\/p>\n\n\n\n<p>Plut\u00f4t que de d\u00e9marrer la lecture de l\u2019ADC manuellement dans le timer 2, nous allons utiliser l\u2019\u00e9v\u00e9nement CC2 du timer 2 pour le faire automatiquement.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Initialisation de l'ADC<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ Activation de l\u2019horloge sur ADC1\nRCC->APB2ENR|= RCC_APB2ENR_ADC1EN;\n\n\/\/ R\u00e9solution \u00e0 8 bits + interruption EndOfConversion\nADC1->CR1 |= ADC_CR1_RES_1 | ADC_CR1_EOCIE;\n\n\/\/ Active l\u2019ADC1 avec d\u00e9clenchement sur CC2 du timer 2\nADC1->CR2 |= ADC_CR2_ADON |ADC_CR2_EXTEN_0;\nADC1->CR2 |= ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1;\n\/\/ Canal \u00e0 lire = canal 1\nADC1->SQR3 |= 1;\n\n\/\/ Active IRQ du ADC\nNVIC_EnableIRQ(ADC_IRQn);<\/pre>\n\n\n\n<p> Code d\u2019initialisation de CC2 TIM2 <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Active horloge sur TIM2\nRCC->APB1ENR |= RCC_APB1ENR_TIM2EN;\n\nTIM2->PSC = (SystemCoreClock>>1) \/ 10000 - 1;\nTIM2->ARR = 999;\n\/\/ PWM2\nTIM2->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 ;\nTIM2->CCER  = TIM_CCER_CC2E; \/\/ Active sortie CH2\nTIM2->CCR2  = TIM2->ARR >>1; \/\/ Duty cycle \u00e0 50%\n\n\/\/ Active registre ARR et d\u00e9marre le compteur\nTIM2->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN;<\/code><\/pre>\n\n\n\n<p class=\"has-medium-font-size\"><strong><a name=\"codeComplet\"><\/a>Code complet<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#include \"stm32f4xx.h\"\nbool refreshADC = false;\nuint8_t adcValue = 0;\n\nint main(void)\n{\n\n\tRCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;\n\tGPIOA->MODER |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER0_0;\n\n\t\/\/ Active horloge sur TIM2\n\tRCC->APB1ENR |= RCC_APB1ENR_TIM2EN;\n\n\tTIM2->PSC = (SystemCoreClock>>1) \/ 1000000 - 1;\n\tTIM2->ARR = 24;\n\tTIM2->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 ;\/\/ PWM2\n\tTIM2->CCER  = TIM_CCER_CC2E; \/\/ Active sortie CH2\n\tTIM2->CCR2  = TIM2->ARR >>1; \/\/ Duty cycle \u00e0 50%\n\n\t\/\/ Active l'interruption (IRQ) du TIM2\n\tNVIC_EnableIRQ(TIM2_IRQn);\n\tTIM2->DIER = TIM_DIER_UIE;\n\n\t\/\/ Active registre ARR et d\u00e9marre le compteur\n\tTIM2->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN;\n\n\t\/\/ Initialisation de l'ADC1\n\tRCC->APB2ENR|= RCC_APB2ENR_ADC1EN;\n\tADC1->CR1 |= ADC_CR1_RES_1 | ADC_CR1_EOCIE;\n\tADC1->CR2 |= ADC_CR2_ADON ;\n\tADC1->CR2 |= ADC_CR2_ADON |ADC_CR2_EXTEN_0 | ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1;\n\tADC1->SQR3 |= 0;\n\tNVIC_EnableIRQ(ADC_IRQn);\n\n\twhile(1)\n\t{\n\n\t\tif(refreshADC)\n\t\t{\n\t\t\trefreshADC = false;\n\t\t\t\/\/ Faire qqchose avec la donn\u00e9e\n\t\t}\n\t}\n}\n\nextern \"C\"\nvoid TIM2_IRQHandler(void)\n{\n\tif (TIM2->SR & TIM_SR_UIF) \/\/ if UIF flag is set\n\t{\n\t\tTIM2->SR &= ~TIM_SR_UIF; \/\/ clear UIF flag\n\t\trefreshADC = true;\n\t\t\/\/ADC1->CR2 |= ADC_CR2_SWSTART; \/\/ Pour l'exemple 1\n\t}\n}\n\nextern \"C\"\nvoid ADC_IRQHandler(void)\n{\n\tif (ADC1->SR & ADC_SR_EOC) \/\/ if UIF flag is set\n\t{\n\t\tADC1->SR &= ~ADC_SR_EOC; \/\/ clear UIF flag\n\t\tadcValue = ADC1->DR;\n\t}\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Cet article pr\u00e9sente la configuration de base d&rsquo;un ADC sur le STM32F446. Dans un premier exemple, l&rsquo;ADC1 sera configur\u00e9 sur le canal 0 pour une lecture d\u00e9marr\u00e9e dans l&rsquo;interruption du timer 2. Dans un second exemple, la lecture sera d\u00e9marr\u00e9e automatiquement par l&rsquo;\u00e9v\u00e9nement CC2 (Capture\/Compare canal2) du timer 2. Tous<span class=\"more-link\"><a href=\"https:\/\/marcjuneau.ca\/?p=225\">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,13],"tags":[],"class_list":["entry","author-mjuneau","has-more-link","post-225","post","type-post","status-publish","format-standard","category-cc","category-stm32","category-stm32-nucleo"],"_links":{"self":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/225","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=225"}],"version-history":[{"count":19,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/225\/revisions"}],"predecessor-version":[{"id":323,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/225\/revisions\/323"}],"wp:attachment":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}