برد STM قطعات الکترونیک

راه اندازی مبدل آنالوگ به دیجیتال ADC در میکروکنترلرهای STM32

نوشته شده توسط علی زاهدی

دنیایی که در آن زندگی میکنیم از انواع کمیت های آنالوگ تشکیل شده است. برای اندازه گیری  این کمیت ها با استفاده از میکروکنترلر ها بایستی ابتدا این کیمیت هارا به منطق دیجیتال (اعداد باینری) تبدیل کنیم. در اکثر میکروکنترلر ها بخشی تحت عنوان مبدل آنالوگ به دیجیتال (ADC) وجود دارد. که امکان اندازه گیری کیمیت های آنالوگ را در اختیار ما میگذارد. در این آموزش قصد داریم تا بخش مبدل آنالوگ به دیجیتال ADC میکروکنترلر های STM32 را مورد بررسی قرار دهیم. در ادامه با مرجع تخصصی بردهای امبدد به زبان فارسی، دیجی اسپارک همراه باشید.

 


ADC در میکروکنترلر STM32


کلمه ADC مخفف Analog to Digital Converter به معنای مبدل آنالوگ به دیجیتال است. در واقع ADC مقادیر فیزیکی یک پدیده در دنیای واقعی را به یک زبان دیجیتالی تبدیل می کند که در سیستم های کنترل ، محاسبات داده ، انتقال داده و پردازش اطلاعات استفاده می شود. معمولا از ADC برای تبدیل مقادیری مثلا ولتاژ و جریان به سیگنال دیجیتال استفاده می‌شود. در میکرو کنترلر های STM32 بسته به نوع میکروکنترلر مورد استفاده، چند کانال مبدل آنالوگ به دیجیتال ۱۲ یا ۱۶ بیتی در اختیار شما قرار میگیرد.

شناخت ADC در میکروکنترلرها - دیجی اسپارک

 

ADC تعبیه شده در میکروکنترلرهای STM32 از اصل SAR (ثبات تقریب متوالی) استفاده می کند ، که توسط آن تبدیل در چند مرحله انجام می شود. تعداد مراحل تبدیل برابر با تعداد بیت های مبدل ADC است. هر مرحله توسط کلاک ADC هدایت می شود. هر ساعت ADC از نتیجه به خروجی یک بیت تولید می کند. طراحی داخلی ADC بر اساس تکنیک خازن تغییر یافته است. ولتاژ مرجع در برخی پکیج های میکروکنترلر STM32 به پایه VDDA متصل است.

عملکرد آنالوگ به دیجیتال ADC - دیجی اسپارک

 


اتصالات مدار


در این پروژه قصد داریم تا مقدار ولتاژ ورودی داده شده به پایه ADC میکروکنترلر STM32 را انداز گیری نموده و روی LCD نمایش دهیم. برای این کار بایستی از یک پتانسومتر در ورودی ADC میکروکنترلر قرار دهیم تا تغیرات ولتاژ ورودی را اندازه گیری کنیم. در این پروژه از LCD کاراکتری استفاده شده است. در آموزش های راه اندازی LCD کاراکتری با میکروکنترلر STM32 و راه اندازی LCD کاراکتری با رابط I2C نحوه کار با این نوع نمایشگر توضیح داده شده است. اتصالات پروژه به صورت زیر است.

شماتیک راه اندازی و اتصالات ADC در میکروکنترلر STM32 - دیجی اسپارک

 


پیکربندی ADC در STM32CubeMX


پس از ساخت پروژه در نرم افزار STM32CubeMX و انجام تنظیمات مربوط به بخش های RCC و SYS، برای راه اندازی ADC در ساده ترین حالت بایستی یکی از ADC های میکروکنترلر را انتخاب کنید. سپس بایستی یکی از کانال های ورودی ADC را در نظر گرفته و تیک مربوط به آن پایه را در بخش ADC بزنید. میکروکنترلر STM32F103C8T6 دارای ۲ مبدل آنالوگ به دیجیتال ۱۲ بیتی است که مجموعاً ۱۶ کانال ADC در اختیار ما قرار می دهد.

