در پوشه اصلی پروژه سه فایل main.c برای برنامه اصلی، فایل global.c برای تعریف متغیرهای عمومی و برخی از ماکرو ها و فایل WINAVR_CAMP.h نیز که برخی دیگر از ثوابت در آن تعریف شده است قرار گرفته است.
کتابخانه های این پروژه برای کامپایلر CodevisionAVR در دو پوشه Driver و net قرار گرفته اند. در پوشه درایور فایل های مربوط به پیاده سازی تراشه ENC28J60 ، طراحی منوها، پیاده سازی پروتکل اترنت و راه اندازی بخش ADC میکروکنترلر قرار گرفته است. در پوشه net فایل های مربوط به پیاده سازی پروتکل های لایه های بالاتر قرار گرفته است.
در بخش های بعدی به توضیح در مورد هریک از این کتابخانه ها و توابع موجود در آنها می پردازیم.
فایل main.c :
در ابتدا، آدرس MAC برد در avr_mac.byte تعیین شده است. سپس آدرس IP میکروکنترلر و سرور از تراشه EEPROM خوانده شده و در avr_ip.byte مربوط به آدرس IP میکروکنترلر AVR و server_ip.byte مربوط به آدرس IP سرور ریخته می شود. (ذخیره
سازی آدرس های IP در حافظه EEPROM در فایل global صورت گرفته است(. در بخش بعدی تنظیمات فعال سازی مقاومت های pull-up انجام شده است.
در بخش setup clock for timer1 تنظیمات رجیسترهای تایمر شماره 1 میکروکنترلر انجام شده است. سه تابع adc_init ، lcd_init و menu_init به ترتیب وظیفه تنظیم بخش ADC میکروکنترلر، تنظیم LCD کاراکتری با 16 ستون و تنظیم اولیه منوهای برنامه که بر روی
LCD کاراکتری نشان داده می شود را به عهده دارند.
در بخش بعدی تنظیمات مربوط به پایه های LED انجام شده است.
تابع enc28j60_init() برای تنظیمات و پیکربندی اولیه تراشه ENC28J60 فراخوانی می شود.
در حلقه while(1) یا حلقه دائمی برنامه :
برای زمان بندی سیستم، از سر ریز تایمر 1 در هر 4 میلی ثانیه استفاده می شود.
توسط تابع adc_read_temp مقدار دمای محیط توسط سنسور متصل شده به ADC میکروکنترلر اندازه گیری می شود.
توسط تابع server_process به درخواست های پروتکل های ARP ، ICMP و HTTP پاسخ داده می شود.
توسط تابع client_process (که به صورت پیشفرض غیر فعال شده است(، دمای اندازه گیری شده توسط واحد ADC که توسط تابع adc_read_temp خوانده شده است، از طریق پروتکل HTTP به سمت وب سرور ارسال می شود.
تابع menu_process وظیفه تنظیم منوهای LCD مطابق دستورات کاربر و همچنین وظیفه تنظیم آدرس IP و شمارش تایمر را به عهده دارد.
تابع standby_display وظیفه نمایش دما، آدرس IP میکروکنترلر و سرور و شمارش تایمر را به عهده دارند.
تابع client_process
این تابع برای ارسال دمای اندازه گیری شده به سمت وب سرور مورد استفاده قرار می گیرد و به صورت پیش فرض در برنامه استفاده نشده است و غیر فعال است. برای استفاده از این تابع، باید وب سرور و کدهای آن را قبل از استفاده از این تابع پیاده سازی کنید. )به عنوان مثال می توانید از وب سرور Apache و کدهای PHP استفاده کنید(.
تابع Server_process
از این تابع برای پیاده سازی پروتکل های مورد استفاده در برنامه استفاده می شود. در بخش اول این تابع، متغیر client_mac از نوع ساختار MAC_ADDR )تعریف شده در فایلstruct به صورت شش بایتی(، متغیر client_ip از نوع ساختار IP_ADDR )تعریف شده در فایل
struct به صورت چهار بایتی(، آرایه 8 بایتی rxtx_buffer با ظرفیت MAX_RXTX_BUFFER (تعریف شده در فایل global معادل 1518 بایت) به عنوان حافظه بافر فرستنده و گیرنده و متغیر plen با اندازه دو بایت تعریف شده اند.
فایل global.c :
MAC_ADDR به شکل زیر به عنوان یک ساختار (structure) در فایل struct در پوشه Driver تحت یک آرایه 6 بایتی تعریف شده است :
به شکل مشابه IP_ADDR به شکل زیر به عنوان یک ساختار در فایل struct تحت یک آرایه 4 بایتی تعریف شده است :
در ابتدای این فایل، متغیرهایی برای ذخیره سازی آدرس IP و آدرس MAC میکروکنترلر AVR
avr_ip و avr_mac و متغیرهایی برای ذخیره سازی آدرس IP و آدرس MAC گیرنده server_ip
و server_mac تعریف شده اند. سپس آدرس IP میکروکنترلر و سمت گیرنده مقداردهی شده اند و در حافظه EEPROM میکروکنترلر ذخیره سازی شده اند. همان طور که در فصل هفتم در توضیحات دیتاشیت تراشه ENC28J60 توضیح داده شد، باید توسط میکروکنترلر حداکثر حافظه بافر تعیین شود. توسط ثابت MAX_RXTX_BUFFER حداکثر ظرفیت حافظه بافر 1518 بایت تعریف شده است.
در انتهای این فایل نیز پایه های مربوط به LED1 و LDE2 مشخص شده اند.
فایل WinAVR_CAMP.h :
در این فایل برخی ثوابت مورد استفاده در برنامه تعریف شده است. به عنوان مثال نوشتن عبارت:
delay_ms(ms)
که تابع ایجاد تاخیر برحسب میلی ثانیه در کتابخانه delay می باشد معادل عبارت :
_delay_ms(ms)
می باشد یا عبارت :
LOW(x)
معادل عبارت :
(x&0xFF)
می باشد، به عنوان مثال اگر data یک متغیر باشد عبارت :
LOW(data)
معادل :
(data&0xFF)
می باشد.
در بخش بعدی در مورد دو فایل Ethernet و struct در پوشه Driver توضیح می دهیم.
فایل Ethernet.c :
تابع eth_generate_header
توسط این تابع سرآمد یا header مربوط به پروتکل اترنت )شامل آدرس MAC مبدا و مقصد( تولید می شود. از این تابع در پیاده سازی پروتکل های ARP ، ICMP ، TCP و UDP استفاده شده است.
تابع software_checksum
توسط این تابع الگوریتم خطایابی checksum بر روی 20 بایت اول header پروتکل IPv4 انجام می شود تا از صحت اطلاعات دریافتی )توسط مقایسه با checksum انجام شده در فرستنده) اطمینان حاصل شود.
فایل struct.h :
در بخش اول این فایل، نام نوع متغیرهای تغییر پیدا کرده است :
به عنوان مثال به جای unsigned char از uint8_t استفاده می شود. در دیگر بخش های این فایل، ساختارهای مختلف مورد استفاده در بخش های دیگر این قسمت تعریف شده است. به عنوان مثال MAC_ADDR برای آدرس MAC و IP_ADDR برای آدرس IP در فایل global.c استفاده شده است.
کتابخانه ی ARP :
تابع arp_generate_packet
از این تابع برای تولید بسته های ARP استفاده می شود. ورودی های تابع عبارت اند از حافظه بافر، آدرس MAC مقصد و آدرس IP مقصد. در ابتدای این تابع، نوع سخت افزار برای پروتکل اترنت عدد 1 قرار می گیرد. در بخش بعدی نوع پروتکل تعیین می شود که مطابق توضیحات فصل پنجم برای IPv4 برابر 0x0800 قرار می گیرد.
در خطوط بعدی به ترتیب طول آدرس MAC برابر 6 بایت و طول آدرس IP برابر 4 بایت تنظیم می شوند. در حلقه ی for اول آدرس MAC فرستنده و گیرنده و در حلقه for دوم آدرس IP فرستنده و گیرنده تنظیم می شوند.
تابع arp_send_request
از این تابع برای ارسال درخواست ARP )مورد نیاز در فرایند Who-is برای یافتن آدرس MAC مقصد( استفاده می شود. تابع arp_send_reply نیز که در ادامه توضیح می دهیم برای پاسخ دادن نوشته شده است.
تابع arp_packet_is_arp
از این تابع برای تشخیص بسته های از نوع ARP و همچنین تعیین این مسئله که آیا IP این بسته برابر IPمیکروکنترلر می باشد یا خیر استفاده می شود.
ورودی های این تابع حافظه بافر و opcode می باشند. )برای بسته های درخواست برابر عدد 1و برای بسته های پاسخ برابر عدد 2 می باشد(
تابع arp_send_reply
این تابع مشابه تابع arp_send_request برای ایجاد پاسخ به بسته های ARP مورد استفاده قرار می گیرد. ورودی های این تابع حافظه بافر و آدرس MAC مقصد است که میخواهیم پاسخ ARPرا برای آن ارسال کنیم.
تابع arp_who_is
اگر قصد ارسال بسته ای را به گره ای از شبکه داشته باشیم و آدرس MAC آن را ندانیم، طبق قوائد پروتکل ARP باید فرایند Who-is اجرا شود. این تابع برای این منظور نوشته شده است.
کتابخانه ی IP :
تابع ip_generate_header
از این تابع برای تولید بخش سرآیند بسته های IP استفاده می شود. ورودی های این تابع عبارت اند از حافظه بافر، بخش های ظرفیت بسته های IP ، پروتکل مورد استفاده در لایه انتقال و آدرس IP گیرنده که مربوط به سرآیند پروتکل IP می شوند.
تابع ip_packet_is_ip
این تابع که تنها ورودی آن اشاره گر حافظه بافر می باشد، بسته های دریافتی را بررسی کرده و در صورتی که بسته از نوع IP باشد و آدرس IP گیرنده آن )در بخش سرآیند IP بسته( برابر IP تنظیم شده در میکروکنترلر باشد، مقدار یک به عنوان خروجی تابع بازگردانده می شود، در غیر اینصورت مقدار صفر بازگردانده می شود.
کتابخانه ی ICMP :
تابع icmp_generate_packet
از این تابع برای تولید بسته های پروتکل ICMP استفاده می شود. تنها ورودی این تابع حافظه بافر می باشد و خروجی ندارد. از این تابع در تابع icmp_send_request برای ارسال درخواست های پروتکل ICMP در شبکه استفاده می شود.
تابع icmp_send_request
از این تابع برای ارسال درخواست پروتکل ICMP در شبکه استفاده می شود. ورودی های این تابع حافظه بافر، آدرس MAC و آدرس IP گیرنده هستند.
تابع icmp_send_rply
توسط این تابع به درخواست های ICMP که توسط تابع icmp_send_request در شبکه ایجاد می شوند پاسخ داده می شود، به همین دلیل این دو تابع شباهت دارند.
تابع icmp_ping
از این تابع برای انجام فرایند ping در شبکه استفاده می شود. در عملیات ping ، یک پیام درخواست فرستاده می شود و مدت زمانی منتظر پاسخ می مانیم (در این تابع به اندازه 100ms) در صورتی که پیام پاسخ را دریافت کردیم، مقدار یک به عنوان خروجی تابع بازگردانده می شود و در غیر اینصورت مقدار صفر بازگشت داده می شود.
کتابخانه ی TCP
تابع tcp_get_dlength
از این تابع برای محاسبه ظرفیت بخش داده بسته های TCP دریافت شده استفاده می شود. ورودی این تابع حافظه بافر می باشد و مقدار برگشتی آن اندازه بخش داده بسته های TCP می باشد.
تابع tcp_get_hlength
از این تابع برای محاسبه ظرفیت بخش سرآیند بسته های TCP دریافت شده استفاده می شود. ورودی این تابع حافظه بافر می باشد و مقدار برگشتی آن اندازه بخش سرآیند بسته های TCP می باشد.
تابع tcp_puts_data_p
از این تابع برای قرار دادن داده های حافظه flash درون حافظه فرستنده استفاده می شود. ورودی های این تابع به ترتیب عبارت اند از حافظه بافر، داده موجود در حافظه flash و آفست آدرس مورد نیاز. مقدار برگشتی تابع نیز مقدار آفست تغییر یافته می باشد.
تابع tcp_puts_data
مشابه تابع tcp_puts_data_p برای قرار دادن داده های حافظه SRAM در بافر فرستنده مورد استفاده قرار می گیرد.
تابع tcp_send_packet
از این تابع برای ارسال بسته های tcp در شبکه استفاده می شود. ورودی های تابع شامل موارد مختلفی مورد نیاز برای تنظیم سرآیند پروتکل TCP می باشد مانند پورت فرستنده، پورت گیرنده، پرچم ها، آدرس MAC و آدرس IP مقصد و موارد مورد نیاز دیگر .
کتابخانه ی UDP :
تابع udp_generate_header
از این تابع برای تولید بخش سرآیند بسته های UDP استفاده می شود. ورودی های این تابع عبارت اند از حافظه بافر، شماره پورت مقصد و اندازه بسته های UDP . تابع به عنوان خروجی مقداری را برنمی گرداند.
تابع udp_puts_data و udp_puts_data_p
برای نوشتن بخش داده بسته های UDP مورد استفاده قرار می گیرند. تابع udp_puts_data_p برای نوشتن داده های موجود در حافظه flash میکروکنترلر استفاده می شود و تابع udp_puts_data برای نوشتن داده موجود در حافظه SRAM میکروکنترلر مورد استفاده قرار می گیرد.
کتابخانه ی HTTP :
تابع http_get_ip
از این تابع برای گرفتن آدرس IP از حافظه بافر پس از فراخوانی تابع http_get_variable که به صورت کد اسکی می باشد و تبدیل آن به معادل باینری و ذخیره سازی آن در متغیر dest استفاده می شود.
تابع http_get_variable
از این تابع برای گرفتن متغیر در روش ارسال GET استفاده می شود. از این تابع در تابع http_webserver_process برای دریافت متن های نوشته شده در جعبه های متنی و نمایش بر روی LCD استفاده می شود.
تابع hex2int
از این تابع برای تبدیل یک کاراکتر hex به معادل عدد صحیح آن استفاده می شود. از این تابع در تابع urldecode استفاده می شود.
تابع http_put_request
از این تابع برای نوشتن درخواست های http در بافر فرستنده استفاده می شود.
تابع urldecode
با زدن دکمه Write LCD در صفحه وب طراحی شده، متن نوشته شده در کادرهای متنی به صورت کد URL به سمت میکروکنترلر ارسال می شوند. به عنوان مثال با نوشتن عبارات زیر در کادر متنی :
به دلیل استفاده از روش GET در HTTP )در تابع http_home توضیح داده می شود(، رشته ارسالی به سمت میکروکنترلر در نوار آدرس مروگر ظاهر می شود :
تابع http_webserver_process
بررسی درخواست های HTTP در تابع http_webserver_process انجام می شود. ورودی های تابع عبارت اند از حافظه بافر، آدرس MAC مقصد (dest_mac) و آدرس IP مقصد ( dest_ip ). در بخش اول توسط دستور if شماره پورت TCP بررسی می شود. به عنوان مثال برای کنترل LED1 از کدهای زیر در تابع استفاده شده است :
در تابع http_home برای ایجاد یک جعبه متن و گرفتن یک رشته از کد زیر استفاده می کنیم :
کلید submit برای ارسال محتویات متن به سرور می باشد. کدهای مورد نیاز برای پاسخ دادن به این درخواست و نمایش رشته گرفته شده روی LCD به صورت زیر می باشد :
در صورتی که بخواهیم یک صفحه ساده HTML که تنها شامل یک لینک می باشد ایجاد کنیم، تابع http_home باید به صورت زیر باشد :
برای ایجاد یک کادر متنی:
<input type=”radio”>
برای ایجاد گزینه های مختلف یا :
<input type=”submit”>
برای دریافت اطلاعات کاربر:
<input type=”text”>
برای ساختن دکمه submit یا تایید اطلاعات )دکمه write lcd در این پروژه( به عنوان مثال با نوشتن کد :
و نتیجه این می شود:
و نتیجه ی کدهای نوشته شده شکل زیر می شود:
تست عملی:
برای تست مدار، ابتدا سورس برنامه را کامپایل نموده و توسط پروگرامر روی میکروکنترلر پروگرام نمایید. تنظیمات فیوز بیت را روی کریستال 8MHZ خارجی قرار دهید.
مدار را توسط کابل شبکه به پورت LAN کامپیوتر وصل کرده و روشن کنید. با روشن کردن دستگاه، صفحه زیر ظاهر می شود :
به صورت پیشفرض IP برد روی 255.255.255.255 تنظیم شده است. با استفاده از کلیدهای جهت نما وارد منوی تنظیمات و بخش AVR IP Config شوید و IP را طبق رنج IP شبکه خود تنظیم کنید. برای مثال اگر رنج IP شبکه 192.168.0.xx باشد، IP را روی 192.168.0.10 تنظیم کنید.
نکته : مطابق شکل های زیر در بخش تنظیمات TCP/IP کارت شبکه، باید رنج IP شبکه را به شکل مناسبی تنظیم کنیم. به عنوان مثال برای تطبیق با IP برابر 192.168.0.10 ، می توان این آدرس را روی192.168.0.15 تنظیم کرد.
شکل زیر نتیجه دستور ping را برای تست ارتباط نشان می دهد.
مرورگر اینترنتی خود را باز کنید و IP برد را وارد کنید. حال باید صفحه ای شبیه تصویر زیر را روی مرورگر مشاهده کنید.
با نوشتن در کادر LCD Line 1 و LCD Line 2 و زدن دکمه Write LCD مطابق کدهایی که در بخش های قبل توضیح داده شد، متن نوشته شده در این دو جعبه متنی توسط دستور GET در پروتکل HTTP به سمت میکروکنترلر ارسال می شود و بر روی سطر اول و سطر دوم LCD متصل شده به میکروکنترلر نمایش داده می شود.
برای گسترش این پروژه می توانید به پایه های PORTA میکروکنترلر برد طراحی شده که توسط pin header در دسترس می باشد، سنسورهای مختلف متصل نموده و مقادیر خوانده شده از سنسورها را در صفحه وب طراحی شده نمایش دهید.
با اتصال برد طراحی شده به یک switch شبکه و تنظیم صحیح آدرس های IP ، امکان دسترسی گره های مختلف شبکه به وب سرور محلی طراحی شده وجود خواهد داشت. همچنین توسط اتصال switch به یک router که به عنوان access point عمل می کند )یا استفاده
مستقیم از یک router ( و انجام تنظیمات مربوطه، امکان دسترسی به وب سرور محلی به صورت wireless نیز وجود خواهد داشت.
ارسال یک دیدگاه