پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc
سلام
به درخواست یکی از دوستان، می خوام تو این تاپیک به کتابخونه ارتباط سریال uart رو معرفی کنم. این کتابخونه جدا از کتابخونه های avrlib و چون راحتر بود دیگه بیخیال کتابخونه uart Avrlib شدم. این فایل رو می تونین از اینجا دانلود کنید : (چرا سایت امکان پلود نداره؟؟!)
http://beaststwo.org/avr-uart/Updated%20_UART_Library.zip
کار کردن باهاش خیلی ساده. (البته یه باگ داشت که در راه پیدا کردنش، دست دوتا mega16 هام از این دنیا کوتاه شد و البته یه mega16 دیگه رو هم فلج کردم!! بهرحال در راه علم ...)
uart.h رو باز کنید. خیلی سریع بررسی می کنیم. یه ماکرو به شکل زیر تعریف کرده :
#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)
این ماکرو برای معرفی کردن نرخ ارتباط سریال (یا همون سرعت خودمون!!) استفاده میشه. پارامتر هاش هم که مشخص، اولی baud و دومی فرکانس کلاک. بعد از این یه ماکرو دیگه یه نام UART_BAUD_SELECT_DOUBLE_SPEED برای استفاده از سرعت دو برابر تعریف شده.
ادامه:
/** Size of the circular receive buffer, must be power of 2 */
#ifndef UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE 32
#endif
/** Size of the circular transmit buffer, must be power of 2 */
#ifndef UART_TX_BUFFER_SIZE
#define UART_TX_BUFFER_SIZE 32
#endif
اینجا اندازه بافر برای نگهداری داده های دریافت شده یا داده هایی که باید ارسال بشن تعریف شده. اگه بخواین تغییرش بدین، دقت کنید که گفته باید توانی از 2 باشه. فعلا تغییرش نمیدیم...
بریم به قسمت توابع
extern void uart_init(unsigned int baudrate);
این تابع uart رو فعال میکنه و مقداردهی های اولیه رو انجام میده. پارامتر تابع باید با ماکرو تعیین baud باشه. مثلا این دستور برای تعیین باوود 9600 برای کلاک 1 مگاهرتز :
uart_init(UART_BAUD_SELECT(9600, 1000000L));
بقیه توابع هم مشخص دیگه! من فقط با uart_puts کار میکنم. برای ارسال رشته. بقیه توابع بکار نمیان!!!
uart.c رو باز کنید. اینجا دو تا متغیر مهم داریم.
UART_RxBuf
این رشته، همون بافر برای نگه داری اطلاعات دریافتیه. هر بایت اطلاعاتی که بیاد تو این متغیر ذخیره میشه.
UART_RxHead
این متغیر نشون میده چند بایت تو بافر UART_RxBuf اطلاعات دریافتی ذخیره شده.
وقفه دربافت رو ببینید ...
ISR(UART0_RECEIVE_INTERRUPT)
/************************************************** ***********************
Function: UART Receive Complete interrupt
Purpose: called when the UART has received a character
************************************************** ************************/
{ …
این خط رو آخر وقفه می بینیم :
UART_RxBuf[tmphead] = data;
بایت دریافتی رو تو بافر مینویسه. اما یه مشکل داره! اونم اینه که از اندیس شماره 1 شروع به نوشتن میکنه نه صفر!! چراش رو دیگه خودتون تو چند خط بالاتر ببینین. خوب برای رفع این مشکل اینطوری تغییرش بدین:
UART_RxBuf[tmphead-1] = data;
خوب فعلا دیگه مشکلی نیست. این برنامه برای میکرو اول که اطلاعات می فرسته:
#include <avr/io.h>
#include <util/delay.h>
#include "uart.c"
char *str="test serial";
int main()
{
sei();
uart_init(UART_BAUD_SELECT(9600, 1000000L));
_delay_ms(2000);
uart_puts(str);
_delay_ms(2000);
uart_puts("ok"
;
return 0;
}
اینم برنامه میکرو دوم که اطلاعات ارسال شده رو دریافت میکنه و رو ال سی دی نمایش میده:
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.c"
#include "uart.c"
int main()
{
sei();
lcdInit();
uart_init(UART_BAUD_SELECT(9600, 1000000L));
while(1)
{
lcdClear();
if (UART_RxHead != 0)
lcdPrintData(UART_RxBuf, UART_RxHead);
_delay_ms(20);
}
}
دستور sei یادتون نره! وقفه ها باید فعال بشن.
ضمنا فریم ارسال اطلاعات هم تو تابع uart_init تعیین شده. پیش فرض همون 8 بیت داده بدون parity و یک بیت داده. معمولا همینه دیگه. مگه اینکه یه پروژه مخوف سری داشته باشین ... !!
موفق باشید.
سلام
به درخواست یکی از دوستان، می خوام تو این تاپیک به کتابخونه ارتباط سریال uart رو معرفی کنم. این کتابخونه جدا از کتابخونه های avrlib و چون راحتر بود دیگه بیخیال کتابخونه uart Avrlib شدم. این فایل رو می تونین از اینجا دانلود کنید : (چرا سایت امکان پلود نداره؟؟!)
http://beaststwo.org/avr-uart/Updated%20_UART_Library.zip
کار کردن باهاش خیلی ساده. (البته یه باگ داشت که در راه پیدا کردنش، دست دوتا mega16 هام از این دنیا کوتاه شد و البته یه mega16 دیگه رو هم فلج کردم!! بهرحال در راه علم ...)
uart.h رو باز کنید. خیلی سریع بررسی می کنیم. یه ماکرو به شکل زیر تعریف کرده :
#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)
این ماکرو برای معرفی کردن نرخ ارتباط سریال (یا همون سرعت خودمون!!) استفاده میشه. پارامتر هاش هم که مشخص، اولی baud و دومی فرکانس کلاک. بعد از این یه ماکرو دیگه یه نام UART_BAUD_SELECT_DOUBLE_SPEED برای استفاده از سرعت دو برابر تعریف شده.
ادامه:
/** Size of the circular receive buffer, must be power of 2 */
#ifndef UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE 32
#endif
/** Size of the circular transmit buffer, must be power of 2 */
#ifndef UART_TX_BUFFER_SIZE
#define UART_TX_BUFFER_SIZE 32
#endif
اینجا اندازه بافر برای نگهداری داده های دریافت شده یا داده هایی که باید ارسال بشن تعریف شده. اگه بخواین تغییرش بدین، دقت کنید که گفته باید توانی از 2 باشه. فعلا تغییرش نمیدیم...
بریم به قسمت توابع
extern void uart_init(unsigned int baudrate);
این تابع uart رو فعال میکنه و مقداردهی های اولیه رو انجام میده. پارامتر تابع باید با ماکرو تعیین baud باشه. مثلا این دستور برای تعیین باوود 9600 برای کلاک 1 مگاهرتز :
uart_init(UART_BAUD_SELECT(9600, 1000000L));
بقیه توابع هم مشخص دیگه! من فقط با uart_puts کار میکنم. برای ارسال رشته. بقیه توابع بکار نمیان!!!

uart.c رو باز کنید. اینجا دو تا متغیر مهم داریم.
UART_RxBuf
این رشته، همون بافر برای نگه داری اطلاعات دریافتیه. هر بایت اطلاعاتی که بیاد تو این متغیر ذخیره میشه.
UART_RxHead
این متغیر نشون میده چند بایت تو بافر UART_RxBuf اطلاعات دریافتی ذخیره شده.
وقفه دربافت رو ببینید ...
ISR(UART0_RECEIVE_INTERRUPT)
/************************************************** ***********************
Function: UART Receive Complete interrupt
Purpose: called when the UART has received a character
************************************************** ************************/
{ …
این خط رو آخر وقفه می بینیم :
UART_RxBuf[tmphead] = data;
بایت دریافتی رو تو بافر مینویسه. اما یه مشکل داره! اونم اینه که از اندیس شماره 1 شروع به نوشتن میکنه نه صفر!! چراش رو دیگه خودتون تو چند خط بالاتر ببینین. خوب برای رفع این مشکل اینطوری تغییرش بدین:
UART_RxBuf[tmphead-1] = data;
خوب فعلا دیگه مشکلی نیست. این برنامه برای میکرو اول که اطلاعات می فرسته:
#include <avr/io.h>
#include <util/delay.h>
#include "uart.c"
char *str="test serial";
int main()
{
sei();
uart_init(UART_BAUD_SELECT(9600, 1000000L));
_delay_ms(2000);
uart_puts(str);
_delay_ms(2000);
uart_puts("ok"

return 0;
}
اینم برنامه میکرو دوم که اطلاعات ارسال شده رو دریافت میکنه و رو ال سی دی نمایش میده:
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.c"
#include "uart.c"
int main()
{
sei();
lcdInit();
uart_init(UART_BAUD_SELECT(9600, 1000000L));
while(1)
{
lcdClear();
if (UART_RxHead != 0)
lcdPrintData(UART_RxBuf, UART_RxHead);
_delay_ms(20);
}
}
دستور sei یادتون نره! وقفه ها باید فعال بشن.
ضمنا فریم ارسال اطلاعات هم تو تابع uart_init تعیین شده. پیش فرض همون 8 بیت داده بدون parity و یک بیت داده. معمولا همینه دیگه. مگه اینکه یه پروژه مخوف سری داشته باشین ... !!

موفق باشید.
دیدگاه