خانه > آموزش > اولین پروژه با CodeVisionAVR و Proteus

اولین پروژه با CodeVisionAVR و Proteus

در این آموزش می­ خواهیم اولین پروژه را با استفاده از میکروکنترلر AVR به زبان C انجام داده و درستی آن را با استفاده از نرم ­افزار شبیه­ ساز پروتئوس بیازماییم.  برای این کار از نرم افزارهای codevision  و proteus کمک می گیریم. در این پروژه یک LED به پایه شماره 1 (PB0)میکرو متصل بوده و می ­خواهیم برنامه ­ای بنویسیم که میکروکنترلر این LED را با فواصل زمانی معین(مثلا یک ثانیه) خاموش و روشن نماید.

نحوه ایجاد یک پروژه در کدویژن

ابتدا در نرم افزار کدویژن از منوی File گزینه New Source File را مانند شکل زیر انتخاب می­ کنیم:

atmega-first-project-with-codevision-proteus111

با این کار یک فایل با نام untitled.c ایجاد می­ شود. حال با استفاده از منوی فایل گزینه Save as  این فایل را با نام test.c در یک پوشه  به نام New ذخیره می­ نماییم.

حال از منوی File گزینه New Project یک فایل پروژه ایجاد می­ کنیم.

atmega-first-project-with-codevision-proteus1

در پنجره باز شده بعدی کدویژن از ما می­ پرسد که آیا می­خواهیم از ابزار CodeWizard استفاده کنیم یا خیر. کدویزارد یک ابزار برای تولید اتوماتیک برنامه می­ باشد که موجب آسان­تر شدن کار برنامه نویسی می­شود. فعلا ما از این ابزار استفاده نمی ­کنیم. روی گزینهNO کلیک می­ کنیم.

 

atmega-first-project-with-codevision-proteus2

در پنجره باز شده فایل پروژه خود را با نام Led.prj در همان پوشه New ذخیره می­ نماییم. با این کار یک پنجره برای پیکربندی پروژه باز می ­شود.

تا اینجای کار ما یک فایل سورس با پسوند c. و یک فایل پروژه با پسوند prj ساخته ایم. در برنامه نویسی میکروکنترلرها به زبان C همیشه باید یک یا چند فایل سورس به یک فایل پروژه متصل شوند. برای اینکه فایل test.c را به led.prj اضافه کنیم از پنجره پیکربندی پروژه (Configure Project) گزینه Add را انتخاب می­ کنیم:

atmega-first-project-with-codevision-proteus3

از پنجره باز شده فایل test.c را از محل ذخیره شده پیدا کرده و انتخاب می­نماییم. با این کار فایل test.c به پروژه اضافه می­شود:

atmega-first-project-with-codevision-proteus4

در همین پنجره از لبه C Compiler نیز نوع میکروکنترلر به کار رفته را ATmega32 و نرخ پالس ساعت را 8 مگاهرتز انتخاب می­نماییم:

atmega-first-project-with-codevision-proteus5

در نهایت روی OK کلیک می­ نماییم.

پس از انجام این مراحل قسمت Code Navigator در سمت چپ باید به صورت شکل زیر درآید که در آن فایل test.c به فایل پروژه به نام led اضافه شده باشد:

atmega-first-project-with-codevision-proteus6

در نسخه 3.12 و بالاتر از آن در نرم­افزار کدویژن ساخت فایل پروژه و سورس ساده تر شده است. به این صورت که در همان ابتدا از منوی File گزینهNew Project  را انتخاب می­کنیم و در حین ساختن فایل پروژه، از کاربر نوع میکرو مورد استفاده و نام فایل سورس پرسیده شده و این فایل به صورت خودکار به پروژه اضافه می­گردد و نیاز به طی کردن این مراحل طولانی نمی­باشد!

حال برنامه زیر را در داخل فایل test.c وارد می­ نماییم:

بعد از نوشتن این برنامه در فایل سورس نوبت به ساختن فایل با پسوند هگز(Hex) می­ رسد. در واقع این کار با کامپایل کردن پروژه مورد نظر انجام می­ شود.  با این کار کامپایلر برنامه نوشته شده به زبان C را به کدهای صفر و یک قابل فهم برای CPU تبدیل می­کند. برای این کار از منوی Project گزینه Build را مانند شکل زیر انتخاب می­ نماییم:atmega-first-project-with-codevision-proteus7

با این کار یک پنجره به صورت شکل زیر باز می­ شود:

atmega-first-project-with-codevision-proteus8

در این پنجره  اطلاعاتی در مورد برنامه نوشته شده وجود دارد. اگر برنامه خطایی داشته باشد کامپایلر به برنامه نویس اعلام می­کند. همچنین در قسمت پایین این پنجره میزان حافظه­ ای که توسط این برنامه از میکرو اشغال می ­شود نمایش داده می­ شود.

حال اگر برنامه بدون خطا کامپایل شده باشد در همان دایرکتوری که پروژه را ساخته ایم یک پوشه جدید با نام EXE ایجاد شده و در داخل آن پوشه یک فایل با نام led.hex به طور خودکار ایجاد شده است. این همان برنامه­ ای که نوشته­ ایم به زبان ماشین(صفر و یک) می ­باشد. حال اگر بخواهیم در واقعیت برنامه نوشته شده را آزمایش کنیم باید همین فایل را با استفاده از پروگرامر در داخل حافظه فلش میکرو پروگرام نماییم.

شاید این مطلب هم برایتان مفید باشد: کنترل LED RGB نواری با استفاده از میکروکنترلر

اما در اینجا می خواهیم با استفاده از نرم افزار شبیه­ ساز پروتئوس برنامه نوشته شده را شبیه سازی نماییم. برای این کار نرم افزار پروتیئوس را باز می ­نماییم:

atmega-first-project-with-codevision-proteus9

در سمت چپ روی گزینه زرد رنگ Component Mode و سپس روی گزینه P کلیک می ­نماییم تا به کتابخانه ابزارهای موجود در پروتئوس دسترسی پیدا نماییم. در قسمت 1( keyword ) با تایپ کردن تمام یا قسمتی از نام هر المان لیستی از ابزارها نمایش داده می­شود تا از بین آنها ابزار مورد نظر خود را انتخاب نماییم. در این قسمت نام ATmega32 را وارد کرده و روی اولین گزینه دابل­ کلیک می­ نماییم(2) تا میکرو به صفحه کاری ما و قسمت Devices اضافه شود(3). به همین ترتیب با تایپ کلید واژه Resistor یک مقاومت و با تایپ LED-RED یک LED به رنگ قرمز به صفحه کاری انتخاب می­نماییم و روی OK کلیک می­ نماییم.

atmega-first-project-with-codevision-proteus10

از قسمت Terminal Mode )1) گزینه Ground)2)  برای مدل سازی زمین انتخاب می­ نماییم:

atmega-first-project-with-codevision-proteus11

مدار مورد نظر را مانند شکل زیر رسم کرده و مقدار مقاومت را روی 330 اهم قرار می­ دهیم

atmega-first-project-with-codevision-proteus12

حال روی میکرو دابل ­کلیک می ­نماییم. صفحه ای به صورت زیر باز می­ شود که روی شکل پوشه مقابل Program File کلیک کرده و فایل led.hex که قبلا توسط کدویژن تولید شده را به میکرو معرفی می­ نماییم.

atmega-first-project-with-codevision-proteus13

و در نهایت روی گزینهatmega-first-project-with-codevision-proteus14 نوار وضعیت پایین پروتئوس کلیک می­نماییم تا برنامه اجرا شود. اگر تمام مراحل به درستی انجام شود مشاهده می­نماییم که LED متصل به پایه 1 به صورت متوالی خاموش و روشن می­شود. تنها نکته­ای که باقی می­ماند این است که احتمالا مدت زمان خاموش و روشن شدن LED از یک ثانیه بیشتر است و این به دلیل این است که تابع ()delay_ms معمولا مدت زمان تاخیر دقیقی را ایجاد نمی ­کند و تاخیر ایجاد شده به پالس ساعت مورد استفاده بستگی دارد. برای ایجاد تاخیرهای زمانی دقیق باید از تایمر میکرو استفاده نماییم.

 

۲۴ دیدگاه

  1. سلام من کل پروژه رو مو به مو طبق گفته شما انجام دادم اما در انتها ۳ تا ارور میده.
    Cannot find model file ‘ITFMOD.MDF’.
    Cannot find model file ‘LEDA.MDF’.
    Simulation FAILED due to netlist linker error(s).

  2. سلام میخواستم ببیم چطوری میشه با کدویژن مدباس را طراحی کرد.
    کد نویسیش و پروتئوسش رو میشه برام ایمیل کنید.
    amirafsar95@gmail.com

  3. سلام من کل فولدر را کپی کردم، اما باز هم build نمیشه

  4. سلام
    ممنون و خسته نباشید

  5. با سلام
    مهندس من یه برنامه AVR دارم. برای پروژم نیازه که بهش مسلط بشم.میخواستم ببینم شما میتونید توضیحات لازم برای برای برنامرو انجام بدید؟

  6. سلام ببخشید من توکپی کردن یه فایل pjr مشکل دارم یعنی بعد کپی دیگه build نمیشه کمکم کنید لطفا

  7. ahmadi958
    این ایدی تلگرامم اکه لازم شد

  8. با سلام
    مندس جان من یه فایل به زبان c دارم میخوام تبدیل کنم به فایل هگز ولی یه چنتا ارور داره اگه فایل رو بفرستم برات امکان داره برام اصلاح کنی ممنون میشم کمکم کنی

    • سلام. بفرستین ان شاالله که بتونم کمکتون کنم.

    • #include

      #define spi_wait() while (!(SPSR & (1<<SPIF))) {}

      #define nop() asm volatile ("nop")

      #define xlat_high() PORTB |= (1 << PB2)
      #define xlat_low() PORTB &= ~(1 << PB2)

      #define blank_high() PORTB |= (1 << PB1)
      #define blank_low() PORTB &= ~(1 << PB1)

      #define gsclk_high() PORTD |= (1 << PD5)
      #define gsclk_low() PORTD &= ~(1 << PD5)

      #define PIXELS_PER_PLANE 19
      #define PLANE_COUNT 5

      #define PIXEL_COUNT (PIXELS_PER_PLANE * PLANE_COUNT)

      static byte pixels[PIXEL_COUNT * 3];

      #define OUTPIXEL_COUNT 64

      static byte plane_trans[] = {
      ۰, ۲, ۴, ۱, ۳
      };

      static char pixel_trans[] PROGMEM = {
      ۵۰,۳۱,۳۰,۳۲,۴۸,۴۹,-۱,۲۹,۲۸,۲۷,-۱,-۱,۲۴,۲۶,۲۵,-۱,
      ۴۵,۲۲,۲۳,۴۷,۴۶,۲۱,-۱,۲۰,۱۹,۱۸,۴۳,۱۷,۱۶,۴۲,۱۵,۴۴,
      ۴۱,۱۳,۱۲,۱۴,۳۹,۴۰,-۱,۱۱,۱۰, ۹,۵۵, ۸, ۷,۵۴, ۶,۵۶,
      ۳۶, ۴, ۳, ۵,۳۸,۳۷,-۱, ۲, ۱, ۰,۵۲,۵۱,۳۵,۳۳,۳۴,۵۳
      };

      static int gamma[] PROGMEM = {

      // gamma 1.5 4095: normal brightness
      ۰,۱,۳,۵,۸,۱۱,۱۵,۱۹,۲۳,۲۷,۳۲,۳۷,۴۲,۴۷,۵۳,۵۸,
      ۶۴,۷۰,۷۷,۸۳,۹۰,۹۷,۱۰۴,۱۱۱,۱۱۸,۱۲۶,۱۳۳,۱۴۱,۱۴۹,۱۵۷,۱۶۵,۱۷۴,
      ۱۸۲,۱۹۱,۱۹۹,۲۰۸,۲۱۷,۲۲۶,۲۳۶,۲۴۵,۲۵۴,۲۶۴,۲۷۴,۲۸۴,۲۹۴,۳۰۴,۳۱۴,۳۲۴,
      ۳۳۴,۳۴۵,۳۵۶,۳۶۶,۳۷۷,۳۸۸,۳۹۹,۴۱۰,۴۲۱,۴۳۳,۴۴۴,۴۵۶,۴۶۷,۴۷۹,۴۹۱,۵۰۳,
      ۵۱۵,۵۲۷,۵۳۹,۵۵۲,۵۶۴,۵۷۶,۵۸۹,۶۰۲,۶۱۴,۶۲۷,۶۴۰,۶۵۳,۶۶۶,۶۷۹,۶۹۳,۷۰۶,
      ۷۲۰,۷۳۳,۷۴۷,۷۶۰,۷۷۴,۷۸۸,۸۰۲,۸۱۶,۸۳۰,۸۴۴,۸۵۹,۸۷۳,۸۸۷,۹۰۲,۹۱۷,۹۳۱,
      ۹۴۶,۹۶۱,۹۷۶,۹۹۱,۱۰۰۶,۱۰۲۱,۱۰۳۶,۱۰۵۱,۱۰۶۷,۱۰۸۲,۱۰۹۷,۱۱۱۳,۱۱۲۹,۱۱۴۴,۱۱۶۰,۱۱۷۶,
      ۱۱۹۲,۱۲۰۸,۱۲۲۴,۱۲۴۰,۱۲۵۶,۱۲۷۳,۱۲۸۹,۱۳۰۵,۱۳۲۲,۱۳۳۹,۱۳۵۵,۱۳۷۲,۱۳۸۹,۱۴۰۵,۱۴۲۲,۱۴۳۹,
      ۱۴۵۶,۱۴۷۳,۱۴۹۱,۱۵۰۸,۱۵۲۵,۱۵۴۲,۱۵۶۰,۱۵۷۷,۱۵۹۵,۱۶۱۳,۱۶۳۰,۱۶۴۸,۱۶۶۶,۱۶۸۴,۱۷۰۲,۱۷۲۰,
      ۱۷۳۸,۱۷۵۶,۱۷۷۴,۱۷۹۲,۱۸۱۱,۱۸۲۹,۱۸۴۷,۱۸۶۶,۱۸۸۵,۱۹۰۳,۱۹۲۲,۱۹۴۱,۱۹۵۹,۱۹۷۸,۱۹۹۷,۲۰۱۶,
      ۲۰۳۵,۲۰۵۴,۲۰۷۴,۲۰۹۳,۲۱۱۲,۲۱۳۱,۲۱۵۱,۲۱۷۰,۲۱۹۰,۲۲۰۹,۲۲۲۹,۲۲۴۹,۲۲۶۸,۲۲۸۸,۲۳۰۸,۲۳۲۸,
      ۲۳۴۸,۲۳۶۸,۲۳۸۸,۲۴۰۸,۲۴۲۹,۲۴۴۹,۲۴۶۹,۲۴۹۰,۲۵۱۰,۲۵۳۰,۲۵۵۱,۲۵۷۲,۲۵۹۲,۲۶۱۳,۲۶۳۴,۲۶۵۵,
      ۲۶۷۵,۲۶۹۶,۲۷۱۷,۲۷۳۸,۲۷۵۹,۲۷۸۱,۲۸۰۲,۲۸۲۳,۲۸۴۴,۲۸۶۶,۲۸۸۷,۲۹۰۹,۲۹۳۰,۲۹۵۲,۲۹۷۳,۲۹۹۵,
      ۳۰۱۷,۳۰۳۹,۳۰۶۰,۳۰۸۲,۳۱۰۴,۳۱۲۶,۳۱۴۸,۳۱۷۰,۳۱۹۲,۳۲۱۵,۳۲۳۷,۳۲۵۹,۳۲۸۲,۳۳۰۴,۳۳۲۶,۳۳۴۹,
      ۳۳۷۱,۳۳۹۴,۳۴۱۷,۳۴۳۹,۳۴۶۲,۳۴۸۵,۳۵۰۸,۳۵۳۱,۳۵۵۴,۳۵۷۷,۳۶۰۰,۳۶۲۳,۳۶۴۶,۳۶۶۹,۳۶۹۲,۳۷۱۶,
      ۳۷۳۹,۳۷۶۲,۳۷۸۶,۳۸۰۹,۳۸۳۳,۳۸۵۶,۳۸۸۰,۳۹۰۴,۳۹۲۸,۳۹۵۱,۳۹۷۵,۳۹۹۹,۴۰۲۳,۴۰۴۷,۴۰۷۱,۴۰۹۵,

      /*
      // gamma 1.5 400: very dim but good for photography
      ۰,۰,۰,۱,۱,۱,۱,۲,۲,۳,۳,۴,۴,۵,۵,۶,
      ۶,۷,۸,۸,۹,۹,۱۰,۱۱,۱۲,۱۲,۱۳,۱۴,۱۵,۱۵,۱۶,۱۷,
      ۱۸,۱۹,۱۹,۲۰,۲۱,۲۲,۲۳,۲۴,۲۵,۲۶,۲۷,۲۸,۲۹,۳۰,۳۱,۳۲,
      ۳۳,۳۴,۳۵,۳۶,۳۷,۳۸,۳۹,۴۰,۴۱,۴۲,۴۳,۴۵,۴۶,۴۷,۴۸,۴۹,
      ۵۰,۵۱,۵۳,۵۴,۵۵,۵۶,۵۸,۵۹,۶۰,۶۱,۶۳,۶۴,۶۵,۶۶,۶۸,۶۹,
      ۷۰,۷۲,۷۳,۷۴,۷۶,۷۷,۷۸,۸۰,۸۱,۸۲,۸۴,۸۵,۸۷,۸۸,۹۰,۹۱,
      ۹۲,۹۴,۹۵,۹۷,۹۸,۱۰۰,۱۰۱,۱۰۳,۱۰۴,۱۰۶,۱۰۷,۱۰۹,۱۱۰,۱۱۲,۱۱۳,۱۱۵,
      ۱۱۶,۱۱۸,۱۲۰,۱۲۱,۱۲۳,۱۲۴,۱۲۶,۱۲۸,۱۲۹,۱۳۱,۱۳۲,۱۳۴,۱۳۶,۱۳۷,۱۳۹,۱۴۱,
      ۱۴۲,۱۴۴,۱۴۶,۱۴۷,۱۴۹,۱۵۱,۱۵۲,۱۵۴,۱۵۶,۱۵۸,۱۵۹,۱۶۱,۱۶۳,۱۶۴,۱۶۶,۱۶۸,
      ۱۷۰,۱۷۲,۱۷۳,۱۷۵,۱۷۷,۱۷۹,۱۸۰,۱۸۲,۱۸۴,۱۸۶,۱۸۸,۱۹۰,۱۹۱,۱۹۳,۱۹۵,۱۹۷,
      ۱۹۹,۲۰۱,۲۰۳,۲۰۴,۲۰۶,۲۰۸,۲۱۰,۲۱۲,۲۱۴,۲۱۶,۲۱۸,۲۲۰,۲۲۲,۲۲۴,۲۲۵,۲۲۷,
      ۲۲۹,۲۳۱,۲۳۳,۲۳۵,۲۳۷,۲۳۹,۲۴۱,۲۴۳,۲۴۵,۲۴۷,۲۴۹,۲۵۱,۲۵۳,۲۵۵,۲۵۷,۲۵۹,
      ۲۶۱,۲۶۳,۲۶۵,۲۶۷,۲۷۰,۲۷۲,۲۷۴,۲۷۶,۲۷۸,۲۸۰,۲۸۲,۲۸۴,۲۸۶,۲۸۸,۲۹۰,۲۹۳,
      ۲۹۵,۲۹۷,۲۹۹,۳۰۱,۳۰۳,۳۰۵,۳۰۸,۳۱۰,۳۱۲,۳۱۴,۳۱۶,۳۱۸,۳۲۱,۳۲۳,۳۲۵,۳۲۷,
      ۳۲۹,۳۳۲,۳۳۴,۳۳۶,۳۳۸,۳۴۰,۳۴۳,۳۴۵,۳۴۷,۳۴۹,۳۵۲,۳۵۴,۳۵۶,۳۵۸,۳۶۱,۳۶۳,
      ۳۶۵,۳۶۸,۳۷۰,۳۷۲,۳۷۴,۳۷۷,۳۷۹,۳۸۱,۳۸۴,۳۸۶,۳۸۸,۳۹۱,۳۹۳,۳۹۵,۳۹۸,۴۰۰,
      */

      };

      // index values of up to 6 "neighbors" of each LED. this is used by "snake" and
      // "fireworks" to find adjacent LEDs
      byte nbrs[19][6] PROGMEM = {
      {۱, ۱۲, ۱۷, ۱۱, ۱۱, ۱۱},
      {۰, ۲, ۱۲, ۱۲, ۱۲, ۱۲},
      {۱, ۳, ۱۲, ۱۳, ۱۳, ۱۳},
      {۲, ۴, ۱۳, ۱۳, ۱۳, ۱۳},
      {۳, ۵, ۱۳, ۱۴, ۱۴, ۱۴},
      {۴, ۶, ۱۴, ۱۴, ۱۴, ۱۴},
      {۵, ۷, ۱۴, ۱۵, ۱۵, ۱۵},
      {۶, ۸, ۱۵, ۱۵, ۱۵, ۱۵},
      {۷, ۹, ۱۵, ۱۶, ۱۶, ۱۶},
      {۸, ۱۰, ۱۶, ۱۶, ۱۶, ۱۶},
      {۹, ۱۱, ۱۶, ۱۷, ۱۷, ۱۷},
      {۰, ۱۰, ۱۷, ۱۷, ۱۷, ۱۷},
      {۰, ۱, ۲, ۱۳, ۱۷, ۱۸},
      {۲, ۳, ۴, ۱۲, ۱۴, ۱۸},
      {۴, ۵, ۶, ۱۳, ۱۵, ۱۸},
      {۶, ۷, ۸, ۱۴, ۱۶, ۱۸},
      {۸, ۹, ۱۰, ۱۵, ۱۷, ۱۸},
      {۰, ۱۰, ۱۱, ۱۲, ۱۶, ۱۸},
      {۱۲, ۱۳, ۱۴, ۱۵, ۱۶, ۱۷}
      };

      // precomputed values used for HSV to RGB conversion
      static byte hue_f[] PROGMEM = {
      ۰, ۴, ۹, ۱۳, ۱۷, ۲۱, ۲۶, ۳۰, ۳۴, ۳۸, ۴۳, ۴۷, ۵۱, ۵۵, ۶۰, ۶۴, ۶۸, ۷۳, ۷۷, ۸۱, ۸۵, ۹۰,
      ۹۴, ۹۸, ۱۰۲, ۱۰۷, ۱۱۱, ۱۱۵, ۱۱۹, ۱۲۴, ۱۲۸, ۱۳۲, ۱۳۷, ۱۴۱, ۱۴۵, ۱۴۹, ۱۵۴, ۱۵۸, ۱۶۲,
      ۱۶۶, ۱۷۱, ۱۷۵, ۱۷۹, ۱۸۳, ۱۸۸, ۱۹۲, ۱۹۶, ۲۰۱, ۲۰۵, ۲۰۹, ۲۱۳, ۲۱۸, ۲۲۲, ۲۲۶, ۲۳۰, ۲۳۵,
      ۲۳۹, ۲۴۳, ۲۴۷, ۲۵۲,
      };

      // store an RGB value for one "pixel" (LED) in the framebuffer
      static void set_pixel_rgb(byte plane, byte idx, byte r, byte g, byte b) {
      byte *p = pixels + ((int) ((plane * PIXELS_PER_PLANE) + idx) * 3);
      *(p++) = b;
      *(p++) = g;
      *(p++) = r;
      }

      // convert a hue to an RGB value and then call set_pixel_rgb
      static void set_pixel_hue(byte plane, byte idx, int hue) {
      byte r, g, b;
      hue = hue % 360;
      if (hue <= 120) {
      r = ((120 – hue) * 255) / 120;
      g = (hue * 255) / 120;
      b = 0;
      } else if (hue <= 240) {
      r = 0;
      g = ((240 – hue) * 255) / 120;
      b = ((hue – 120) * 255) / 120;
      } else {
      r = ((hue – 240) * 255) / 120;
      g = 0;
      b = ((360 – hue) * 255) / 120;
      }
      set_pixel_rgb(plane, idx, r, g, b);

      }

      static void set_all_pixels_rgb(byte r, byte g, byte b) {
      int i;
      for (i = 0; i < (PIXEL_COUNT * 3); i += 3) {
      pixels[i] = r;
      pixels[i + 1] = g;
      pixels[i + 2] = b;
      }
      }

      static void set_all_plane_pixels_rgb(byte plane, byte r, byte g, byte b) {
      byte i;
      for (i = 0; i < PIXELS_PER_PLANE; i++) {
      set_pixel_rgb(plane, i, r, g, b);
      }
      }

      // send one plane of values to the TLC5940 drivers via SPI.
      // Called by the timer interrupt handler.
      void send_plane(byte plane) {
      byte i, pixel;
      char idx;
      int base, v1, v2;

      base = plane * PIXELS_PER_PLANE * 3;
      for (i = 0; i < OUTPIXEL_COUNT; i+= 2) {
      idx = pgm_read_byte(&(pixel_trans[i]));
      if (idx > 4;
      idx = pgm_read_byte(&(pixel_trans[i + 1]));
      if (idx < 0) {
      pixel = 0;
      } else {
      pixel = pixels[base + idx];
      }
      v2 = pgm_read_word(&(gamma[pixel]));
      spi_wait();
      SPDR = (v1 <> 8) & 0xf);
      spi_wait();
      SPDR = v2;
      }
      spi_wait();
      nop();
      nop();
      }

      void delay_some() {
      int i;
      for (i = 0; i < 4096; i++) {
      nop();
      nop();
      nop();
      }
      }

      void delay_count(int count) {
      int c;
      for (c = 0; c < count; c++) {
      delay_some();
      }
      }

      void setup() {
      DDRD = 0xff; // PORTD output
      PORTD = 0; // All PD pins low

      DDRB = 0xff;
      PORTB = 0;

      DDRC |= 0x1f;
      PORTC &= ~0x1f;

      SPCR = (1 << SPE) | (1 << MSTR);
      SPSR |= (0 << SPI2X);
      SPDR = 0;
      spi_wait();

      // timer0 generates the grayscale clock signal on OC0B (PD5) at 2MHz
      TCCR0B = 0;
      TIMSK0 = 0;
      TCNT0 = 0;
      TCCR0A = (1 << COM0B0) | (1 << WGM01);
      TCCR0B = 0;
      OCR0A = 7;
      TCCR0B |= (1 << CS00);

      // timer1 triggers the multiplexing interrupt at 500Hz
      TCCR1B = 0;
      TIMSK1 = 0;
      TCNT1 = 0;
      TCCR1A = 0;
      TCCR1B = (1 << WGM12);
      OCR1A = 31;
      TIMSK1 |= (1 << OCIE1A);
      TCCR1B |= (1 << CS12) | (1 << CS10);

      // timer2 drives the charge pump on OC2B (PD3) at 150KHz. This generates +10V needed to switch
      // the 5 big mosfets.
      TCCR2B = 0; // stop timer
      TIMSK2 = 0; // cancel interrupts
      TCNT2 = 0; // reset timer to 0
      TCCR2A = (1 << COM2B0) | (1 << WGM21);
      TCCR2B = 0;
      OCR2A = 52; // TOP = 52 (note that this has to be set AFTER selecting CTC mode)
      TCCR2B |= (1 << CS20); // start timer, full speed

      set_all_pixels_rgb(0, 0, 0);
      srand(123456);
      }

      static int current_plane = 0;

      ISR(TIMER1_COMPA_vect) {
      // turn off all mosfets
      PORTC &= ~0x1f;
      // wait for any pending SPI data to finish transferring
      spi_wait();
      // stop the grayscale clock
      TCCR0B = 0;
      gsclk_low();
      // reset the TLC5940's internal counter by toggling BLANK
      blank_high();
      xlat_high();
      nop();
      nop();
      xlat_low();
      blank_low();
      // activate the mosfet for the next plane
      PORTC |= (1 << plane_trans[current_plane]);
      // restart the grayscale clock
      TCCR0B |= (1 << CS00);
      // send the next plane's worth of data to the TLC5940s via SPI
      current_plane = (current_plane + 1) % PLANE_COUNT;
      send_plane(current_plane);
      }

      // the functions below are different animations that are run by loop()

      void phase(int count, byte angle) {
      byte plane, idx;
      int hue, h, c;

      for (c = 0; c < count; c++) {
      for (hue = 0; hue < 360; hue++) {
      h = 0;
      for (plane = 0; plane < PLANE_COUNT; plane++) {
      for (idx = 0; idx < PIXELS_PER_PLANE; idx++) {
      set_pixel_hue(plane, idx, hue + h);
      h += angle;
      }
      }
      }
      }
      }

      void solid_hue(int count, int hue) {
      int c;
      byte idx, plane;
      byte r, g, b;

      hue = hue % 360;
      if (hue <= 120) {
      r = ((120 – hue) * 255) / 120;
      g = (hue * 255) / 120;
      b = 0;
      } else if (hue <= 240) {
      r = 0;
      g = ((240 – hue) * 255) / 120;
      b = ((hue – 120) * 255) / 120;
      } else {
      r = ((hue – 240) * 255) / 120;
      g = 0;
      b = ((360 – hue) * 255) / 120;
      }
      for (c = 0; c < 255; c++) {
      for (plane = 0; plane < PLANE_COUNT; plane++) {
      for (idx = 0; idx < PIXELS_PER_PLANE; idx++) {
      set_pixel_rgb(plane, idx, r * c / 255, g * c / 255, b * c / 255);
      }
      }
      delay_count(5);
      }
      for (c = 0; c < count; c++) {
      delay_some();
      }
      }

      void solid_white(int count) {
      int c;
      byte idx, plane;

      for (c = 0; c < 255; c++) {
      for (plane = 0; plane < PLANE_COUNT; plane++) {
      for (idx = 0; idx < PIXELS_PER_PLANE; idx++) {
      set_pixel_rgb(plane, idx, c, c, c);
      }
      }
      delay_count(5);
      }
      for (c = 0; c < count; c++) {
      delay_some();
      }
      }

      void scan_hue(int count, int hue) {
      int c;
      byte idx;
      char plane;
      set_all_pixels_rgb(0, 0, 0);
      for (plane = 0; plane < PLANE_COUNT; plane++) {
      for (idx = 0; idx < 12; idx++) {
      set_pixel_hue(plane, idx, hue);
      for (c = 0; c = 0; plane–) {
      for (idx = 12; idx < 18; idx++) {
      set_pixel_hue(plane, idx, hue);
      for (c = 0; c < count; c++) {
      delay_some();
      }
      set_pixel_rgb(plane, idx, 0, 0, 0);
      }
      }
      for (plane = 0; plane < PLANE_COUNT; plane++) {
      set_pixel_hue(plane, 18, hue);
      for (c = 0; c < count; c++) {
      delay_some();
      }
      set_pixel_rgb(plane, 18, 0, 0, 0);
      }
      }

      void rain(int count) {
      byte idx, d;
      int c;
      byte drops[19];
      int hues[19];
      for (idx = 0; idx < 19; idx++) {
      drops[idx] = rand() % 21;
      hues[idx] = rand() % 360;
      }
      for (c = 0; c < 200; c++) {
      for (idx = 0; idx < 19; idx++) {
      d = drops[idx];
      if (d < 5) {
      set_pixel_hue(4 – d, idx, hues[idx]);
      }
      }
      delay_count(count);
      for (idx = 0; idx < 19; idx++) {
      d = drops[idx];
      if (d < 5) {
      set_pixel_rgb(4 – d, idx, 0, 0, 0);
      }
      if (d == 0) {
      d = (rand() % 15) + 5;
      hues[idx] = rand() % 360;
      } else {
      d–;
      }
      drops[idx] = d;
      }
      }
      }

      void sparkle(int count) {
      byte plane, idx;
      int c, j, hue;
      for (c = 0; c < 400; c++) {
      for (plane = 0; plane < 5; plane++) {
      for (idx = 0; idx < 19; idx++) {
      if ((rand() % 11) == 0) {
      set_pixel_hue(plane, idx, rand());
      } else {
      set_pixel_rgb(plane, idx, 0, 0, 0);
      }
      }
      }
      delay_count(count);
      }
      }

      void firework() {
      byte idx, i, j, p, dly;
      char plane;
      int hue;
      byte rings[10][19];

      for (p = 0; p < 10; p++) {
      for (i = 0; i < 19; i++) {
      rings[p][i] = 0;
      }
      }

      idx = 12 + (rand() % 7);

      rings[0][idx] = 1;
      for (p = 1; p < 10; p++) {
      for (i = 0; i < 19; i++) {
      if (rings[p – 1][i] != 0) {
      for (j = 0; j < 6; j++) {
      rings[p][pgm_read_byte(&(nbrs[i][j]))] = 1;
      }
      }
      }
      }
      for (p = 0; p < 9; p++) {
      for (i = 0; i < 19; i++) {
      if (rings[p][i] != 0) {
      for (j = p + 1; j < 10; j++) {
      rings[j][i] = 0;
      }
      }
      }
      }

      plane = (rand() % 3) + 2;
      dly = 30;
      for (p = 0; p <= plane; p++) {
      set_pixel_rgb(p, idx, 255, 255, 255);
      delay_count(dly);
      dly += 20;
      set_pixel_rgb(p, idx, 0, 0, 0);
      }
      dly = 80;
      hue = rand() % 360;
      for (j = 0; j < 10; j++) {
      for (p = 0; p <= j; p++) {
      for (i = 0; i < 19; i++) {
      if (rings[j – p][i]) {
      if ((plane + p) = 0) {
      set_pixel_hue(plane – p, i, hue);
      }
      }
      }
      }
      delay_count(dly);
      dly+= 10;
      set_all_pixels_rgb(0, 0, 0);
      }
      delay_count(20);
      set_all_pixels_rgb(0, 0, 0);
      }

      void fireworks() {
      int i;
      for (i = 0; i < 10; i++) {
      firework();
      }
      }

      void snake() {
      byte idx, plane, i, p;
      int hue, c;
      byte snk[10];

      hue = rand() % 360;
      idx = rand() % 19;
      plane = rand() % 5;

      for (c = 0; c < 10; c++) {
      snk[c] = 255;
      }

      for (c = 0; c > 3, 0, 0, 0);
      }
      snk[c % 10] = plane + (idx << 3);
      if (c < 490) {
      set_pixel_hue(plane, idx, hue);
      }
      delay_count(20);
      }
      }

      void suck(int count) {
      char plane, idx;
      for (plane = 0; plane = 0; idx–) {
      set_pixel_rgb(plane, idx, 0, 0, 0);
      }
      delay_count(count);
      }
      }

      void wisp(int count) {
      char plane, idx;
      for (plane = 0; plane = 0; idx–) {
      set_pixel_rgb(plane, idx, 0, 0, 0);
      delay_count(count);
      }
      }
      }

      void stomp(int count) {
      char plane, idx;
      for (plane = 4; plane >= 0; plane–) {
      for (idx = 18; idx >= 0; idx–) {
      set_pixel_rgb(plane, idx, 0, 0, 0);
      }
      delay_count(count);
      }
      }

      void curl(int count) {
      char plane, idx;
      for (plane = 4; plane >= 0; plane–) {
      for (idx = 18; idx >= 0; idx–) {
      set_pixel_rgb(plane, idx, 0, 0, 0);
      delay_count(count);
      }
      }
      }

      void float_hue(int count, int angle) {
      byte plane, idx;
      int hue, h, c;

      for (c = 0; c < count; c++) {
      for (hue = 0; hue < 360; hue++) {
      h = 0;
      for (plane = 0; plane < PLANE_COUNT; plane++) {
      for (idx = 0; idx < PIXELS_PER_PLANE; idx++) {
      set_pixel_hue(plane, idx, hue + h);
      }
      h += angle;
      }
      }
      }
      }

      void set_column_hue(byte idx, int hue) {
      set_pixel_hue(0, idx, hue);
      set_pixel_hue(1, idx, hue);
      set_pixel_hue(2, idx, hue);
      set_pixel_hue(3, idx, hue);
      set_pixel_hue(4, idx, hue);
      }

      void spin_hue(int count, int angle) {
      byte idx;
      int hue, h, c;

      for (c = 0; c < count; c++) {
      for (hue = 0; hue < 360; hue++) {
      h = 0;
      for (idx = 0; idx < 12; idx++) {
      set_column_hue(idx, hue + h);
      h += angle;
      }
      h = angle;
      for (idx = 12; idx < 18; idx++) {
      set_column_hue(idx, hue + h);
      h += angle * 2;
      }
      set_column_hue(idx, hue);
      }
      }
      }

      void ring_hue(int count, int angle) {
      byte idx;
      int hue, c, h;

      for (c = 0; c < count; c++) {
      for (hue = 0; hue < 360; hue++) {
      h = hue;
      for (idx = 0; idx < 12; idx++) {
      set_column_hue(idx, h);
      }
      h = hue + angle;
      for (idx = 12; idx < 18; idx++) {
      set_column_hue(idx, h);
      }
      h = hue + angle + angle;
      set_column_hue(18, h);
      }
      }
      }
      void loop() {
      int h;
      for (h = 0; h < 360; h += 120) {
      scan_hue(10, h);
      }
      for (h = 0; h < 360; h += 120) {
      solid_hue(1000, h);
      stomp(100);
      }
      solid_white(1000);
      rain(25);
      float_hue(10, 43);
      suck(100);
      snake();
      spin_hue(10, 43);
      wisp(10);
      fireworks();
      ring_hue(10, 45);
      sparkle(5);
      phase(10, 103);
      }

  9. با سلام …. ممنون از توضیحات کاملی که دادید خیلی خوب بودن …. من با اینکه همه کارها رو انجام دادم اما LED هام روشن نمیشن ! منم سر درنمیارم که باید چیکار کنم ، نقطه ی آبی میذاره جای LED ها و مقاومت ها و پورت …. ینی چی ؟!

  10. بابات مطالب ممنونم.خیل وقت بود با avr کار نکرده بودم.و به کل فراموش کرده بودم

  11. با سلام و درود فراوان
    در کد نوشته شده در جاییکه حلقه while نوشته می شود باید آکولاد باز شود. در غیر اینصورت کد خطا می دهد

  12. سلام چرا با این ارور در پروتیوس مواجه میشم؟
    mixed model AVR2.DLL failed to authorize – Missing or invalid Customer Key.. [U1]

    • با سلام. تا به حال به این ارور برنخوردم. ولی ظاهرش که میگه سریال نامبر نرم افزار درست نیست. احتمالا درست کرک نشده نرم فزار. نرم افزار رو طبق راهنمای سایتی که دانلود کردین نصب کنین.

  13. عالی بود
    سپاس

  14. سلام و تشکر از مطلبتون.
    ببخشید من یک مشکلی داشتم و اون این هست که تابع delay داخل کدم عمل نمیکنه و led ایی که گذاشتم، روشن باقی میمونن.
    مشکل چی هست

    • سلام، خواهش میکنم. از چه میکرویی استفاده میکنید؟ فرکانس رو چند تنظیم کردید؟ اگه میتونید کدتون رو قرار بدین.

پاسخ دهید

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