راهنمای جامع روش‌ها، فیوزبیت‌ها، خطاهای رایج و عیب‌یابی حرفه‌ای

فهرست مطالب

  • برنامه‌دهی ATmega چیست و چه روش‌هایی دارد؟
  • پیش‌نیازها و ابزار لازم (USBasp، AVRISP mkII، Atmel-ICE، avrdude، Arduino IDE، Microchip Studio)
  • روش‌های برنامه‌دهی: ISP (SPI)، Bootloader (UART)، JTAG، HVPP/HVSP
  • اتصال صحیح ۶ پین/۱۰ پین ISP و نقشه پایه‌ها در ATmega16/32/8
  • فیوزبیت‌ها در AVR: CKSEL، SUT، CKDIV8، BODLEVEL، SPIEN، RSTDISBL، JTAGEN، EESAVE، WDTON
  • آموزش گام‌به‌گام برنامه‌ریزی با avrdude (دستورات کامل + نکات حرفه‌ای)
  • برنامه‌دهی با Arduino IDE (هسته‌های MegaCore/MiniCore) و سوزاندن بوت‌لودر
  • برنامه‌دهی و دیباگ با Microchip Studio/Atmel Studio و Atmel-ICE
  • خطاهای رایج و عیب‌یابی: rc=-1، signature 0x000000/0xFFFFFF، verification error، baud mismatch، clock dead، JTAG اشغال پورت‌ها، Brown-Out
  • چک‌لیست سخت‌افزار حرفه‌ای: تغذیه، نویز، کلاک، AVCC/AREF، ریست، خازن‌های کنارگذر
  • نمونه‌کدهای کاربردی (چشمک‌زن، UART، ADC، PWM)
  • سوالات متداول (FAQ)
  • کلمات کلیدی پیشنهادی سئو + متا توضیح پیشنهادی

برنامه‌دهی ATmega چیست و چه روش‌هایی دارد؟

برنامه‌دهی میکروکنترلرهای ATmega یعنی انتقال فایل باینری (HEX) به حافظه فلش آی‌سی، تنظیم فیوزبیت‌ها و در صورت نیاز فلش/EEPROM. روش‌های متداول:

  1. ISP (SPI Programming): مستقیم از طریق پایه‌های MOSI/MISO/SCK/RESET/VCC/GND. سریع، امن و استاندارد.
  2. Bootloader (UART): ابتدا بوت‌لودر روی آی‌سی سوزانده می‌شود، سپس از طریق پورت سریال با سرعت انتخابی برنامه منتقل می‌گردد (مثلاً Optiboot).
  3. JTAG: برای مدل‌های دارای JTAG (مثل ATmega16/32/128). مزیت: دیباگ درجا و برنامه‌دهی.
  4. HVPP/HVSP (High-Voltage Programming): زمانی که با فیوزبیت اشتباه آی‌سی «قفل» شده؛ تنها راه نجات قطعی.

پیش‌نیازها و ابزار لازم

  • پروگرامر:
    • USBasp (اقتصادی و محبوب)، USBtinyISP، AVRISP mkII، Atmel-ICE (حرفه‌ای: ISP/JTAG/debugWIRE).
  • نرم‌افزار:
    • avrdude (همه‌فن‌حریف خط فرمان)، Microchip Studio (محیط توسعه و دیباگ)، Arduino IDE (ساده و سریع).
  • تجهیزات: سیم کوتاه و باکیفیت برای ISP، بردبورد/PCB، منبع تغذیه ۵V یا ۳.۳V مطابق دیتاشیت، خازن‌های کنارگذر 100nF نزدیک هر پایه VCC/AVCC، پول‌آپ 10k روی RESET، کریستال و خازن‌های Load در صورت استفاده از کلاک خارجی.

روش‌های برنامه‌دهی (به تفکیک)

1) ISP (SPI) — استاندارد و سریع

