پیش فرض من این است که با خود زبان C آشنایی کامل دارید با این حال می خوام نکاتی در مورد برنامه نویسی با C بگم توی میکرو تابع رو به این صورت تعریف کنیم
void (*function)(void) = 0x0000;
میکرو به اون آدرسی که نوشته شده
پرش می کنه! مثلا با کد بالا میکرو تقریبا ریست میشه می تونید ادرس رو تغییر بدید
و به بوت لودر پرش کنید و ...
اگه یه متغییری دارید که هم در توابع تغییر پیدا می کنن هم توی
روتین وقفه باید اونو از نوع
"volataile" تعریف کنید!
volataile int iranled=0xFFFF;
سعی کنید متغییر هایی که فقط توی
یه تابع استفاده میشن رو محلی تعریف کنید تا حجم کمتری اشغال بشه اینجوری ممکن هست
متغییر توی ریجیستر های عمومی یا استک قرار بگیره ولی در حالت عمومی یه آدرس بهش
توی اسرم تعلق می گیره!
سعی کنید حلقه های خودتون رو به صورت کاهشی بنویسید!
چرا؟ چون در حالت افزایشی باید مدام با مقدار مشخص شده مقایسه بشه
ولی در حالت کاهشی وقتی مقدار به صفر رسید فلگ Z فعال میشه!
بعضی وقت ها توی بررسی تساوی به
جای استفاده از "==" از "=" استفاده می کنیم! تو هزار خط کد
مشکل رو پیدا کن!
یادتون باشه که مقداری که تابع بر میگردونه یه متغییر محلی نباشه
چون در این صورت مقدار پاک میشه و یه چیز بی خودی برگشت داده میشه ) اگه محلی بود استتیک باشه که مقدار
از بین نره! (
وقتی اشاره گر تعریف می کنید
int* p, q, r;
الان فقط اولی اشاره گر هست اگه خواستید همه اشاره گر باشن باید این جوری بنویسید!
int *p, *q, *r;
شروع آموزش ATMEL STUDIO با همون AVRSTUDIO
پیش نیاز
ATMEL STUDIO 6
Extensions to the C Language Family-
USERMANUAL-
list of
all documented functions, variables, defines, enums, and typedefs with links to
the documentation-
اینم
لینک کتابخونه کامل
چیزی که هست اینه که همه رو ATMELSTUDIO
داره بیشتر مال WINAVR هست
تمامی کتابخانه های پر کاربرد رو توضیحش رو همین جا میزارم
و نکات مهم منابع بالا رو ذکر می کنم اون هارو گفتم اگه خیلی عجله
دارید یا می خواید بیشتر یاد بگیرید ببینید
اصولا تنظیم ریجیستر ها کار سختی هست هم اسمشون یادمون نمی مونه هم
نحوه مقدار دهیش! برای همین من توصیه می کنم CODEVISION نسخه رایگانش رو بگیرید (رایگان
برای این که 1- کار مارو راه میندازه 2- اون دنیا ...)
البته خیلی هم روش حساب نکنید بعضی مواقع سوتی میده (خودم سر سرعت
دو سیمه یک هفته الاف شدم تا فهمیدم اشتباه مقدار دهی کرده!)
New Project
در سمت چپ یکسری پیش فرض هایی هست
که پروژه رو بر اساس اون ها بسازید که مال برد های مختلف هست که شما ندارید
یکی از قسمت هاش اسمبلر معروف هست
اما توی همین قسمت که می بینید 4 گزینه وجود دارد که ما همون سی خودمون رو انتخاب می
کنیم و اطلاعات پروژه خودتون رو بنویسید و کلیک ...
این صفحه میاد
میکرو ی مورد نظر رو انتخاب کنید (mega16 )
در سمت چپ یکسری اطلاعات در موردش میاد حافظه و ...سخت افزار هایی که می تونن باهاش
کار کنن , دیتاشیت و ...
OK کلیک را کلیک کنید
.....
اون قسمت سمت چپ برای شما جزو گروه
راست هست که اگر میخواید درگ انجام بدید و بیاریدش اینجا اما این VA چی هست؟
این کد نویسی رو راحت می کنه یکی از قسمت هاش همین outline هست که میبینید و همه ی توابع و
متغییر ها و ... رو نشون میده تا سریع به اون جا برید!
به محیط خوش آمدید
VA:VAssistansX
کد نویسی را راحت می کنه یکی از
قسمت هاش همین outline هست که میبینید و همه ی توابع و
متغییر ها و ... رو نشون میده تا سریع به اون جا برید!
نشون دادن خطا ها و تکمیل کردن نوشته هم از کار هاش هست
برای تکمیل کردن یه کار جالبی هم میشه کرد مثلا دستور if رو بنویسید و بعدش TAB رو بزنید! آزمایش کردید منظورم رو
متوجه می شید!
اما برای تنظیم کامپابلر برای پروژه خودتون در منوی پروژه به پروپرتیز برید و در این قسمت
می تونید تنظیمات رو انجام بدید
شرح کامل در آینده!
اما حالا برای خالی از لطف نبودن این آموزش یه برنامه هم می نویسیم!
برای کسایی که C بلدن که توضیح نمیخواد!
با کلید F7 کامپایل میشه و اطلاعات کامپایلر نوشته میشه
اگه یه کمی بالا تر برید اطلاعات دیگه ای هم نوشته شده
فایل کامپایل شده در پوشه دیباگ
ایجاد میشه جون برنامه توی این مد هست
اگه می خواید تغییرش بدید از منوی اون وسط که دیباگ زار میزنه
ریلیز رو انتخاب کنید
یکی از اولین نیاز های برنامه نویسی با C اشنایی با ریجیستر های مختلف هست و
در صورت امکان آشنایی با دستورات اسمبلی.
هر دوتای این هارو در آخر دیتاشیت کامل میکرو ها به صورت خلاصه
نوشته.
احتمالا همه ی شما کار دو ریجیستر DDRX و PORTX رو میدونید ولی در اکثر موارد به
دسترسی بیتی به این ها نیاز داریم!
مثلا میخوایم بیت دوم از فلان ریجیستر رو یک کنیم یا مقدارش رو
بخونیم.
اینجا کلا در مورد توابع بیتی توضیح میدم.
این توابع در
"AVR/SRF_Defs.h" هستند که به صورت پیش فرض فراخوانی میشند!
اولین تابع
bit_is_clear(sfr, bit)
این تابع در ابتدا آدرس ریجیستر را
می خواهد (می توانید از نام آن ها هم استفاده کنید ) مثلا ( PORTC,TCNT0,0x33 ) و در قسمت دوم شماره بیت مورد نظر در صورت صفر بودن ان بیت مقداری
نا صفر و در صورت یک بودن بیت مقدار صفر برگردانده میشود
تابع بعدی
bit_is_set(sfr, bit)
مانند بالایی با این تفاوت که در
صورت صفر بودن بیت مقدار صفر و درصورت یک بودن آن مقداری ناصفر را باز میگرداند
-
تابع بعدی
loop_until_bit_is_set(sfr, bit)
مانند بالایی ها مقدار دهی می شود
و تا یک شدن بیت مورد نظر منتظر می ماند.
-
تابع بعدی
loop_until_bit_is_clear(sfr, bit)
برعکس تابع قبلی منتظر صفر شدن بیت
مورد نظر می ماند.
این تابع ارزش مکانی بیت در مبنی 10 را باز می گرداند.
_BV(bit)
در واقع 1 به اندازه ی مقدار داده
شده به سمت چپ شیفت داده میشود.
-
اما ما برای یک یا صفر کردن ریجیستر ها نیز نیاز به توابعی داریم
برای این کار از این توابع نوشته شده (از یه بنده خدایی یاد گرفتم)
استفاده کنید این هارو باید در پروژه خودتون بنویسید.
این توابع در اصل سه تابع هستند که
بقیه از یکدیگر استفاده می کنند در واقع کار برخی از توابع قبلی رو انجام میدهند.
اولی BITVAL که مانند توابع قبلی اول ادرس و
بعد شماره یه بیت را می گیرد و در صورت یک بودن بیت مقدار 1 و در صورت صفر بودن بیت
0 را باز میگرداند
SETBIT که مانند قبلی ها مقدار دهی میشود
و بیت متناظر را یک می کند.
CLEARBIT نیز به هم چنین بیت متناظر را صفر
می کند.
برای تغییر وضعیت یک بیت هم میتوانید این گونه عمل کنید
X^=_BV(Y)
که اگر می خواهید به صورت تابع استفاده کنید این کد رو اضافه کنید
#define TOG(x,y) (x)^_BV(y)
و مساوی پورت مورد نظر قرار دهید یعنی اینجوری استفاده کنید برای مثال
PORTC=TOG(PORTC,0)
برای پورت ها هم مقدار هایی شبیه PORTC,0 و PORTD,5 تعریف شده اند که اینها صرفا 1 که
به اندازه ی عدد پورت شیفت داده شده هستند ،
-
برای ایجاد تاخیر دو کتابخانه جود دارد
میکرو یه دستوری به نام nop داره که توی C میتونید اینجوری استفاده ازش بکنید
asm("nop")
و کارش اینه که یک کلاک رو بدون
انجام هیچ کاری سپری میکنه ( تلاش کنید از این دستور برای ایجاد
تاخییر استفاده نکنید!(
این دو کتابخانه عبارت اند از
#define F_CPU 8000000UL
مثلا الان من کلاک 8 مگا رو تعریف
کردم.
توجه کنید که قبل از فراخوانی کتابخانه این رو تعریف کرده باشید
اولیم کتابخانه
توی این کتابخانه این دو تابع وجود دارد
void _delay_ms (double __ms)
میزان تاخییر به میلی ثانیهمی باشد توجه کنید که یک متغییر رو نمیشه
به این توابع ارسال کرد! ( باید عدد در Flash ذخیره شده باشه )
برای حفظ دقت باید اپتیمایز کردن کد رو فعال کنید
حداکثر تاخیر با دقیق حداکثر این است
262.14 ms / F_CPU in MHz
که اگه یه مقداری بیشتر به تابع
بدید دقت به مرور کم میشود
و این حداکثر مقداری هست که میشه به تابع داد وبیشتر از این
اورفیلو میشه
4294967.295 ms/ F_CPU
void _delay_us (double __us)
این درحد نانو ثانیه تاخیر ایجاد
می کنه
حداکثر عدد برای بیشترین دقت
void _delay_us (double __us)
و بیشترین عددی که به تابع میشه داد
4294967.295 us/ F_CPU
کتاب خانه ی بعدی
#include <util/delay_basic.h>
کتابخانه ی قبلی هم از همین
استفاده می کنه با این تفاوت که محاسبات رو خودش انجام میده
void _delay_loop_1 ( uint8_t __count )
ایجاد یک تاخیر با کانتر 8 بیتی
به تابع حداکثر 255 میشه ورودی داد
در فرکانس 1 مگ حداکثر 768 میکرو ثانیه میشه تاخیر ایجاد کرد
void _delay_loop_2 ( uint16_t __count )
ایجاد تاخیر با کانتر 16 بیتی
به تابع حداکثر 65535 میشه داد
در فرکانس 1 مگ حداکثر تاخیر 262 میلی ثانیه
-
پیشنهاد میکنم از همون کتابخونه ی قبلی استفاده کنید که این مشکلات
رو نداشته باشید.
استفاده از Watchdog
#include <avr/wdt.h>
این توابع داخلش هست که خوب نیازی به توضیح نداره
برای مقدار آخرین تابع که زمان تایمر رو تنظیم می کنه این مقادیر قابل قبول هست
از اینکه میکرو یه شما اون مقدار
خاص رو پشتیبانی میکنه اطمینان حاصل کیند
برای کار با UART
سه راه دارید که ریجیستر هارو
تنظیم کنید!
1- استفاده از کتابخانه ی خود نرم افزار
2- کدویزارد کرویژن
3- فشار به مغز
دو روش دیگه با خودتون اولی رو من میگم
برای این کار از کتابخانه ی
"setbaud" استفاده می کنیم
برای این کار این سه خط رو اضافه کنید
طبق معمول نیاز به توضیحی که نداره!
فقط میزان خطا رو حواستون رو جمع کنید زیاد نشه!
بعد این قسمت رو اضافه کنید تا ریجیستر ها مقدار دهی بشن
برای وقفه و اینا دیگه باید برید
سراغ دیتاشیت یا کدویزارد!
اما با تنظیم این ها شما باید ریجیستر
"UDR" رو مقدار دهی بکنید تا نوشته بشه یا بخونید! که این چیزی نیست که
شما دنبالش باشید!
اصولا از دستور PRTINTF استفاده می کنیم اما این دستور هیچ
چیزی رو ارسال نمی کنه! چرا؟ چون خروجی اون تعیین نشده و باید مشخص بکنید که خروجی
اون باید به کجا بره برای انی کار از این کد استفاده می کنیم
و این یکی رو توی برنامه بنویسید که یک بار اجرا بشه
stdout = &mystdout;
حالا خروجی تابع printf به تابع زیر میره که باید به برنامه اضافش کنید!
دقیقا منم نگرفتم که اون دو خط
اولی چه کاری میکنن! به هر حال مارو به خواستمون میرسونن! شما میتونید برای کار
های دیگه هم ازش استفاده کنید مثلا جای ارسال به UART توی یک رشته ذخیره کنید! کار جالبی
میشه نه!
_
توابع مدیریت توان!
برای این کار این کتابخونه رو اضافه کنید!
#include <avr/sleep.h>
این کتابخونه شمال این توابع است
ابتدا فعال میکنید بعد سی پی یو رو
به اسلیپ می برید و بلافاصله بعد از بیدار شدن غیر فعال کنید تا دباره به خواب
نرود!
البته اگر قبل از ان وقفه ای رو فعال نکرده باشید یا وقفه سراسری
غیر فعال باشه اون وقت هست که دیگه میکرو به کما میره تا شما ریستش کنید
برخی میکرو ها این قابلیت رو دارد که قبل از به خواب رفتن brown down رو هم خاموش کنن برای این کار قبل از به خواب بردن میکرو این رو اضافه بکنید
sleep_bod_disable();
اما قبل از همه ی این ها نیاز هست
مد خواب رو تعیین کنید: 1- زمستانی 2- عصرانه 3- اقما و ...
برای این کار قبل از فرا خوانی هر کدام از توابع بالا این کد رو
اضافه کنید
set_sleep_mode(<mode>);
که به جای "<mode>" این ها رو می تونید بزارید
البته باید این قابلیت رو میکرو
داشته باشه وگرنه کامپایلر خطا میده پس هر میکرویی همه ی حالات بالا رو نداره!
اینم یه نمونه کد
فقط یک بار که نوع اسلیپ رو مشخص
کنید کافی هست مگر اینکه بخواید تغییرش بدید و نیازی نیست هر دفعه قبل از به خواب
رفتن مشخصش کنید.
اگر احیانا یکی از حالاتی رو می خواستید که اون بالا من ننوشته
بودم و میکرو ی شما قابلیتش رو داشت می تونید عدد مربوط به ریجیستری که اسلیپ رو
مشخص می کنه رو به تابع بدید.
حافظه EEPROM
حافظه EEPROM که در این پست قصد استفاده از آن
را داریم نسبت به کدویژن دارای پیچیدگی بیشتری است!
ابتدا فایل مربوط به این حافظه را به برنامه اضافه می کنیم
#include <avr/eeprom.h>
یه ذره توابع موجود و اینا زیاد
هست برای همین تو این لینک می تونید کامل ببینید ولی من اون هایی که نیاز دارم رو توضیح میدم.
اما قبل از هر چیز یه سری متغییر استفاده شده اند که لازم هست
توضیح بدم اون هارو!
زیاد پیش میاد که توی برنامه هایی که می بینید از متغییر هایی از نوع "uint8_t" و اینا استفاده شده باشند!
این ها فرقی با قبلی ها ندارن ولی برای اینکه هر کامپایلری بتونه
با برنامه کار کنه از این ها استفاده می کنن
توی این فایل که باید به برنامه اضافه کنید
#include <stdint.h>
لیست کاملی از این ها اضافه میشه و
برای مثال توی C ما از
"unsigned char" استفاده می کنیم پس
"uint8_t" به اون ترجمه می شه ممکن هست فلان کامپایلر "un
ch" باشه پس
"uint8_t" به اون تبدیل میشه!
کلا این ها توی این فایل سرامد تعریف شدن!
چیز های دیگه ای هم توی این فایل
هست که فعلا زیاد کاری باهاشون نداریم ولی توی این لینک می تونید ببینید
اولین قدم می خوایم از آدرس 60 حافظه یه داده ای رو بخونیم!
برای خوندن دو بایت از حافظه یا به عبارتی متغییر int این گونه عمل می کنیم
این دستور از 46 و 47 داده رو می
خونه و توی متغییر ذخیره می کنه
برای متغییر های بزرگ از
eeprom_read_dword()
و برای اعداد اعشاری از
eeprom_read_float()
استفاده می کنیم
برای نوشتن یک بایت در حافظه این گونه عمل می کنیم
حالا متغییر ما رو توی قسمت 46 حافظه ذخیره کرد و همانطوری که انتظار دارید برای متغییر های 2 بایتی از
و دو باره برای متغییر های 4 بایتی از
eeprom_update_dword()
و اعشاری ها
eeprom_update_float()
حالا ما می تونیم دونه دونه
بنویسیم یا بخونیم ولی نیاز هست گاهی که چند تا رو بخونیم مثلا ارایه ها یا یک
رشته متنی که ذخیره شده!
برای این کار از این تابع استفاده می کنیم
void eeprom_read_block ( void * pointer_ram , const void * pointer_eeprom , size_t n)
شاید تعجب کنید که هیچ مقداری رو
بر نمی گردونه !
این مقدار در متغییری که ادرسش رو به عنوان اولین ورودی به تابع
دادید ذخیره میشه!
برای مثال ما از این برای خواندن 10 بایت پشت سر هم از ادرس 12 رو
می بینیم
حالا شاید از من بپرسید این void این وسط چه فایده ای داره؟!
در جواب می گم در مثال های قبل با اندازه ما مثلا یک متغییر دو
بایتی رو خوندیم که ممکن بود که علامت دار باشد یا نباشد و نوع آن را مشخص می
کردیم در واقع برای تابع اهمیت داشت که چه مقداری رو می خواند!
اما گاهی ما نمی دانیم که داده ای که درحال خواندن آن هستیم چه نوع
داده ای است! شاید هم اصلا مهم نباشد! برای همین از void استفاده می کنیم با این کار تابع
فقط مغدار را می خواند و دیگر کاری به نوع داده ی خوانده شده (متن - اعشاری - صحیح
- منفی و...) ندارد و عین آن را در خروجی ظاهر می کند در مثال بالا 10 بایت پشت سر
هم خوانده شده و در 10 عضو ارایه نوشته می شود.
برای نوشتن در حافظه هم این گونه عمل میشود
اولین ورودی از کلمه ی const استفاده شده است چون دیگر نیازی
نیست که تغییری در آن در تابع ایجاد شود و فقط قرار است مقدار آن خوانده شود.
حال از خانه 12 به صورت متوالی برای 10 بایت در حافظه نوشته میشود
که 5 تای آن مقداری که در متغییر ما موجود است نوشته میشود و بقیه مقدار 0 می
گیرند
حالا ما کار با این حافظه رو یاد گرفتیم ولی حتما این چیزی نیست که
ما بخوایم چون وقتی کمی تعداد متغییر ها زیاد میشن دیگه به خاطر سپردن آدرس ها کار
ما نیست برای همین نیاز میشه که مثل بقیه متغییر ها ، متغییری برای حافظه تعیین
بکنیم تا کار را برای ما ساده تر بکند!
برای این کار مانند تعریف متغییر ها عمل می کنیم با این تفاوت که "EEMEM" را به قبل آن ها اضافه می کنیم که
به کامپایلر می گوید متغییر ها در حافظه EEPROM تعریف شوند
برای مثال
اما با این حال این به این معنی نیست که مانند متغییر های معمولی به طور مستقیم به آن ها دسترسی داشته باشیم
برای مثال این کد کار نمی کند!
این ها صرفا یک ادرس هستند برای کار با ان ها باید مثل قبل عمل کنید
uint8_t EEMEM SomeVariable = 12;
تغییر رو می تونید داخل فایل خروجی
مربوط به حافظه مشاهده کنید
دقت کنید که پس از پروگرام کردن اگر مقدار در برنامه تغییر کرد با
شروع مجدد میکرو این مقدار ها برای بار جدیدی نوشته نمی شوند و مقدار های قبلی خود
را می گیرند!
کار با وقفه ها
کار با وقفه هارو آموزش بدم برای
این کار کتابخانه ی "AVR/INTERRUPT.H" رو به برنامه اضافه کنید
توجه کنید که تمامی ادرس های وقفه رو توی فایل اصلی بنویسید وگرنه
خطا میده
اولین دستور ها
مثلا این وقفه ی انالوگ به دبجیتال
رو به این جا میاره
برای هر
قسمتی اسم مخصوص به خودش رو داره این جا دنبالش بگردید
اگه یه وقفه ای رخ بده که هیچ چیزی براش تعریف نکرده باشید مثل
بالا موجب میشه میکرو ریست بشه!
برای همین از این استفاده کنید که همه ی وقفه هایی که بردارشون
مشخص نشده به اینجا برن
اصولا وقتی وقفه رخ میده وقفه ی سراسری غیر فعال میشه و بعد فعال تا توی وقفه وقفه انجام نشه برای غیر فعال کردن این قابلیت این جوری استفاده کیند
اگه می خواید دو تا وقفه به یک جا برن اینجوری استفاده کنید
الان دومی به همون اولی میره
اگه می خواید هیچ برنامه ای اجرا نشه اینو استفاده کنید
EMPTY_INTERRUPT(ADC_vect);
یکسری چیز هایی رو خود کامپایلر مدیریت می کنه مثل ذخیره ی SREG و باز گشت از وقفه و غیره اگه می خواید برنامه سریع تر اجرا بشه یا هرچی دیگه اینجوری استفاده کنید
اون reti اخر باید باشه چون باعث برگشت از
وقفه میشه در ضمن بدونید که چون هیچ کد اضافی نمی شه ممکن هست داده های مربوط به
برنامه که ذخیره شدن رو از بین ببرید پس اگه این کاره نیستید بی خیال شید
-
اینم باعث بازگشت از وقفه میشه به طور عادی نیازی به این نیست مگر
جا هایی که گفتم
تغییر سطح پین ( فشرده شدن کلید )
سلام میتونید با استفاده از یک دستور if تغییر سطح پین رو تشخیص بدین به شکل زیر:
if(bit_is_set(PINB,1))_delay_us(1),function();
این برای حالتی بود که اگه پایه یک بشه فعال دستور مورد نظر انجام بشه ولی اگه بخواین صفر شدنش رو چک کنید به شکل زیر مینویسید:
if(bit_is_clear(PINB,1))_delay_us(1),function();
به جای
عبارت
function() اسم تابعتون رو بنویسید که فراخوانی بشه .
وقتی که بخوایم زمانی رو با تایمر تولید کنیم از چه فرمول هایی باید استفاده کرد؟؟
باید با در نظر گرفتن فرکانس کریستال و همچنین مقدار
تقسیم فرکانسی که برای تایمر انتخاب میکنی زمان مورد نظر رو دربیاری
به فرض مثال اگه بخوای زمان 1 ثانیه رو ایجاد کنی باید به
تایمر هات نگاه کنی
میدونیم که تایمر0 هشت بیتی هستش و تایمر 1 شانزده بیتی
من به صورت پیشفرض با استفاده از تایمر یک اینو برای شما
توضیح میدم
فرض کنید که فرکانس کریستال شما 8 مگاهرتز باشه و برای
تایمر 1 هم تقسیم فرکانسی 256 رو در نظر گرفته باشید
پس:
8000000/256=31250
خب در این حالت میدونیم که فرکانس کلاک وارد شده به تایمر
31250 بار در ثانیه اس
پس زمان هر پله بالا رفتن تایمر میشه: (تایمر درواقع همون
کانتره)
1/31250=32us
و چون میخوایم یک ثانیه بسازیم داریم:
1000000/32=31250
پس عدد تایمر باید به 31250 برسه که بدونیم 1 ثانیه
گذشته(با توجه به تنظیمات انجام شده)
اگه تایمر 1 رو تو مد ctc بذارین و عددش رو هم
31250 بذارین سر 1 ثانیه میتونید وقفه هم داشته باشید
امیدوارم جواب بقیه سوالهاتونم داده باشم
در مورد انتخاب تقسیم فرکانسی برای تایمر هم باید بگم که
باید نگاه کنید که از بین اعداد پیشفرض کدوم عدد برای کار شما مناسبه این کار با
تجربه براتون راحتتر میشه
برای ایجاد pwm هم دو مود داریم که مد fast pwm در حالت یک شیبه هستش و اون یکی دو شیبه ، تو fast pwm از روی شیب تایمر
میتونید درصد دیوتی رو تغییر بدین و دو دوشیبه هم همینطور یعنی شما با تغییر ocrx میتونید تغییراتی در دیوتی سایکل ایجاد کنید
باسلام و خسته نباشید
شروع خوب و پرباری بود ، ادامه بدید لطفاً
با سپاس فراوان
سلام!
مطالبون عالیه!
من یه سری مشکل در مورد کار با avr gcc دارم ، مثلا میخوام یه برنامه ای تحت ویندوز بنویسم که طبق یه قواعدی یه سری کد به زبون سی تولید کنه!
خب حالا میخوام این کد ها را برای avr کامپایل کنم! بعد از سرچ کردن متوجه شدم که باید از avr gcc استفاده کنم که مجموعش را هم دانلود کردم ولی هیچ گونه اطلاعاتی در موردش ندارم!
ممنون میشم اگه راهنماییم کنید
سلام
ممنون از مطالب مفیدتون
من میخواستم بدونم برای پروگرم کردن میتونیم مستقیما از این برنامه استفاده کنیم؟
سلام و خسته نباشید
واقعا مطالب عالی بودن
ممنون
سلام ممنون از اموزش خوبتون من نیاز به راهنمایی دارم ، مفهوم دستورهای زیر را متوجه نمی شم میشه بگید مفهومشون چیه و نمونه ی چه دستوری در codevision میشن
PORTB &= ~(1<<PORTB.1 یا
PORTB |= (1<<PWM_PIN1)