PDA

توجه ! این یک نسخه آرشیو شده میباشد و در این حالت شما عکسی را مشاهده نمیکنید برای مشاهده کامل متن و عکسها بر روی لینک مقابل کلیک کنید : [آموزش] تجربیات عملی میکروکنترلری ...



1nafar
01-03-2014, 00:06
TIMEOUT در میکروکنترلر ها ( پورت سریال )
بعضی وقت ها نیاز داریم تا از پورت سریال میکروکنترلر ها استفاده کنیم و برای این پورت برنامه بنویسیم .
معمولا ما در هنگام برنامه نویسی ، از دستورات استاندارد برنامه نویسی ( کتابخانه stdio.h ) یا به صورت مستقیم از رجیستر ها برای تبادل داده بر مبنای این پروتکل استفاده کنیم . در این رابطه بحث های زیادی در سطح انجمن و کتب برنامه نویسی انجام شده و کلیه دستورات مذکور قبلا معرفی شدن .
دستورات زیر از جمله دستورات استاندارد برنامه نویسی پروتکل uart یا rs232 در زبان سی هستند :


printf(string)
putchar()

fputc()

putc (cdata)

value = getc()

value = fgetc(stream)

value=getch()

value=getchar()



برای ارسال داده به دستگاه جانبی مشکلی وجود نداره ، ما با یکی از دستورات printf یا putchar یا fputc یا putc رشته ، متغیر یا کاراکتر مورد نظرمون رو با یک نرخ انتقال داده ثابت به دستگاه جانبی ارسال میکنیم .
برای دریافت داده از دستگاه جانبی از دستورات getc و fgetc و getch و getchar و... استفاده میشه . معمولا با اجرا شدن این دستورات ،در درون کتابخانه ها حلقه زیر اجرا میشه :



while (!(RXRDY)); // Wait for new char
return (*Rx Buffer );



مثلا برای میکروکنترلر arm اتمل ، کلیه هدر های ارائه شده ، در نهایت دستور زیر رو برای دریافت یک کاراکتر از پورت سریال اجرا میکنن :


while (!((*AT91C_US0_CSR) & AT91C_US_RXRDY)); // Wait for Empty Rx Buffer
return (*AT91C_US0_RHR );

یا در کامپایلر mplab دستور زیر در هنگام دریافت داده از پورت سریال اجرا میشود :



while (! U1STAbits.URXDA); // wait until data is available
return U1RXREG; // return received character over UART


همون طور که مشاهده میکنید در تمامی حلقه های بالا اگر بعد از اجرای دستورات getc و fgetc و getch و getchar و.. داده ای به بافر پورت سریال وارد نشه ، میکروکنترلر در حلقه while موجود برای همیشه گیر میکنه .
این حالت ممکنه در هنگام ارتباط با یک کامپیوتر و به دلیل هنگ کردن نرم افزار کامپیوتری ، در هنگام دریافت داده از یک ماژول و به دلیل قطع شدن تغذیه ماژول ، در هنگام دریافت داده از یک میکروکنترلر و ایجاد خطا در داده دریافتی و و در هنگام ارتباط با هر نوع وسیله جانبی دیگر و به دلیل بروز مشکلاتی مانند قطع شدن سیم ها ، عدم اتصال صحیح سیم ها و... میکروکنترلر ما هنگ کنه و نتونه سایر دستورات رو اجرا کنه .
مثال:
You can see links before reply
You can see links before reply
You can see links before reply
You can see links before reply
و... نمونه برنامه های نوشته برای پورت سریال هستند که در آنها بروز اختلال در پروتکل سریال پیشبینی نشده است ، میکروکنترلر های موجود در این پروژه ممکنه در آینده به دلیل بروز اختلال در پروتکل rs232 عملکردی غیر قابل پیشبینی داشته باشن .
برای رفع این مشکل باید از TIMEOUT استفاده کنیم . TIMEOUT رو میشه هم به صورت سخت افزاری و هم به صورت نرم افزاری برای میکروکنترلر اجرا کرد (مثلا میکروکنترلر های arm از TIMEOUT سخت افزاری پشتیبانی میکنن . اما میکروکنترلر pic و avr فاقد TIMEOUT سخت افزاری هستند و ما باید TIMEOUT رو به صورت نرم افزاری برای اونا اجرا کنیم ).
چند تا نکته :