پایه‌ها (ATmega16/32/8/32A و مشابه)

  • MOSI → PB5 (برای M16/32)، MISO → PB6، SCK → PB7 (در 40-پین‌ها)
  • RESET، VCC، GND مشترک
  • هدر ۶ پین یا ۱۰ پین پروگرامر → نقشه را دقیق مطابق دیتاشیت و پروگرامر ست کنید.
    مزایا: نیازی به بوت‌لودر ندارد، همه حافظه و فیوزها در دسترس.
    نکته طلایی: اگر هدف روی کلاک داخلی کند است، سرعت کلاک پروگرامر را کم کنید (USBasp: جامپر SLOW یا پارامتر -B در avrdude).

2) Bootloader (UART) — مناسب توسعه سریع

  • ابتدا با ISP، بوت‌لودر (مثلاً Optiboot) را سوزانده و فیوزها را مطابق کلاک انتخابی تنظیم کنید.
  • از این پس از طریق UART/USB-Serial با baud مشخص (مثلاً 115200) برنامه بریزید.
    مزایا: سریع برای چرخه‌های توسعه، بدون نیاز به اتصال مداوم ISP.
    ریسک: اگر فیوز یا کلاک تغییر کند و با baud بوت‌لودر نخواند، ارتباط از دست می‌رود → باید دوباره با ISP احیا شود.

3) JTAG — برنامه‌دهی + دیباگ

  • در مدل‌های JTAG-دار (M16/M32/M128/…) فعال است (فیوز JTAGEN).
  • با Atmel-ICE می‌توانید Breakpoint، Step-Into، Watch و… داشته باشید.
    هشدار: وقتی JTAG فعال است، پین‌های PC2..PC5 در ATmega16/32 اشغال می‌شوند. اگر به این پورت‌ها نیاز دارید، JTAGEN را خاموش کنید.

4) HVPP/HVSP — نجات‌دهنده آی‌سی قفل‌شده

  • اگر RSTDISBL را اشتباه فعال کرده‌اید یا SPIEN را خاموش کرده‌اید، تنها راه برنامه‌دهی ولتاژبالا است.
  • HVPP (Parallel) مخصوص پکیج‌های بزرگ مثل ATmega16/32؛ HVSP برای برخی پکیج‌های کوچکتر.
  • جعبه‌های بازیابی آماده یا مدار DIY برای این کار وجود دارد.

اتصال صحیح ۶/۱۰ پین ISP

  • کلید طلایی: جهت کانکتور را با علامت Pin-1 روی برد و روی فیش پروگرامر تطبیق دهید.
  • زمین (GND) را اول وصل کنید؛ طول سیم‌ها کوتاه باشد (<20cm)؛ مسیرها از منابع نویزی دور باشند.
  • اگر روی برد قطعاتی به خطوط MOSI/MISO/SCK آویزان‌اند (مثلاً ترانسیور SPI)، هنگام پروگرام‌کردن جدا یا ایزوله کنید (مقاومت سری 100Ω کمک می‌کند).

فیوزبیت‌ها در AVR (مهم‌ترین بخش برای «مگاها»)

فیوزبیت‌ها رفتار پایه‌ای آی‌سی را تعیین می‌کنند:

  • CKSEL[3:0] + SUT: منبع و راه‌اندازی کلاک (RC داخلی 1/8MHz/…، کریستال، ساعت خارجی).
  • CKDIV8: تقسیم فرکانس سیستم ×۸ (پیش‌فرض برخی مدل‌ها روشن است).
  • BODLEVEL: فعال‌سازی Brown-Out (سطح قطع ولتاژ برای جلوگیری از هنگ).
  • SPIEN: فعال بودن رابط ISP (اگر خاموش شود، فقط HV می‌تواند نجات دهد).
  • RSTDISBL: غیرفعال‌سازی پایه RESET (خطرناک برای مبتدی‌ها؛ فقط وقتی لازم است).
  • JTAGEN: فعال/غیرفعال‌سازی رابط JTAG (در مگاهای JTAG-دار).
  • EESAVE: حفظ EEPROM هنگام پاک‌کردن فلش.
  • WDTON: وادار کردن Watchdog همیشه روشن.