پیکربندی ADC در STM32CubeMX - دیجی اسپارک

 

سپس در بخش Parameter Setting ابتدا بایستی مد کاری ADC را انتخاب کنید. در این آموزش ADC را در مد پیشفرض خود راه اندازی خواهیم کرد. در قدم بعدی بایستی برای این که ADC به طور پیوسته کار کند، گزینه Continuous Conversion Mode را فعال کنید. پس از آن در بخش ADC_Regular_ConversionMode گزینه Number of Conversion را ۱ قرار دهید. زیرا قصد خواندن مقدار آنالوگ از یک ورودی را داریم. سپس بخش Rank گزینه Sampling Time را بر روی ۱٫۵ Cycles تنظیم کنید.

انتخاب مد کاری ADC در نرم افزار - دیجی اسپارک

 

همانطور که در بخش قبلی گفته شد برای نمایش تغیرات ولتاژ از نمایشگر LCD کاراکتری استفاده شده است. بنابراین مطابق آموزش راه اندازی LCD کاراکتری با میکروکنترلر STM32 بایستی ۷ پایه میکروکنترلر را برای برقراری ارتباط با LCD کارکتری به صورت خروجی تعریف کنیم.

STM32 Pinout

سپس بایستی وارد بخش Clock Configuration شده و کلاک میکروکنترلر را بر روی ۷۲ مگاهرتز تنظیم کنید. در آخر در قسمت Project Manager ابتدا نام پروژه و مسیر مورد نظر برای ذخیره پروژه را مشخص کنید. سپس گزینه Toolchain را بروی MDK-ARM و ورژن آن را بر روی ۵ تنظیم کرده و بر روی گزینه GENERATE CODE در قسمت نوار بالایی کلیک کنید تا پروژه ساخته شود.

 


کدنویسی در نرم‌افزار KEIL


پس از ورود به نرم افزار KEIL بایستی وارد فایل main.c شده و شروع به برنامه نویسی کنید. پس از ورود به فایل main.c بایستی ابتدا ۲ متغیر برای اندازه گیری مقدار خروجی ADC میکروکنترلر STM32 و مقدار ولتاز محاسبه شده تعریف کنید.

uint16_t ADC_Value;
float Voltage;

سپس برای شروع به کار ADC میکروکنترلر STM32 بایستی از دستور زیر استفاده کنید.

HAL_ADC_Start(&hadc1);

با استفاده از دستور زیر می‌توانید پرچم های EOS و EOC را پاک کنید.

// ADC conversion flags EOS (end of sequence) and EOC (end of conversion) are cleared by this function.
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);

تا به اینجا تنظیمات مورد نیاز برای خواندن از ADC را انجام شده است. حالا می‌توانید مقدار آنالوگ موجود بر روی پایه PA0 را محاسبه کنید. برای این کار بایستی از دستور زیر استفاده کنید.

ADC_Value = HAL_ADC_GetValue(&hadc1);

همانطور که مشاهده می‌کنید. مقدار آنالوگ اندازه گیری شده بر روی پایه ADC میکروکنترلر STM32 در متغیر ADC_Value ذخیره شده است. این مقدار عددی بین ۰ تا ۴۰۹۶ است ( عدد ۴۰۹۶ بر اساس ۱۲ بیتی بودن ADC میکروکنترلر STM32 است). برای به دست آوردن ولتاژ ورودی داده شده به پایه ADC میکزوکنترلر STM32 بایستی از فرمول زیر استفاده کنید.

Voltage = (float)(ADC_Value * 3.3) / (4095);

حال ولتاژ ورودی دریافتی بر روی پایه ADC میکروکنترلر STM32 در متغیر Viltage ذخیر شده است. و برای مشاهده این مقدار کافیست مقدار ذخیره شده در متغیر Voltage را بر روی LCD نمایش دهید. برای نمایش مقدار متغیر مورد نظر میتوانید از تابع sprintf استفاده کنید. این تابع داخل کتابخانه Stdio.h قرار دارد که در آموزش تحلیل و بررسی کتالیخانه Stdio.h نحوه کار با این تابع توضیح داده شده است. در ادامه کد کامل پروژه قرار داده شده است. توجه داشته باشید که بایستی هر بخش کد زیر را در بخش های مشخص شده در توسط نرم افزار STM32CubeMX کپی کنید.

