مبدل آنالوگ به دیجیتال یا به اختصار ADC، بخش جدا نشدنی تمامی میکروکنترلرها از جمله AVR است. چون عملیات درون میکروکنترلر به صورت دیجیتال (0 و 1) است، سیگنالهایی که به صورت آنالوگ از بیرون به میکرو اعمال میشوند، باید قابل سنجش باشند. مبدل ADC سیگنال آنالوگ را به دیجیتال تبدیل میکند تا برای میکروکنترلر قابل فهم باشد.
از طرفی مبدل ADC تنها مخصوص میکروکنترلرها نیست و آیسیهایی به صورت جداگانه برای اینکار ساخته شدهاند که در اکثر مواقع، دقتی بیشتر از واحد ADC درون میکروکنترلر دارند.
مشخصات مبدل ADC
هر مبدل آنالوگ به دیجیتال مشخصات زیادی مثل ولتاژ آفست خروجی، نسبت سیگنال به نویز، ضریب تبدیل غیرخطی، تعداد نمونه در ثانیه، دقت، ولتاژ مبنا و اتلاف توان دارد. اما از مهمترین این مشخصات تعداد نمونه در ثانیه، دقت و ولتاژ مبنا است.
تعداد نمونه در ثانیه یا Sample Rate
به تعداد نمونه یا Sample که در مدت یک ثانیه، مبدل ADC میتواند تبدیل کند، Sample Rate گفته میشود. به عنوان مثال اگر مدت زمان هر تبدیل 20 میکروثانیه باشد، مقدار Sample Rate برابر 50K نمونه در ثانیه است. یعنی مبدل ADC در هر ثانیه، 50 هزار بار سیگنال آنالوگ ورودی را به سیگنال دیجیتال تبدیل میکند.
ولتاژ مبنا یا Reference Voltage
مقدار ولتاژی است که باید به عنوان مرجع برای ADC تعیین شود. به عبارتی بیشترین مقدار ولتاژ ورودی، نباید از ولتاژ مبنا بیشتر باشد. در میکروکنترلرهای AVR، اکثرا ولتاژ مرجع، 5 ولت در نظر گرفته میشود.
دقت یا Accuracy
وضعیت سیگنال ورودی که مشخص است؛ یک سیگنال آنالوگ که البته مقدار آن بین بازهای محدود است. اما خروجی که حتما دیجیتال است، برحسب تعداد بیت مشخص میشود. دقت یا Accuracy یعنی چه مقدار تغییر ولتاژ در ورودی لازم است تا خروجی به اندازه 1 واحد تغییر کند. دقت مبدل ADC از رابطه زیر به دست میآید.
در فرمول فوق، Vref ولتاژ مبنا و n تعداد بیت خروجی است. به عنوان مثال اگر خروجی 8 بیتی و ولتاژ مبنا برابر 5 ولت باشد، در این صورت دقت مبدل ADC برابر 0.0196 ولت یا 19.6 میلیولت خواهد شد.
سوال: اگر ولتاژ مبنا 5 ولت و خروجی 10 بیتی باشد، دقت مبدل چقدر است؟
جواب: با تقسیم 5 بر 1023 ((1 – 1024)/5)، دقت مبدل، 4.88 میلیولت میشود.
مبدل ADC در میکروکنترلر AVR
مبدل ADC در میکروهای AVR به صورت 10 بیتی است و مطابق شکل زیر 8 کانال ورودی دارد. البته طبق توضیحات بالا در یک لحظه فقط یکی از ورودیها خوانده شده و تبدیل به دیجیتال میشود. این که کدام یکی از ورودیها خوانده شود، در بخش بعدی در مورد آن صحبت میکنیم.
در ATmega16 تمام کانالهای مبدل ADC بر روی پورت A قرار دارند. علاوهبر کانالها، دو پایه AREF و AVCC نیز مربوط به ADC هستند و ولتاژ مرجع باید به یکی از این دو پین اعمال شود.
رجیسترهای ADC
مثل تمام واحدهای میکروکنترلر، واحد ADC هم رجیسترهای منحصر به فرد خود را دارد. پنج رجیستر برای مبدل ADC تعبیه شده که عبارتاند از ADMUX ،ADCSRA ،ADCH ،ADCL و SFIOR.
رجیستر ADCL و ADCH
این دو رجیستر در واقع خروجی مبدل هستند و نتیجه نهایی، در این دو رجیستر قرار میگیرد. چون ADC به صورت 10 بیتی است، 8 بیت در یکی از این رجیسترها و 2 بیت دیگر در دیگری ذخیره میشود. ترکیب قرارگیری مقدار نهایی در این دو رجیستر توسط بیتی به نام ADLAR واقع در رجیستر ADMUX تعیین خواهد شد.
زمانی که بیت ADLAR برابر 0 است، 10 بیت خروجی به صورت زیر ذخیره میشوند. در این حالت 8 بیت کم ارزش در ADCL و 2 بیت باارزش در ابتدای ADCH قرار میگیرد.
اما اگر بیت ADLAR برابر 1 شود، در این حالت 8 بیت باارزش در ADCH و 2 بیت کم ارزش در انتهای ADCL قرار خواهند گرفت.
نکته: اگر ADLAR برابر 1 باشد، میتوان تنها با خواندن ADCH از مبدل ADC به عنوان یک مبدل 8 بیتی استفاده کرد.
نکته: در نرم افزار CodeVision متغیری به نام ADCW وجود دارد که 16 بیتی بوده و مقدارنهایی را میتوان با خواندن این متغیر به دست آورد. شکل این متغیر به صورت زیر است.
با توجه به شکل بالا، 8 بیت کم ارزش ADCW همان ADCL است و 8 بیت با ارزش آن ADCH میباشد.
رجیستر ADC Control Status Register A) ADCSRA)
این رجیستر شامل بیتهایی برای کنترل مبدل ADC است.
بیت ADC Enable) ADEN)
اگر بخواهیم از مبدل ADC میکرو استفاده کنیم، باید با 1 کردن این بیت آن را فعال کرد.
بیت ADC Start Converting) ADSC)
با نوشتن 1 بر روی این بیت، عمل تبدیل آنالوگ به دیجیتال برای یکبار انجام شده و پس از پایان تبدیل این بیت به صورت اتوماتیک 0 میشود.
بیت ADC Auto Trigger Enable) ADATE)
اگر این بیت 1 شود، عمل انجام نمونه برداری بدون استفاده از بیت ADSC👆 انجام میشود. ادامه بحث این بیت در رجیستر SFIOR گفته خواهد شد.
بیت ADC Interrupt Flag) ADIF)
پس از شروع شدن عمل تبدیل (حال به صورت دستی یا تحریک اتوماتیک) و با کامل شدن آن، این بیت به نشانه اتمام تبدیل 1 خواهد شد.
بیت ADC Interrupt Enable) ADIE)
با 1 کردن این بیت وقفه ADC فعال میشود و در صورت 1 بودن بیت وقفه عمومی، با هر بار تمام شدن عمل تبدیل که منجر به 1 شدن ADIF خواهد شد، وقفه رخ میدهد.
بیتهای ADC Prescaler Select) ADPS)
همانند تمامی واحدهای میکروکنترلر، واحد ADC هم برای کار کردن احتیاج به کلاک دارد. کلاک اصلی میکروکنترلر به یکی از ضرایب زیر تقسیم شده و به مبدل داده میشود.
به عنوان مثال اگر فرکانس میکرو 1MHz باشد، با انتخاب ADPS برابر “011”، ضریب تقسیم 8 انتخاب شده و فرکانس کلاک اعمالی به ADC برابر 125KHz خواهد شد.
رجیستر Special Function Input Output Register) SFIOR)
در انتهای این رجیستر 3 بیت برای تحریک اتوماتیک ADC تعبیه شده است.
بیتهای ADC Trigger Source) ADTS)
این سه بیت 8 حالت زیر را میتوانند داشته باشند.
تنها در صورتی میتوان تاثیر موارد فوق را مشاهده کرد که بیت ADATE در رجیستر ADCSRA برابر 1 شده باشد. در این حالت:
- اگر “000” انتخاب شود، هیچگونه تحریکی اعمال نخواهد شد.
- اگر “001” انتخاب شود، وقفه مربوط به مقایسه کننده آنالوگ باعث تحریک ADC میشود.
- اگر “010” انتخاب شود، وقفه خارجی شماره 0 (INT0) باعث تحریک میشود.
- اگر “011” انتخاب شود، عمل مقایسهای مربوط به تایمر 0 باعث تحریک میشود.
- اگر “100” انتخاب شود، هر بار سرریز تایمر 0 باعث تحریک خواهد شد.
- اگر “101” انتخاب شود، عمل مقایسه B در تایمر 1 تحریک ADC را انجام میدهد.
- اگر “110” انتخاب شود، هر بار سرریز تایمر 1 موجب تحریک ADC میشود.
- اگر “111” انتخاب شود، رخ دادن عمل کپچر تایمر 1 باعث تحریک میگردد.
آموزشهای مربوطه را میتوانید از لینکهای تایمر 0 و تایمر 1 مطالعه کنید.
رجیستر ADC Multiplexer Selection) ADMUX)
این که مقدار سیگنال کدام یک از 8 ورودی ADC خوانده و سپس تبدل شود، توسط این رجیستر مشخص خواهد شد.
بیتهای Reference Select) REFS)
این دو بیت مطابق جدول زیر ولتاژ مرجع را مشخص میکنند.
اگر “00” مقداردهی شوند، ولتاژ روی پایه AREF به عنوان مرجع انتخاب میشود.
اگر “01” مقداردهی شوند، ولتاژ پایه AVCC به عنوان مرجع قرار میگیرد. در این حالت باید پایه AREF با یک خازن 100 نانو زمین شود.
اگر “11” مقداردهی شوند، ولتاژ ثابت 2.56 به عنوان مرجع انتخاب خواهد شد.
نکته: حالت “10” غیرمجاز است.
بیت ADC Left Adjust Result) ADLAR)
وظیفه این بیت شرح داد شد و به عنوان یک توضیح مختصر، نحوه قرارگیری نتیجه درون ADCL و ADCH را مشخص میکند.
بیتهای MUX0 تا MUX4
این که سیگنال کدام یک از پایههای ADC به عنوان ورودی انتخاب شده و تبدیل صورت گیرد، با توجه به مقدار این 5 بیت مشخص میشود. به طور کلی واحد ADC دارای دو مد تک کانال و تفاضلی است که جزئیات آن در شکل زیر آمده است.
مد تک کانال یا Single
در این مد سیگنال یکی از ورودیها انتخاب میشود و پس از تبدیل، نتیجهنهایی در رجیسترهای ADCL و ADCH قرار خواهد گرفت. با توجه به جدول بالا 👆 حالتهای “00000” تا “00111” مربوط به مد تک کاناله هستند و به ترتیب پایههای ADC0 تا ADC7 به عنوان ورودی سیگنال انتخاب میشوند.
گفتیم که در نرم افزار CodeVision مقدار نهایی را میتوان با خواندن ADCW به دست آورد. مقدار نهایی مد تک کانال طبق روابط زیر به دست میآید.
در روابط فوق، Vref همان ولتاژ مرجع است؛ Vin یکی از 8 سیگنال ورودی است و ADCW مقدار نهایی تبدیل است.
سوال: اگر مقدار ADMUX برابر 0x45 شود، مبدل ADC در چه مدی و با چه ولتاژ مرجعی کار خواهد کرد؟
جواب: با توجه به مقدار 0x45، بیتهای REFS برابر “01” شده و پایه AVCC به عنوان مرجع انتخاب میشود. همچنین مقدار بیتهای MUX مساوی “00101” بوده که پایه ADC5 (پایه شماره 35 میکرو) به عنوان ورودی مد تک کاناله انتخاب میشود.
مد تفاضل یا Differential
در این مد اختلاف سیگنال 2 تا از ورودیها تبدیل شده و سپس حاصل در رجیسترهای ADCL و ADCH قرار میگیرد. در جدول بالا 👆 حالتهای “01000” تا “11101 مربوط به مد تفاضلی هستند.
در مد تفاضلی موارد زیر نقش اساسی خواهند داشت:
- ستون Positive Differential Input مشخص کننده پایهای است که سیگنال با ولتاژ بیشتر باید به این پین اعمال شود. این پایه در فرمول زیر با نام Vpos مسخش شده است.
- ستون Negative Differential Input مشخص میکند که سیگنال با ولتاژ کمتر باید به کدام پایه اعمال شود. این پایه در فرمول زیر با Vneg نامگذاری شده است.
- ستون Gain که شامل یک عدد است و حکم یک ضریب را دارد. این عدد در اختلاف بین دو ورودی ضرب میشود.
در روابط فوق Vpos سر + سیگنال، Vneg سر – سیگنال، Vref ولتاژ مرجع، Gain ضریب تقویت و در نهایت ADCW حاصل نهایی است.
سوال: اگر ADMUX برابر 0x49 شود، وضعیت مد و ولتاژ مرجع چگونه است؟
جواب: مقدار بیتهای REFS برابر “01” شده و AVCC به عنوان مرجع انتخاب میشود. همینطور مقدار بیتهای MUX مساوی “01001” است و مد تفاضلی با بهره 10 انتخاب میشود. در این مد باید سیگنال + به پین ADC1 و سیگنال – به ADC0 اعمال شود.
مثال 1 : مد تک کانال
برنامهای مینویسیم که ولتاژ روی پایه ADC0 را بخواند و بر روی LCD کاراکتری نشان دهد. محدوده ولتاژ ورودی بین 0 تا 5 ولت و ولتاژ مرجع هم 5 ولت است. چون ADC از نوع 10 بیتی است، طبق رابطه گفته شده در اوایل مطلب، دقت ADC برابر 4.88 میلی ولت میشود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#include <mega16.h> #include <stdio.h> #include <alcd.h> unsigned char buff[17]; float voltage; void main(void){ lcd_init(16); lcd_clear(); ///////////////////// ADC ADMUX = 0x40; ADCSRA = 0x8F; ADCSRA = ADCSRA|0x40; ///////////////////// Enable Global Interrupt #asm ("sei"); while(1); } interrupt[15]void adc_int(void){ voltage = ADCW*(5/1023.0); /////////////////////////////////////// show on lcd sprintf(buff,"%1.2fv",voltage); lcd_gotoxy(0,0); lcd_puts(buff); /////////////////////////////////////// trigger adc for next convert ADCSRA = ADCSRA|0x40; } |
توضیح برنامه
خط 1 تا 3: این سه خط هدر فایلهای لازم را به برنامه الحاق میکنند.
خط 4: یک آرایه به نام buff تعریف کردیم که 17 عضو دارد. این آرایه برای نشان دادن اطلاعات روی LCD استفاده خواهد شد.
خط 5: متغیر voltage را از نوع float تعریف میکنیم. در این متغیر مقدار ولتاژ خوانده شده ذخیره میشود.
خط 8 و 9: پیکربندی lcd انجام شده و یکبار تمام صفحه پاک میشود.
خط 11: در این خط مقدار رجیستر ADMUX برابر 0x40 میشود که مقدار بیتهای MUX مساوی “00000” بوده و کانال 0 به عنوان ورودی انتخاب خواهد شد. از طرفی، دو بیت REFS برابر “01” شده و پایه AVCC به عنوان مرجع ولتاژ انتخاب میشود.
خط 12: رجیستر ADCSRA را برابر 0x8F میکنیم. این مقدار باعث یک شدن بیت ADEN و ADIE شده که به ترتیب باعث فعالسازی مبدل ADC و همچنین وقفه آن خواهد شد. همینطور بیتهای ADPS هم در وضعیت “111” قرار میگیرند که ضریب تقسیم 128 را برای کلاک مبدل ADC انتخاب میکند.
خط 13: در این خط بیت ADSC را 1 میکنیم تا اولین عمل تبدیل سیگنال شروع شود.
خط 15 و 16: بیت وقفه عمومی یک شده و CPU وارد یه حلقه while بدون دستور میشود.
بلاک interrupt
شماره بین دو براکت عدد 15 است که مربوط به وقفه ADC میباشد. بنابراین هرگاه عمل تبدیل سیگنال آنالوگ به دیجیتال تمام شود، وقفه رخ داده و دستورات این بلاک اجرا میشود.
اولین دستور بلاک، خواندن مقدار ADCW و تبدیل آن به مقداری جهت ذخیره سازی در متغیر voltage است. فرمول این خط همان فرمول محاسبه مد تک کانال است. در ادامه مقدار voltage با دستور sprintf به صورت کاراکترهای نمایشی درون آرایه buff ریخته شده و در نهایت این آرایه روی lcd نمایش داده میشود.
آخرین خط این بلاک، بیت ADSC را 1 کرده تا عمل تبدیل بعدی آغاز شود. پس از پایان تبدیل، مراحل بالا تکرار میشود.
مثال 2 : مد دیفرانسیل
برنامه مثال قبل را طوری اصلاح میکنیم که اختلاف پتانسیل بین ADC1 و ADC0 گرفته شده و حاصل را نشان دهد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <mega16.h> #include <stdio.h> #include <alcd.h> unsigned char buff[17]; float voltage; void main(void){ lcd_init(16); lcd_clear(); ///////////////////// ADC ADMUX = 0x49; ADCSRA = 0x8F; ADCSRA = ADCSRA|0x40; ///////////////////// Enable Global Interrupt #asm ("sei"); while(1); } interrupt[15]void adc_int(void){ voltage = ADCW*(5/(1023.0*10)); /////////////////////////////////////// show on lcd sprintf(buff,"%1.3fv",voltage); lcd_gotoxy(0,0); lcd_puts(buff); /////////////////////////////////////// trigger adc for next convert ADCSRA = ADCSRA|0x40; } |
توضیح برنامه
تنها دو تفاوت با برنامه مثال 1 وجود دارد: خط 11 و خط 20.
خط 11: مقدار رجیستر ADMUX را به 0x49 تغییر دادیم. با اینکار مقدار بیتهای MUX برابر “01001” شده و مد دیفرانسل با بهره 10 انتخاب میشود. همچنین ADC1 به عنوان سر + سیگنال و ADC0 به عنوان سر – سیگنال عمل میکنند.
خط 20: فرمول استفاده شده در این خط مربوط به فرمول مد تفاضلی است. عدد 10 بیانگر بهره یا Gain، عدد 5 نشان دهنده ولتاژ مرجع و عدد 1023 هم ثابت است.
نکته: در مد تفاضلی بهره یا Gain نقش بسیار مهمی دارد. هرچه بهره بیشتر انتخاب شود، باعث افزایش دقت و از طرفی کاهش محدوده ولتاژ اختلاف دو سیگنال خواهد شد. در این مثال اختلاف دو سیگنال نباید بیشتر از 0.5 ولت شوند؛ در غیر این صورت خروجی عدد ثابت 0.5 را نشان میدهد.
جمع بندی
به عنوان یک توضیح مختصر باید گفت که مبدل ADC میکروکنترلر 10 بیتی است و میتواند در دو مد کلی کار کند: مد تک کانال و مد دیفرانسیل. واحد ADC از 5 رجیستر تشکیل شده که علاوهبر این رجیسترها، متغیری به نام ADCW وجود دارد و حاصل نهایی که 10 بیتی است، درون آن قرار خواهد گرفت.
از دیگر قابلیتهای مبدل ADC میتوان به تحریک اتوماتیک اشاره کرد که منابع آن میتواند تایمر 0 و 1 و یا وقفه خارجی شماره 0 باشد. برای آموزشهای بیشتر با رزدینو همراه باشید.
23 پاسخ
سلام خسته نباشی
واقعا آموزشاتون عالی و کامله
سلام خوشحالیم که مفید واقع شده در تلاشیم تا محیط را جهت اموزش بهتر هم کنیم.
الحق که کامله و معلومه زحمت زیادی بابت تهیه کردنش کشیده شده.
و این نشان دهنده احترام شما به مخاطبتون هست.
و من هم به عنوان یک مخاطب از شما تشکر میکنم.
نظرشما باعث خوشحالی ماست 🙂
سلام
تشکر میکنم از سایت خوبتون.
دنبال ی تدریس خصوصی خوب برنامه نویسی میکروکنترلر هستم. خودتون میتونین یا کسی مطمین میشناسین؟
ممنون میشم.
با سلام پیشنهاد ما به شما استفاده از ویدیوهای آموزشی یوتیوب است.
سلام استاد
%1.3f v دقیقا یعنی چی؟
سلام دوست خوبم جهت نمایش روی ال سی دی تا 3 رقم اعشار استفاده شده و حرف ( v ) نیز بعد از اعداد چاپ خواهد شد
ممنونم از بزرگواریتان
ممنونم
سلام
اگر بیت های mux برابر01000 در نظر گرفته شود ، چطور هم سر مثبت ولتاژ به adc0 باشد و هم سر منفی ؟
سلام. سر مثبت به adc0 و سر منفی همان زمین مدار است. با این تفاوت که مقدار خوانده شده در عدد 10 ضرب میشود. به همین دلیل ماکزیمم ولتاژی که می توان اعمال کرد 0.5 ولت است. چرا؟ 0.5 = 5/10
سلام
چقدررر سلیس و روان و بدون توپوق و ساده مسائل بعضا پیچیده رو توضیح دادین
آدم لذت میبره از این همه دقت و کفایت که به خرج دادین .
ازتون ممنونم و یه سوال دارم
در حالتی که قرار نیست که از مبدل آنالوگ به دیجیتال استفاده کنیم و پیکربندی پورتهای آنالوگ به دیجیتال به منظورهای دیگه مورد استفاده قرار میگیره تکلیف VREF و AVCC چی میشه
آیا باید شناور باشن یا به نحوی به ولتاژ یا … متصل بشن
بهترین حالت برای این دو پایه چیه که سبب بروز نویز یا مشکلات ناخواسته نشیم
سلام. خیلی ممنون از انرژی خوبی که بهمون دادید.
در مورد سوالی که پرسیدید باید بگم که اگه قراره باشه از ADC استفاده نکنیم، هیچ ایرادی نداره که پایه های AVCC و AREF آزاد باشن.
عالی بود مهندس ، خسته نباشید.یک سوال داشتم. بخواهم این دو مبحث adc و تایمر کانتر را یاد بگیرم ، اول روی کدام مبحث وقت بگذارم؟
سلام خسته نباشید. مبحث adc و تایمر کانتر ربط زیادی بهم ندارن. اما بهتره اول تایمر کانتر ها رو یاد بگیرید و بعد سراغ adc برید.
سلام وقتتون بخیر
اگه با سون سگمنت و ای سی های جانبی بخوایم برنامه رو بنویسیم باید چیکار کنیم
سلام . ای ول آهو فهم شدیم خدا چشم آهو نسیبتان کنه
ممنون🙏
بسیار عالی.
خیلی ممنون.
با تشکر فراوان از شما . سرعت کلاک چه نقشی در عملکرد ADC داره .
هر چقدر سرعت تبدیل ADC بیشتر باشد، نرخ تبدیل در واحد زمان بیشتر و از طرفی دیگر دقت کمی افت میکند. عکس قضیه نیز برقرار است.
عالی