توصیه‌های ایمن

  • برای شروع: کلاک داخلی 8MHz + CKDIV8 خاموش (اگر نیاز به سرعت دارید).
  • SPIEN روشن بماند.
  • اگر پورت‌های C لازمند و JTAG دارید: JTAGEN خاموش.
  • برای تجهیزات باتری‌محور: BODLEVEL را منطقی تنظیم کنید (مثلاً 2.7V برای 5V سیستم، 1.8V برای 3.3V).
  • EESAVE را فقط وقتی داده‌های EEPROM حیاتی‌ست روشن کنید.

آموزش گام‌به‌گام با avrdude (USBasp/AVRISP mkII)

خواندن شناسه و فیوزها

# نمونه برای ATmega32 با USBasp
avrdude -c usbasp -p m32 -v
avrdude -c usbasp -p m32 -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h

  • اگر signature خوانده شد (مثلاً 0x1E 0x95 0x02 برای m32)، ارتباط OK است.

نوشتن برنامه (HEX) و بررسی

avrdude -c usbasp -p m32 -U flash:w:project.hex:i -U verify

تنظیم فیوز نمونه (با احتیاط!)


مثال فرضی: RC داخلی 8MHz، بدون تقسیم بر 8، JTAG خاموش، BOD = 2.7V


# هشدار: مقادیر نمونه‌اند؛ قبل از اجرا با دیتاشیت مدل خود تطبیق دهید
avrdude -c usbasp -p m32 -U lfuse:w:0xE4:m -U hfuse:w:0xD9:m

  • حتماً قبل از نوشتن فیوزها، مقادیر فعلی را ذخیره کنید و با تنظیمات دلخواه روی کاغذ/فایل یادداشت کنید.

وقتی ارتباط کند است یا نمی‌گیرد

  • با USBasp: جامپر SLOW را فعال کنید یا از پارامتر -B 10 استفاده کنید:

avrdude -c usbasp -p m32 -B 10 -v

  • اگر کلاک هدف بسیار کند/خارجی است، سرعت SCK را پایین بیاورید.

برنامه‌دهی با Arduino IDE (هسته‌های MegaCore/MiniCore)

برای استفاده از ATmega16/32/128/1284 و… در Arduino IDE، هسته‌های جامعه کاربری (مثل MegaCore از MCUdude) را از Boards Manager نصب کنید. برای سری ATmega48/88/168/328 از MiniCore استفاده می‌شود.

مراحل کلی

  1. نصب هسته (Boards Manager → جستجوی MegaCore/MiniCore → Install).
  2. انتخاب برد: ATmega32 یا ATmega16 و…
  3. انتخاب Clock (مثلاً Internal 8MHz، External 16MHz)، BOD، Bootloader (Optiboot یا بدون).
  4. انتخاب Programmer: USBasp یا AVRISP mkII.
  5. Burn Bootloader (تا فیوزها و بوت‌لودر ست شوند).
  6. آپلود Sketch از طریق Upload Using Programmer (ISP) یا از طریق Port اگر بوت‌لودر سریال دارید.

نکته کلیدی سئو/فنی: mismatch بین Clock انتخابی و Bootloader baudrate یکی از دلایل رایج خطاست (در بخش خطاها می‌آید).

برنامه‌دهی و دیباگ با Microchip Studio (Atmel Studio)

  • پروژه GCC AVR بسازید، آی‌سی هدف (مثلاً ATmega32) را انتخاب کنید.
  • پروگرامر/دیباگر (Atmel-ICE/AVRISP mkII/..) را از Device Programming انتخاب کنید.
  • از همان‌جا Read Signature، Read/Write Fuses و Program Flash انجام دهید.
  • اگر سخت‌افزار اجازه دهد، JTAG/DebugWIRE برای دیباگ خط‌به‌خط فوق‌العاده است.

خطاهای رایج و عیب‌یابی حرفه‌ای

1) initialization failed, rc=-1 یا programmer not responding