#include "character_lcd.h"
#include <stdio.h>

uint16_t ADC_Value;
float Voltage;
char buff[16];
 
int main(void)
{

  LCD_Config.Font = _FONT_5X7; 
  LCD_Config.Mode = _4BIT_INTERFACE; 
  LCD_Config.NumberOfLine = _2LINE_DISPLAY; 
  LCD_Init();
 
  LCD_GotoXY(2,0);
  LCD_PutString("DigiSpark.ir");
  while (1)
  {
	HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
	
    ADC_Value = HAL_ADC_GetValue(&hadc1);
    Voltage = (float)(ADC_Value * 3.3) / (4095);
	
	sprintf(buff,"Voltage = %1.2f V",Voltage);	
	LCD_GotoXY(0,1);
    LCD_PutString(buff);
  }
}

در آخر بایستی برنامه را کامپایل کرده و بر روی برد Bluepill پروگرام کنید. در صورتی که با نحوه پروگرام کردن میکروکنترلر های Stm32 آشنا نیستید. لطفا بخش اول آموزش های میکروکنترلر Stm32 را مطالعه نمایید. پس از دانلود کد بر روی برد BluePill بایستی یک بار کلید reset را بر روی برد فشار دهید. در صورت که اتصالات را به طور صحیح متصل کرده باشید. ADC میکروکنترلر STM32 فعال شده و با چرخواندن پتانسومتر مقدار ولتاژ نمایش داده شده بر روی LCD تغییر می‌کند.

 


جمع بندی


تقریبا تمامی کیمیت های فیزیکی اطراف ما، آنالوگ هستند. اما دنیای کامپیوتر و میکروکنترلر ها تنها کمیت های دیجیتال را تشخیص میدهد. به عبارت دیگر می‌توان گفت این سیستم ها تنها صفر و یک را می‌فهمند. برای تبدیل کمیت های آنالوگ به دیجیتال راه های مختلفی وجود دارد. که استفاده از مبدل های آنالوگ به دیجیتال یکی از دقیق ترین آنها است. اکثر میکروکنترلر هایی که در بازار موجود است. دارای مبدل آنالوگ به دیجیتال داخلی هستند. میکروکنترلر های STM32 دارای مبدل آنالوگ به دیجیتال ۱۲ بیتی هستند. در این آموزش با نحوه فعال سازی و همچنین استفاده از ADC میکروکنترلر های STM32 آشنا شدیم.

 


لوازم مورد نیاز


 

چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریع‌ترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند می‌توانید از همین طریق اطلاع رسانی کنید.

 

در پایان نظرات و پیشنهادات خود را با ما درمیان بگذارید و با اشتراک گذاری این آموزش در شبکه های اجتماعی از وبسایت دیجی اسپارک حمایت کنید.

 

درباره نویسنده

علی زاهدی

برنامه نویس و طراح سیستم های مبتنی بر میکروکنترلر

دانسته هایتان را مانند یک ساعت مچی در دست کنید، نه صرفا به این خاطر که نشان دهید آن را دارید. بلکه به این خاطر که اگر کسی از شما ساعت را پرسید، برایش بگویید.
لرد چسترفیلد

تبادل نظر و رفع عیب با ثبت دیدگاه

