آموزش AVR

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

سلام. آموزش کامل مبدل آنالوگ به دیجیتال ADC در میکروکنترلر های AVR را آماده کردیم. در این مطلب به صورت کامل مبحث تبدیل سیگنال آنالوگ به دیجیتال را آموزش میدهیم.

در میکروکنترلر های AVR یک واحد وجود دارد به نام ADC یا همان تبدیل کننده آنالوگ به دیجیتال (Analog Digital Conversion) که وظیفه آن تبدیل سیگنال های پیوسته آنالوگ به سیگنال های گسسته دیجیتال است.

سنسور ها و … کلا اجزای بیرون از کامپیوتر با سیگنال آنالوگ کار میکنند در صورتی که میکروکنترلر ها با سیگنال دیجیتال کار میکنند و ما برای تبدیل اطلاعات آنالوگ به دیجیتال از ADC میکروکنترلر استفاده میکنیم.

خب در ابتدا برای فهمیدن مفهوم ADC یک مثال میزنیم. به پخش کننده های موسیقی جدید دقت کنید. این پخش کننده ها در قسمت تنظیمات ولوم ابتدا و انتها ندارند. یعنی مثل انواع قدیمی آنها دارای پیچه برای تنظیم ولوم نیستند ! و با دکمه + و – صدا را کم و زیاد میکنند. حالا کم کم متوجه موضوع میشوید.

انواع روش های تبدیل سیگنال آنالوگ به دیجیتال

برای تبدیل سیگنال آنالوگ به دیجیتال 6 روش داریم که در زیر لیست شده اند :

  1. روش موازی یا همزمان
  2. روش دو شیب
  3. روش پله ای
  4. روش تبدیل ولتاژ به فرکانس
  5. روش تبدیل ولتاژ به زمان
  6. روش تقریب متوالی

میکروکنترلر های AVR از روش تقریب متوالی برای ADC استفاده میکنند. در میکروکنترلر های AVR معمولا چند کانال آنالوگ به دیجیتال وجود دارد. اما هر میکروکنترلر تنها یک تبدیل کننده دارد و همه کانال ها به یک مبدل متصل میشود و کانال های مختلف با هم مالتی پلکس میشوند و اطلاعات مورد نظر را ارائه میدهند.

فرمول محاسبه مقدار دیجیتال از روی موج آنالوگ

فرمول محاسبه مقدار دیجیتال از روی موج آنالوگ

فرمول بالا نحوه محاسبه مقدار دیجیتال را نشان میدهد. در فرمول بالا مواردی داریم که نیاز به توضیح دارند :

  • Vin : ولتاژ ورودی است یعنی ولتاژی که قرار است مقدار دیجیتال آن محاسبه شود.
  • Vref : ولتاژ مرجع است.
  • n : درجه دقت است که در میکروکنترلر های AVR اغلب دارای دقت 10 بیتی هستند که میشود برای آنها از دقت 8 نیز استفاده کرد.

دقت 10 بیتی چیست ؟

به طور مثال وقتی ولتاژ ورودی شما بین 0 تا 5 است، میکروکنترلر این فاصله را به 210 = (1024) واحد تقسیم میکند. تصویر زیر را ببینید :

چگونگی تبدیل آنالوگ به دیجیتال در AVR

همانطور که در تصویر بالا مشاهده میکنید ولتاژ 0 تا 5 ولت به 1024 واحد دیجیتال تبدیل میشوند. و به طور مثال ولتاژ 2.5 میشود 512 واحد ADC. هر چه درجه دقت یک میکروکنترلر بالاتر باشد ، دقت محاسبه ADC در آن بالا تر است.

همچنین پیشنهاد میکنم آموزش آنالوگ به دیجیتال در آردوینو را نیز مشاهده کنید.

Vref یا همان ولتاژ مرجع در ADC

این ولتاژ برای مقایسه با ولتاژ ورودی استفاده میشود. مثلا اگر ولتاژ مرجع را 4 انتخاب کنیم ، بازه 0-4 نیز به 1024 قسمت تقسیم میشود.

بررسی رجیستر کنترلی ADMUX

مشخصات رجیستر کنترلی ADMUX را در تصویر زیر میبینید :

رجیستر ADMUX

اگر در مورد این مطلب سوالی دارید در قسمت نظرات بپرسید

ما با بیت 6 و 7 این رجیستر سر و کار داریم. یعنی REFS1 و REFS0. در تصویر زیر مشخصات این بیت ها ذکر شده است :

بیت های REF در ADC

  • ردیف 1: ولتاژ پایه AREF به عنوان مرجع انتخاب میشود.
  • ردیف 2: ولتاژ پایه AVCC به عنوان مرجع انتخاب میشود.
  • ردیف 3: رزرو شده است.
  • ردیف 4: ولتاژ مرجع داخلی 2.56 ولت تثبیت شده به عنوان مرجع انتخاب میشود.