TIMEOUT نرم افزاری فقط در کامپایلر های قابل اجرا هست که به کاربران امکان ویرایش کتابخونه ها رو دادن .
برای برخی از کامپایلر مثل bascom avr یا ccs pic c جهت TIMEOUT دستوراتی در نظر گرفته شده ، برای کسب اطلاعات بیشتر دستور TIMEOUT رو در راهنمای اونا جستوجو کنید ، مثال برای بسکام :You can see links before reply
استفاده از دستورات TIMEOUT ، قابلیت جدیدی رو به برنامه اضافه نمیکنه و بدون لحاظ کردن این ویژگی ،برنامه بدون هیچ مشکلی کار میکنه . این اموزش صرف برای افرادی هست که میخوان به صورت حرفه ای برنامه نویسی کنند .

در ادامه با یک مثل ، نحوهی استفاده از قابلیت TIMEOUT برای میکروکنترلر های PIC و ATM اتمل توضیح داده شده است :
اجرای دستور TIMEOUT در کامپایلر CCS PIC C :
برای استفاده از TIMEOUT در این کامپایلر باید در هنگام راه اندازی واحد UART دو دستور ERRORS و TIMEOUT=X رو در پیکربندی پروتکل وارد کنید ، مثال :

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS,TIMEOUT=70)

در پیکربندی بالا TIMEOUT برابر با 70 میلی ثانیه تنظیم شده
برای استفاده از TIMEOUT باید بعد از دستورات getc و fgetc و getch و getchar و.. ، دستور زیر رو قرار بدید :

if (c==0 && RS232_ERRORS==0) break;


در این حالت اگه تا 70 میلی ثانیه ، داده ای توسط پورت سریال دریافت نشه ، میکروکنترلر از کلیه دستورات getc و fgetc و getch و getchar و.. عبور میکنه ( از داخل حلقه مربوط به دریافت داده خارج میشه ) .

مثال عملی :
در برنامه زیر اگر بعد از گذشت 2 ثانیه داده ای از دستگاه جانبی دریافت نشود ، رشته "TIMEOUT , type faster" به دستگاه جانبی ارسال میگردد .

#include <16F877A.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT //Power Up Timer
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS,TIMEOUT=2000)
void main()
{
char c;
while(true){
printf("Perss any key...\r");
c=getc();
if (c==0 && RS232_ERRORS==0)
printf("TIMEOUT , type faster\r" );
else
printf("Enter key is:%c\r",c );
}
}


مثال عملی
در برنامه ای ، باید یک رشته از پورت سریال دریافت شود ،در این حالت باید از کتابخانه input.c استفاده کنیم ، این کتابخونه فاقد دستورات لازم جهت timeout هست و ما باید دستور شرطی زیر رو در کتابخانه input.c و بعد از دستور c=getc(); قرار بدیم .


if (c==0 && RS232_ERRORS==0) break;

برنامه :

#include <16F877A.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT //Power Up Timer
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS,TIMEOUT=2000)
#INCLUDE <INPUT.C>
void main()
{
char c[10];
while(true){
printf("Enter string..\r");
get_string(c, 10);
printf("Enter sting is:%s\r",c);
}
}


تابع جدید get_string :

void get_string(char* s, unsigned int8 max) {
unsigned int8 len;
char c;

--max;
len=0;
do {
c=getc();
if (c==0 && RS232_ERRORS==0){
printf("TIMEOUT , type faster\r" );
break;
}
if(c==8) { // Backspace
if(len>0) {
len--;
putc(c);
putc(' ');
putc(c);
}
} else if ((c>=' ')&&(c<='~'))
if(len<=max) {
s[len++]=c;
putc(c);
}
} while(c!=13);
s[len]=0;
}


به زودی نحوه ی استفاده از TIMEOUT برای میکروکنترلر های avr و arm رو توضیح میدم .