دلایل محتمل:

  • سیم‌بندی اشتباه ISP (جابه‌جایی MOSI/MISO/SCK/RESET).
  • نبود تغذیه یا زمین مشترک.
  • سرعت زیاد پروگرامر نسبت به کلاک هدف (کلاک داخلی کند).
    راه‌حل‌ها:
  • مسیرها را با مولتی‌متر تست کنید؛ طول سیم را کوتاه کنید.
  • گزینه -B 10 (یا بالاتر) در avrdude؛ جامپر SLOW در USBasp.
  • بررسی پول‌آپ 10k روی RESET و وصل بودن AVCC (برای پورت A و ADC ضروری است).

2) امضای دستگاه 0x000000 یا 0xFFFFFF یا signature غلط

دلایل:

  • قطع بودن یکی از خطوط؛ جهت کانکتور اشتباه؛ تغذیه ناکافی؛ نویز.
  • کلاک مرده: فیوز روی کریستال خارجی است اما کریستال وصل نیست.
    راه‌حل:
  • سیم‌کشی و تغذیه را اصلاح کنید.
  • اگر کلاک مرده است: یک سیگنال 1–8MHz به پایه XTAL1 تزریق کنید (از اسیلاتور/میکرو دیگر) تا موقتاً زنده شود، سپس فیوز را به RC داخلی برگردانید.

3) verification error, first mismatch at byte ...

دلایل:

  • نویز روی تغذیه یا طول سیم بالا؛ سرعت پروگرام زیاد.
  • فیوز BOD نامناسب باعث ریست حین پروگرام.
    راه‌حل:
  • خازن بالک 10–47µF نزدیک آی‌سی؛ 100nF نزدیک هر VCC/AVCC.
  • کاهش سرعت پروگرام (-B 10/20).
  • تنظیم BODLEVEL متناسب با ولتاژ واقعی سیستم.

4) stk500_getsync() not in sync (در Arduino IDE)

دلایل:

  • بوت‌لودر با کلاک/baud ناهماهنگ؛ پورت/درایور اشتباه.
    راه‌حل:
  • مجدد Burn Bootloader با انتخاب Clock صحیح.
  • انتخاب پورت درست و سرعت صحیح سریال.

5) پورت‌های C کار نمی‌کنند (ATmega16/32)

علت: JTAGEN روشن است و PC2..PC5 را اشغال کرده.
راه‌حل: خاموش‌کردن JTAGEN در فیوزها (ISP لازم است)، سپس تست مجدد.

6) آی‌سی کاملاً قفل: ISP جواب نمی‌دهد

دلایل:

  • RSTDISBL فعال یا SPIEN خاموش شده.
    راه‌حل قطعی: HVPP/HVSP. پروگرامر ولتاژبالا لازم است.

7) Brown-Out Resets

نشانه: ریست‌های تصادفی، به‌خصوص هنگام فعال‌شدن بار (موتور/رله).
راه‌حل: BODLEVEL را مطابق ولتاژ تغذیه تنظیم کنید یا تغذیه را بهبود دهید (رگولاتور مناسب، خازن‌های کافی، دیود هرزگرد برای بارهای القایی).

چک‌لیست سخت‌افزار حرفه‌ای (برای موفقیت ۹۹٪)

  • AVCC را حتماً تغذیه کنید (برای پورت A/ADC حیاتی است).
  • AREF را با 100nF به زمین کوپل کنید (اگر از Vref داخلی/AVCC استفاده می‌کنید).
  • کنار هر پایه VCC/AVCC یک 100nF بچسبانید؛ یک 10–47µF نزدیک آی‌سی.
  • RESET با 10k به VCC؛ در محیط‌های نویزی یک 100nF به GND هم کمک می‌کند.
  • اگر کریستال می‌گذارید، خازن‌های Load مطابق دیتاشیت و مسیر بسیار کوتاه.
  • خطوط MOSI/MISO/SCK کوتاه، موازی توان/رله/موتور عبور نکنند.
  • زمین آنالوگ و دیجیتال خوب ستاره‌ای یا پلن مناسب؛ دیود هرزگرد روی بوبین‌ها.