اگر انتخاب ما ردیف 1 باشد ، هر ولتاژی را که به پین AREF بدهیم به عنوان ولتاژ مرجع استفاده میشود. در حالت دوم نیز هر ولتاژی را که به پین AVCC بدهیم به عنوان ولتاژ مرجع انتخاب خواهد شد. در ردیف چهارم خود میکروکنترلر ولتاژ 2.56 ولت را به عنوان ولتاژ مرجع در نظر میگیرد.

بیت های 0، 1، 2، 3، 4 MUX4:0 – Analog Channel and Gain Selection Bits
این بیت ها برای پیکربندی آنالوگ به دیجیتال در میکروکنترلر AVR استفاده میشوند. با استفاده از جدول زیر میتوانیم کانال مورد استفاده را (P0-P7) مشخص کنیم.

انتخاب کانال برای adc

رجیستر  ADCSRA

رجیستر  ADCSRA

بیت 7 : ADEN – ADC Enable : وظیفه فعال و غیرفعال کردن آنالوگ به دیجیتال را بر عهده دارد.

بیت 6 : ADSC – ADC Start Conversion : 

قبل از تبدیل باید مقدار این بیت 1 باشد و سپس (بعد از انجام تبدیل) به 0 تغییر میکند.

مبدل آنالوگ به دیجیتال در میکروکنترلر AVR دارای دو Mode است : Single – Free

در Mode سینگل ، بعد از هر تبدیل ADC منتظر میماند تا دوباره تحریک شود. این تحریک توسط برنامه نوشته شده مشخص میشود. در مود Free ، مبدل ADC پی در پی و بدون توجه به برنامه نوشته شده نمونه برداری میکند. و در رجیستر ADCH,ADCL اطلاعات را ذخیره میکند.

حالا اگه مد تبدیل Single مدنظر باشه، کافیه یکبار 1 را بنویسیم در این بیت و پس از انجام تبدیل خود به خود به 0 تغییر میکند. اما اگر مود تبدیل Free باشد ، برای شروع باید حتما این بیت را 1 کنیم. برای انتخاب مد از طریق بیت های ADTS0:2 رجیستر SFIOR اقدام کنید.

بیت 5 : ADATE – ADC Auto Trigger Enable :

با 1 شدن این فلگ،خاصیت تحریک اتوماتیک فعال میشود. در حالت با هر لبه بالارونده پالس اعمال شده به CPU، واحد ADC تحریک میشود.

بیت 4 : ADIF – ADC Interrupt Flag :

این فلگ به فلگ وقفه ADC معروف است و هر وقت که عملیات تبدیل ADC تمام شود این بیت بصورت اتوماتیک 1 میشود و ما را از انجام عملیات تبدیل مطلع میکند.

بیت 3 : ADIE – ADC Interrupt Enable :

1 بودن این بیت به این معنی است که وقفه ADC فعال است و 0 بودن آن حاکی از غیرفعال بودن آن است.

بیت های 0 و 1 و 2 : ADPS2:0 – ADC Prescaler Select Bits :

این بیت ها برای انتخاب ضریب تقسیم فرکانس واحد ADC هستند. میکروکنترلرهای AVR (مثلا ATmega32) با فرکانس های مختلفی میتوانند کار کنند. قابلیت تنظیم فرکانس بصورت نرم افزاری وجود دارد. فرض کنید که فرکانس کاری را روی 16 مگاهرتز تنظیم کردیم.این 16 مگاهرتز،فرکانس کاری کلی میکرو هست.

بخش ADC هم برای فعالیت نیاز به یه فرکانسی دارد که فرکانس خودش را هم از همین 16 مگاهرتز تامین میکند. برای اینکه میزان تفکیک پذیری و دقت بالا رود، سازنده میکروکنترلر AVR یک ناحیه فرکانس برای فعالیت واحد ADC مشخص کرده است که طبق مقدار اعلام شده باید بین 50 کیلوهرتز تا 200 کیلوهرتز باشد.

راهی که خود اتمل پیش پای ما گذاشته است این است که فرکانس کلی یعنی 16 مگاهرتز را به یک عدد تقسیم کنیم تا کار آسان تر شود.

اگر بخواهید حداکثر دقت را در تبدیل ADC داشته باشید باید فرکانس کاری را در محدوده 50 کیلوهرتز تا 200 کیلوهرتز بگذارید، زیرا اگر حاصل تقسیم بزرگتر از 200 کیلوهرتز باشد دقت 10 بیت از دست میرود.

بیت های ADPS

با توجه به جدول بالا ، به طور مثال برای فرکانس کاری 16 مگاهرتز و ضریب تقسیم 128 داریم :