۵ دیدگاه

  • سلام :
    من از هدر برد stm32f103 همان هدر بردی که در متن توضیح داده شده استفاده میکنم. من adc این میکرو را راه اندازی کردم . تا برایم ولتاژ های مختلفی را برایم بخواند . ولی مثلا یک ولتاژ ثابت را هر بار که تست میکنم هربار یک عددی را برایم نشان میدهد .خلاصه اینکه دقیق نمیخواند . برایم مهم هست که ولتاژ را دقیق بخواند ولی هربار یک ولتاژی را برایم نشان میدهد . من مقدار ولتاژ خوانده شده را با استفاده از uart در کامپیوتر مشاهده میکنم.من ولتاژ ۳٫۳ را به ADC میدهم ولی برایم ۴۰۲۴ را نشان میدهد البته با هر بار تست این عدد کمی بالا یا پایین میشود. در صورتی که باید۴۰۹۵ را باید برایم نشان دهد.
    من ADCرا بایک خازن۱۰۰nf زمین کردم ولی درست نشد . پایه ولتاژ ref را هم که در اختیار نداریم که ولتاژ ref را خودمان بدون نویز به آن اعمال کنیم.چگونه این مشکل را حل کنیم .لطفا کمکم کنید متشکرم

  • سلام
    من ADC آرم stm32f103 را راه اندازی کردم ولی مشکلی که دارم این است که ولتاژ ۳٫۳ را به ADC میدهم و از طریق uart ولتاژ خوانده شده را در کامپیوتر مشاهده میکنم . هر سری که تست میکنم عددهای مختلفی را نشان میدهد باید عدد ۴۰۹۵ را نشان دهد ولی عدد های مثل ۴۰۳۰و۴۰۲۶و۴۰۲۰و…را نشان میدهد پایه adc را با خازن۱۰۰nf زمین کردم ولی مشکل حل نشد .برایم مهم است که ولتاژ را دقیق بخواند .
    به پایه ref هم تو این ایسی دسترسی نداریم که خودمان ولتاژ بدون نویز به آن اعمال کنیم .لطفا کمکم کنید .

    با تشکر

    • با سلام
      پیشنهاد میکنم اگر میزان دقت ADC بسیار برای شما اهمیت دارد. از ماژول هایی مانند ADS1115 استفاده کنید که با دقت ۱۶ بیت ولتاژ را اندازه گیری میکنند.

  • سلام وقت بخیر .
    من کد های مبدل انالوگ به دیجیتال رو از کد های شما کپی کردم.
    بعد کدی نوشتم که اگر ولتاژ بیشتر ۱ ولت شد LED روشن شود و روشن شد.
    ولی بعد که دستوری نوشتم که اگر ولتاژ مساوی با ۱ بود بیا LED رو روشن کن و متاسفانه روشن نشد

    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1,HAL_MAX_DELAY);
    ADC_Value=HAL_ADC_GetValue(&hadc1);
    Voltage=(float)(ADC_Value*3.3) / (4095); ;
    if(Voltage==1)
    {
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
    }
    else
    {
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
    }

    • با سلام! مشکلی که در کد خود توضیح داده‌اید احتمالاً به مسئله دقت اعداد اعشاری مربوط می‌شود. معمولاً اعداد اعشاری در محاسبات دقت کاملی ندارند و ممکن است این عدد ۱ به‌طور دقیق ۱ نباشد و اعدادی کوچکتر یا بزرگتر از آن باشند.

      برای مقایسه اعداد اعشاری در برنامه‌نویسی، بهتر است از یک بازه مجاز استفاده کنید تا هم‌اکنون یک دقت مطلق را برای مقایسه اعداد داشته باشید. به عنوان مثال، شما می‌توانید یک بازه را در نظر بگیرید که ولتاژ‌های بین ۰٫۹ و ۱٫۱ را شامل می‌شود. این به شما امکان می‌دهد که با استفاده از عملگرهای مقایسه‌ای (مانند بزرگتر از، کوچکتر از، یا برابر با) اعداد را مقایسه کنید.

      بنابراین، در کد خود می‌توانید به جای مقایسه Voltage با ۱، از یک بازه استفاده کنید. مانند زیر:

      if(Voltage >= 0.9 && Voltage <= 1.1)
      {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
      }
      else
      {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
      }

      با این تغییر، اگر ولتاژ بین ۰٫۹ تا ۱٫۱ ولت باشد، LED روشن خواهد شد. در غیر این صورت، LED خاموش