نمونه‌کدها

1) چشمک‌زن ساده (ATmega16/32، کلاک داخلی 8MHz)

#include <avr/io.h>
#include <util/delay.h>

int main(void) {     DDRB |= (1<<PB0);        // PB0 خروجی
    while (1) {         PORTB ^= (1<<PB0);   // تغییر وضعیت LED
        _delay_ms(500);     } }

2) UART 9600bps (فرض: 8MHz داخلی، CKDIV8 خاموش)

#include <avr/io.h>

void uart_init(void){     // Baud = 9600 ، فرمول: UBRR = F_CPU/16/BAUD - 1
    UBRRH = 0;     UBRRL = 51;          // برای 8MHz و 9600
    UCSRB = (1<<TXEN);   // فقط ارسال
    UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); // 8N1
}
void uart_putc(char c){ while(!(UCSRA & (1<<UDRE))); UDR = c; }
void uart_print(const char*s){ while(*s) uart_putc(*s++); }
int main(void){     uart_init();     while(1){ uart_print("Hello ATmega!\r\n"); } }

3) ADC خواندن پتانسیومتر از PA0 (مرجع AVCC)

#include <avr/io.h>
#include <util/delay.h>

uint16_t adc_read(uint8_t ch){     ADMUX  = (1<<REFS0) | (ch & 0x07); // AVCC ref
    ADCSRA = (1<<ADEN) | (1<<ADPS2)|(1<<ADPS1); // prescaler 64
    ADCSRA |= (1<<ADSC);     while(ADCSRA & (1<<ADSC));     return ADC; }
int main(void){     uint16_t v;     while(1){         v = adc_read(0); // PA0
        _delay_ms(100);     } }

4) PWM سریع روی OC1A (کنترل موتور/LED)

#include <avr/io.h>

int main(void){     DDRD |= (1<<PD5);                 // OC1A خروجی
    TCCR1A = (1<<COM1A1) | (1<<WGM10); // Fast PWM 8-bit
    TCCR1B = (1<<WGM12) | (1<<CS11);   // prescaler 8
    OCR1A = 128;                        // 50% duty
    while(1){} }

سوالات متداول (FAQ)

فرق ISP و Bootloader چیست؟
ISP مستقیم به فلش/فیوز می‌نویسد و وابسته به بوت‌لودر نیست. بوت‌لودر یک برنامه کوچک در فلش است که از طریق سریال آپلود می‌کند—سریع برای توسعه، ولی وابسته به تنظیم درست کلاک/baud.

وقتی فیوزها را اشتباه زدم چه کنم؟
اگر SPIEN خاموش یا RSTDISBL روشن شده، تنها HVPP/HVSP نجات می‌دهد. اگر فقط کلاک اشتباه شده، کلاک موقت به XTAL1 تزریق کنید و فیوز را برگردانید.

چرا پورت‌های C کار نمی‌کنند؟
در ATmega16/32 احتمالاً JTAGEN روشن است. خاموش کنید.

Brown-Out لازم است؟
برای پایداری در برق ناپایدار یا باتری، BOD بسیار مفید است؛ ولتاژ مناسب را انتخاب کنید تا ریست‌های تصادفی نگیرید.

بهترین پروگرامر برای شروع؟
USBasp اقتصادی و قابل‌اعتماد است. برای دیباگ سطح‌حرفه‌ای، Atmel-ICE.

جمع‌بندی

  • با ISP شروع کنید؛ فیوزها را با دقت تنظیم و یادداشت کنید.
  • برای توسعه سریع از Bootloader بهره ببرید، اما ISP را کنار نگذارید.
  • اگر خطا دیدید، طبق عیب‌یابی بخش خطاها جلو بروید: تغذیه/سیم‌کشی، سرعت پروگرام، کلاک، فیوز، سپس سراغ HV بروید.
  • چک‌لیست سخت‌افزار را رعایت کنید تا ۹۰٪ مشکلات هرگز رخ ندهند.