F_ADC = 16M/128 = 125kHz

پس اینجا ضریب تقسیم 128،مقدار مناسبی است زیرا عدد حاصل در محدوده مورد نظر ما قرار دارد. پس میتوانیم مقدار بیتهای این بخش را به صورت 111 در نظر بگیریم.

بررسی رجیستر ADC (ADCH,ADCL) 0:

رجیستر ADCH و ADCL

در این دو رجیستر اطلاعات خروجی ADC قرار میگیرند. یعنی وقتی تبدیل انجام شد،مقدار حاصل با دقت مورد نظر مدر این رجیستر قرار میگیرد. گفتیم که دقت واحد ADC در میکروکنترلرهای AVR به 10 بیت میرسد. یعنی طول داده ها 10 بیت است. خب همانطور که میدانیم هر رجیستر 8 بیت دارد. حالا چطور 10 بیت را در 8 بیت قرار بدهیم ؟

اتمل برای اینکار 2 رجیستر 8 بیتی را اختصاص میدهد یعنی 8+8=16. خب ما 10 بیت نیاز داریم و استفاده میکنیم و آن 6 بیت دیگر هم هیچ ! برای اینکه دو رجیستر با هم مخلوط نشوند به آن ها پسوند H و L داده اند.

اگر ADLAR=1 باشد نتیجه تبدیل بصورت تنظیم از چپ و اگر ADLAR=0 باشد نتیجه به صورت تنظیم از راست اطلاعات در رجیسترها قرار میگیرند. در تصویر بالا ، جدول اول برای تنظیم از راست و جدول دوم برای تنظیم از چپ است.

بررسی رجیستر SFIOR :

رجیستر SFIOR در ADC میکروکنترلر AVR

در کل در مبحث ADC زیاد از این رجیستر استفاده نمیکنیم. ولی اگه بیت ADATE از رجیستر ADSRA را 1 قرار دادید، تبدیل ها با یک لبه صعودی تحریک کننده اتفاق می افتند.

بیت های 5 و 6 و 7 ؛ ADTS0:2 – ADC Auto Trigger Source :

از طریق این سه بیت و با توجه به جدول زیر مشخص میکنیم که واحد ADC چگونه تحریک میشود.

کنترل وقفه آنالوگ به دیجیتال میکروکنترلر AVR

گاهی وقتها لازم است که براساس یک رخداد خاص، ADC فعال شود. مثلا : هرگاه وقفه خارجی اتفاق افتاد،ADC تبدیل را شروع کند.

کد نمونه:

#define F_CPU 8000000UL 
#include <avr/io.h>
#include <util/delay.h>
#include 
#include "LCD_16x2_H.h"

void ADC_Init()
{
	DDRA=0x0;			/* ورودی کردن پورت آنالوگ به دیجیتال */
	ADCSRA = 0x87;			/* فعال سازی مبدل, تقسیم به128  */
	ADMUX = 0x40;			/* Vref: Avcc, ADC channel: 0 */
	
}

int ADC_Read(char channel)
{
	int Ain,AinLow;
	
	ADMUX=ADMUX|(channel & 0x0f);	/* تعیین کانال ورودی برای خواندن */

	ADCSRA |= (1<<ADSC);		/* شروع تبدیل */
	while((ADCSRA&(1<<ADIF))==0);	/* اطلاع از تمام شدن تبدیل */
	
	_delay_us(10);
	AinLow = (int)ADCL;		/* خواندن بیت های کم ارزش*/
	Ain = (int)ADCH*256;		/* خواندن 2 بیت با ارزش و ضرب در وزن  */
	Ain = Ain + AinLow;				
	return(Ain);			/* برگرداندن مقدار دیجیتال*/
}

 
int main()
{
	char String[5];
	int value;

	ADC_Init();
	LCD_Init();			/* پیکربندی ال سی دی */
	LCD_String("ADC value");	/* نوشتن رشته روی خط اول */

	while(1)
	{
	
		LCD_Command(0xc4);	/* تغییر نشانگر ال سی دی */
		value=ADC_Read(0);	/* خواندن پایه A0 */
		itoa(value,String,10);	/* تبدیل عدد به رشته */ 
		LCD_String(String);						
		LCD_String("  ");			
	}
	return 0;
}
4.2 (22 نفر)

برای دریافت مطالب جدید کانال تلگرام یا پیج اینستاگرام ما را دنبال کنید.

محمد رحیمی

محمد رحیمی هستم. سعی میکنم در آیرنکس مطالب مفید قرار بدهم. سوالات مربوط به این مطلب را در قسمت نظرات همین مطلب اعلام کنید. سعی میکنم در اسرع وقت به نظرات شما پاسخ بدهم.

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *