اطلاعیه

Collapse
No announcement yet.

مشکل در وقفه سریال

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    #16
    پاسخ : مشکل در وقفه سریال

    نوشته اصلی توسط artison
    1- توی اینتراپت نیازی به دستورهای گرفتن دیتا نداریم خود بافر دریافت UDR رو بخونیم و توی متغیر بریزیم کافی هست
    2- شما وقتی از ارتباط سریال استفاده میکنید باید از پروتکل استاندارد استفاده کنید یا یک پروتکل برای خودتون ایجاد کنید . مثلا اگر با یک ماژول خاص کار میکنید باید ببینید ساختار دیتای اون چطور هست و همون رو پیاده کنید . اگر ارتباط بین دو میکرو یا میکرو و کامپیوتر هست ، باید پروتکلی در نظر بگیرید که توش یا طول بسته ها ثابت باشه (مثلا 5 کاراکتر در هر بسته ) یا اینکه ابتدا و انتهای هر بسته با کاراکتر خاصی مشخص بشه (مثلا 0x02 در ابتدا و 0x03 انتها) و طول بسته رو در داخل خود بسته مثلا در کاراکتر دوم بیان کنید تا گیرنده متوجه بشه کی ایندکس صفر میشه .
    من نیاز دارم که در وقفه udr رو بخونم و توی متغیر بریزم و درخارج از وقفه ،هم از اون متغیره که تو وقفه پرش کردم اسفاده کنم و هم از دستور gets اما دیگه اون دستور gets درست کار نمیکنه برای حل این مشکل چیکار کنم?

    دیدگاه


      #17
      پاسخ : مشکل در وقفه سریال

      من هیچ وقت از gets استفاده نمی کنم فکر کردم شما دارین از getchar استفاده می کنید و همون طور که دوستان دیگه و من هم تو یکی از جواب هام قبلا گفتم دیتا رو مستقیم بردارین
      می اونید یک کاری انجام بدید یک تابع جدید تعریف کنید که 2 تا خروجی داشته باشه به جای gets یکی اینکه دیتا قبلا خونده شده یکی هم مقدار اخرین رشته می تونید این کار براحتی با تعریف متغیر های گلوبال انجام بدید اگه موفق نشدید خبر بدین بنویسم
      التماس دعا

      دیدگاه


        #18
        پاسخ : مشکل در وقفه سریال

        نوشته اصلی توسط ali.ra
        من هیچ وقت از gets استفاده نمی کنم فکر کردم شما دارین از getchar استفاده می کنید و همون طور که دوستان دیگه و من هم تو یکی از جواب هام قبلا گفتم دیتا رو مستقیم بردارین
        می اونید یک کاری انجام بدید یک تابع جدید تعریف کنید که 2 تا خروجی داشته باشه به جای gets یکی اینکه دیتا قبلا خونده شده یکی هم مقدار اخرین رشته می تونید این کار براحتی با تعریف متغیر های گلوبال انجام بدید اگه موفق نشدید خبر بدین بنویسم
        من با sim900 کار میکنم و تو کل برنامم از gets استفاده کردم
        میگم یکبار ااصن برگردم و سوال اصلیم رو دوباره میگم که تنها مشکل من این بود که توی حلقه پشت gets متوقف میشد حالا شما هم برا رفع این مشکل نظرتون همین راهی است که داریم میریم? اگه همینه که هیچی ولی اگه راهی به ذهنتون میرسه ممنون میشم بگید
        بعد اگه لطف کنید و همینی که بالا گفتید کدشو بنویسید و بیشتر توضیح بدید ممنون میشم. من تازه کار هستم

        دیدگاه


          #19
          پاسخ : مشکل در وقفه سریال

          char datas[16],index=0; // تعریف ها

          // This flag is set on USART Receiver buffer overflow
          bit rx_buffer_overflow;

          // USART Receiver interrupt service routine
          interrupt [USART_RXC] void usart_rx_isr(void)
          {
          char status,data;
          status=UCSRA;
          data=UDR;
          if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
          {
          rx_buffer[rx_wr_index++]=data;
          #if RX_BUFFER_SIZE == 256
          // special case for receiver buffer size=256
          if (++rx_counter == 0) rx_buffer_overflow=1;
          #else
          if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
          if (++rx_counter == RX_BUFFER_SIZE)
          {
          rx_counter=0;
          rx_buffer_overflow=1;
          }
          #endif
          }
          if(data) datas[index++]=data;
          else
          index=0;
          // وقتی else اجرا می شه یک رشته اماده داری که داخل ارایه datas هستش باید بخونیش که دوباره روش نوشته نشه ترجیحا تو شبیه سازی اول تست کن
          }
          التماس دعا

          دیدگاه


            #20
            پاسخ : مشکل در وقفه سریال

            نوشته اصلی توسط ali.ra
            char datas[16],index=0; // تعریف ها

            // This flag is set on USART Receiver buffer overflow
            bit rx_buffer_overflow;

            // USART Receiver interrupt service routine
            interrupt [USART_RXC] void usart_rx_isr(void)
            {
            char status,data;
            status=UCSRA;
            data=UDR;
            if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
            {
            rx_buffer[rx_wr_index++]=data;
            #if RX_BUFFER_SIZE == 256
            // special case for receiver buffer size=256
            if (++rx_counter == 0) rx_buffer_overflow=1;
            #else
            if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
            if (++rx_counter == RX_BUFFER_SIZE)
            {
            rx_counter=0;
            rx_buffer_overflow=1;
            }
            #endif
            }
            if(data) datas[index++]=data;
            else
            index=0;
            // وقتی else اجرا می شه یک رشته اماده داری که داخل ارایه datas هستش باید بخونیش که دوباره روش نوشته نشه ترجیحا تو شبیه سازی اول تست کن
            }


            من چون واقعا تازه کارم تو برنامه نویسی نمیدونم این چه نوع if هست تا حالا این طوری ندید بود من فقط فرم سادشو کهبه فرم if()
            { };بلدم میشه بگید if ( data) چه جور شرطی هست
            سوال دوم اینکه الان میتونم تو برنامم از gets استفاده کنم?
            با سپاس فراوان

            دیدگاه


              #21
              پاسخ : مشکل در وقفه سریال

              من یکم خلاصه می نویسم فکر کنم واسه اون بوده
              if(data)
              شرط روی کارکتر data هستش و فقط وقتی غلط می شه که نال باشه
              از gets هم نمی تونید استفاده کنید اما می تونید به جاش ارایه گلوبال رو بخونید
              التماس دعا

              دیدگاه


                #22
                پاسخ : مشکل در وقفه سریال

                نوشته اصلی توسط mohammadt3000
                من نیاز دارم که در وقفه udr رو بخونم و توی متغیر بریزم و درخارج از وقفه ،هم از اون متغیره که تو وقفه پرش کردم اسفاده کنم و هم از دستور gets اما دیگه اون دستور gets درست کار نمیکنه برای حل این مشکل چیکار کنم?
                من فکر میکنم شما به جای طرح این سوالات در انجمن و منتظر جواب ماندن ، به قول دوستمون بهتره یکم وقت بذارید برنامه نویسی C مطالعه بفرمایید
                من کد وقفه رو به شما دادم یعنی شما دیتا رو با وقفه میگیرید و توی یک متغیر آرایه یا رشته میریزید . هرجای برنامه هم خواستید میتونید استفاده بفرمایید نمیدونم چه گیری دادید حتما برید سراغ Gets و ....
                Don't hesitate to ask any question ..

                دیدگاه


                  #23
                  پاسخ : مشکل در وقفه سریال

                  سلام دوستان منم همین مشکل رو دارم :angry:
                  برنامه زیر رو هم با کدویزارد نوشتم واسه دریافت یک کاراکتر هم وقفه گذاشتم ولی نمیدونم چطوری از این وقفه استفاده کنم خواهشا بگین چه دستوری و کجا اضافه کنم؟؟؟ :cry2: :cry2:
                  کد:
                   
                  
                  #include <mega32a.h>
                  #include <delay.h>
                  char str[1];
                  #ifndef RXB8
                  #define RXB8 1
                  #endif
                  
                  #ifndef TXB8
                  #define TXB8 0
                  #endif
                  
                  #ifndef UPE
                  #define UPE 2
                  #endif
                  
                  #ifndef DOR
                  #define DOR 3
                  #endif
                  
                  #ifndef FE
                  #define FE 4
                  #endif
                  
                  #ifndef UDRE
                  #define UDRE 5
                  #endif
                  
                  #ifndef RXC
                  #define RXC 7
                  #endif
                  
                  #define FRAMING_ERROR (1<<FE)
                  #define PARITY_ERROR (1<<UPE)
                  #define DATA_OVERRUN (1<<DOR)
                  #define DATA_REGISTER_EMPTY (1<<UDRE)
                  #define RX_COMPLETE (1<<RXC)
                  
                  // USART Receiver buffer
                  #define RX_BUFFER_SIZE 8
                  char rx_buffer[RX_BUFFER_SIZE];
                  
                  #if RX_BUFFER_SIZE <= 256
                  unsigned char rx_wr_index,rx_rd_index,rx_counter;
                  #else
                  unsigned int rx_wr_index,rx_rd_index,rx_counter;
                  #endif
                  
                  // This flag is set on USART Receiver buffer overflow
                  bit rx_buffer_overflow;
                  
                  // USART Receiver interrupt service routine
                  interrupt [USART_RXC] void usart_rx_isr(void)
                  {
                  char status,data;
                  status=UCSRA;
                  data=UDR;
                  if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
                    {
                    rx_buffer[rx_wr_index++]=data;
                  #if RX_BUFFER_SIZE == 256
                    // special case for receiver buffer size=256
                    if (++rx_counter == 0) rx_buffer_overflow=1;
                  #else
                    if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
                    if (++rx_counter == RX_BUFFER_SIZE)
                     {
                     rx_counter=0;
                     rx_buffer_overflow=1;
                     }
                  #endif
                    }
                  }
                  
                  #ifndef _DEBUG_TERMINAL_IO_
                  // Get a character from the USART Receiver buffer
                  #define _ALTERNATE_GETCHAR_
                  #pragma used+
                  char getchar(void)
                  {
                  char data;
                  while (rx_counter==0);
                  data=rx_buffer[rx_rd_index++];
                  #if RX_BUFFER_SIZE != 256
                  if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
                  #endif
                  #asm("cli")
                  --rx_counter;
                  #asm("sei")
                  return data;
                  }
                  #pragma used-
                  #endif
                  #include <stdio.h>
                  
                  void main(void)
                  {
                  
                  PORTB=0x00;
                  DDRB=0xFF;
                  
                  PORTA=0x00;
                  DDRA=0xFF;
                  
                  UCSRA=0x00;
                  UCSRB=0x98;
                  UCSRC=0x06;
                  UBRRH=0x00;
                  UBRRL=0x33;
                  
                  ACSR=0x80;
                  SFIOR=0x00;
                  
                  #asm("sei")
                  
                  while (1)
                     {
                     gets(str,1);
                  
                      if(str==0x61)  PORTB=0xF0;
                      else  PORTB=0x0F;
                  
                     PORTA=0b01010101;
                     delay_ms(100);
                     PORTA=0b10101010;
                     delay_ms(100);
                      
                     }
                  }

                  دیدگاه


                    #24
                    پاسخ : مشکل در وقفه سریال

                    نوشته اصلی توسط artison
                    من فکر میکنم شم
                    ا به جای طرح این سوالات در انجمن و منتظر جواب ماندن ، به قول دوستمون بهتره یکم وقت بذارید برنامه نویسی C مطالعه بفرمایید
                    من کد وقفه رو به شما دادم یعنی شما دیتا رو با وقفه میگیرید و توی یک متغیر آرایه یا رشته میریزید . هرجای برنامه هم خواستید میتونید استفاده بفرمایید نمیدونم چه گیری دادید حتما برید سراغ Gets و ....
                    کی گفته من منتظر جواب میمونم و خودم هیچ کاری نمیکنم .بعدشم این که یه متغیر رو تو وقفه پر کنیم و تو وقفه ازش اسفاده کنیم رو نوشتم و جواب هم داد
                    و من میخواستم همزمان از gets هم استفاده کنم. یکی از خوبیاش این بود که داده هارو از دست نمیدادی ولی اینجا اگه نخونی داده رو از دستت رفته
                    بعدشم مگه جای شما رو توانجمن تنگ کردم من تازه شروع به کار کردم و هیچ تجربه ای ندارم و سوالاتم رو هم تو همین انجمن مطرح میکنم
                    اگه همه همه چیز رو بلد بودن دیگه نیازی به این جور جاها نبود بعدشم خودم دارم مطالعه میکنم نیازی به توصیه شما نبود

                    دیدگاه


                      #25
                      پاسخ : مشکل در وقفه سریال

                      فرض کنید شما میخواید یک سری اعداد که سرعت چرخیدن یک step motor هست و 1تا 5 رقمی هستند رو از کامپیوتر به میکرو بفرستید تا میکرو اون موتور رو با سرعت مناسب بچرخونه پس گامهای زیر رو پی میگیریم : (فرض کنید اعداد شما 1 ، 55 ، 987 ، 12345 و 0 باشه )
                      اول توی میکرو برنامه چرخیدن موتور رو مینویسیم که شامل مراحل مختلفی هست . سپس میکرو رو پروگرام میکنیم تا موتور رو با یک سرعت اولیه ثابت مثلا 20 دور در دقیقه بچرخونه . حالا میخوایم سرعت موتور رو با دستوراتی که از پورت سریال میفرستیم تغییرش بدیم . اما یک مشکل بوجود میاد :sad:! حدس بزنید چی ؟ اگر ما توی برنامه چرخوندن موتور بیایم و دستور دریافت از سریال رو بذاریم ، به محض اینکه موتور یک دور بچرخه ، به دستور get میرسه و منتظر میمونه تا عددی رو دریافت کنه پس عملا موتور از حرکت می ایسته ! اگر هم دستور get رو توی اون قسمت از برنامه نذاریم ، میکرو در حال چرخوندن موتور هست و اصلا نمیفهمه که دیتای جدیدی اومده و باید سرعت تغییر کنه ..
                      اینجاست که "وقفه سریال" مفهوم پیدا میکنه
                      خب حالا چطور ازش استفاده کنیم ؟
                      جواب : یک بافر در میکرو به نام UDR وجود داره که اطلاعات سریال وقتی به میکرو برسند توی اون ریخته میشند . ابتدا تنظیمات سریال و فعال کردن وقفه رو توی کد ویزارد انجام میدیم . بعد خودش یک تابع میسازه که کدهای تشخیص خطاهای مختلفی رو شامل میشه اما برای شروع نیاز به اون کدها نیست پس تابع رو ساده میکنیم
                      interrupt [USART_RXC] void usart_rx_isr(void)
                      {
                      dat[j]=UDR;
                      if(j<=2){
                      j++;}
                      else{
                      j=0;
                      }
                      }
                      Don't hesitate to ask any question ..

                      دیدگاه


                        #26
                        پاسخ : مشکل در وقفه سریال

                        توی نمونه کدی که بالا گذاشتم ما یک متغیر آرایه ای داریم به اسم data و یک شمارنده به نام j که اندیس آرایه رو مشخص میکنه . برای اینکه بتونیم از این آرایه در تمام برنامه استفاده کنیم ، این آرایه رو درون وقفه تعریف نمیکنیم بلکه در تعریف در اول پروژه انجام میشه (یعنی متغیر global هست و local نیست ) اما متغیر j یک شمارنده هست و جای دیگری بهش نیاز نداریم پس چرا اون رو هم بصورت محلی (local ) تعریفش نکردیم ؟ جواب اینه که اگر داخل تابع تعریف بشه با هر بایت اطلاعات دریافتی تابع اجرا میشه و چون j داخلش تعریف شده دیگه مقدار قبلب خودشو نگه نمیداره و مقدار اولیه میگیره ! پس نتیجه این شد که هم آرایه و هم شمارنده اندیس باید متغیر global باشند .
                        با هر بار اجرای وقفه بافر UDR پر میشه و وقفه اجرا میشه ما این بافر رو تور خانه j ام از آرایه میریزیم و j رو یک واحد زیاد میکنیم برای دفعه بعد که وقفه اجرا میشه . ( در کد بالا فرض شده دیتای ما در بسته های 3 تایی بیاد واسه همین گفته اگر j برابر 2 شد اون رو صفر کنه )
                        برگردیم سر پروژه خودمون که ارسال اعداد 5 رقمی بود پس شرط حلقه J رو به جای 2 برابر 4 در نظر میگیریم . پس کد ما میشه اینجوری :
                        interrupt [USART_RXC] void usart_rx_isr(void)
                        {
                        char j
                        dat[j]=UDR;
                        if(j<=4){
                        j++;}
                        else{
                        j=0;
                        }
                        }
                        حالا سوال اینجاست که وقتی برنامه میکرو در حال چرخوندن موتور هست از کجا بفهمه داده جدیدی اومده ؟ :question:
                        پس ما یک متغیر نشانه در نظر میگیریم براش مثلا اسمش رو میذاریم daryaft_shod !
                        بعد زمانی که توی وقفه دیتای ما کامل برسه اندیس آرایه یعنی j برابر 5 میشه همونجا میگیم daryaft_shod =1;

                        interrupt [USART_RXC] void usart_rx_isr(void)
                        {
                        char j
                        dat[j]=UDR;
                        if(j<=4){
                        j++;}
                        else{
                        daryaft_shod=1;
                        j=0;
                        }
                        }
                        برگردیم تو برنامه چرخوندن موتور ؛ هر یک بار که موتور رو چرخوندیم با دستور if بررسی میکنیم آیا daryaft_shod برابر با یک شده یا نه ؟ اگر شده بود میریم و آرایه data رو میخونیم و عدد دریافت شده در دور موتور اعمال میکنیم
                        Don't hesitate to ask any question ..

                        دیدگاه


                          #27
                          پاسخ : مشکل در وقفه سریال

                          خب حالا به نظر شما من وقتی میخوام بگم دور موتور من بشه 55 ، این که دو رقمه ! پس چطور برنامه بفهمه داده جدید رسیده ؟
                          خیلی ساده هست ! شما وقتی قرار دادتون 5 تایی هست 55 رو هم بصورت 00055 میفرستید تا بشه 5 تا :rolleyes:
                          وقتی شما از دستورات توابع انواع get استفاده میکنید در حقیقت همین کار خواندن بافر UDR رو انجام میدید اما چون برنامه شما متوقف شده و منتظر دریافت اطلاعات میمونه ، تصور میکنید کار باهش راحت تره و مطمئن تره
                          اینم از توضیحات ساده اینتراپت سریال ....خسته نباشید :job:
                          اگر سوالی داشتید بپرسید تا بعدش کد رو پیچیده تر کنیم :bye
                          Don't hesitate to ask any question ..

                          دیدگاه


                            #28
                            پاسخ : مشکل در وقفه سریال

                            نوشته اصلی توسط artison
                            خب حالا به نظر شما من وقتی میخوام بگم دور موتور من بشه 55 ، این که دو رقمه ! پس چطور برنامه بفهمه داده جدید رسیده ؟
                            خیلی ساده هست ! شما وقتی قرار دادتون 5 تایی هست 55 رو هم بصورت 00055 میفرستید تا بشه 5 تا :rolleyes:
                            وقتی شما از دستورات توابع انواع get استفاده میکنید در حقیقت همین کار خواندن بافر UDR رو انجام میدید اما چون برنامه شما متوقف شده و منتظر دریافت اطلاعات میمونه ، تصور میکنید کار باهش راحت تره و مطمئن تره
                            اینم از توضیحات ساده اینتراپت سریال ....خسته نباشید :job:
                            اگر سوالی داشتید بپرسید تا بعدش کد رو پیچیده تر کنیم :bye


                            دوست عزیز من یک کلام میخوام بفهمم چرا وقتی یه اریه رو تووقفه پر میکنم دیگه تو برنامه gets درست کار نمیکنه
                            من فقط تو حلقه اصلی برنامم نمیخوام پشت get بمونم و بقیه جا ها برام مشکلی نداره و میخوام بقیه جاها از gets استفاده کنم
                            لطفا فقط جواب همین یه سوالو بده :angry:

                            دیدگاه


                              #29
                              پاسخ : مشکل در وقفه سریال

                              دوست عزیز شما چرا توجه نمی کنید دقیقا توی قسمتی که از من نقل قول کردید جواب دادم
                              وقتی شما از دستورات توابع انواع get استفاده میکنید در حقیقت همین کار خواندن بافر UDR رو انجام میدید
                              gets همین کاری رو میکنه که اینتراپت میکنه پس یا بایداز اینتراپت استفاده کنید یا gets
                              به عبارت دیگه وقتی شما توی وقفه اطاعات رو گرفتید ، دوباره که اطلاعاتی نمیمونه که بتونید بگیریدش
                              Don't hesitate to ask any question ..

                              دیدگاه


                                #30
                                پاسخ : مشکل در وقفه سریال

                                نوشته اصلی توسط artison
                                دوست عزیز شما چرا توجه نمی کنید دقیقا توی قسمتی که از من نقل قول کردید جواب دادم
                                وقتی شما از دستورات توابع انواع get استفاده میکنید در حقیقت همین کار خواندن بافر UDR رو انجام میدید
                                gets همین کاری رو میکنه که اینتراپت میکنه پس یا بایداز اینتراپت استفاده کنید یا gets
                                به عبارت دیگه وقتی شما توی وقفه اطاعات رو گرفتید ، دوباره که اطلاعاتی نمیمونه که بتونید بگیریدش
                                دوست عزیز من یه شرط گزاشتم و با صفر و یک کردن یک متغیر توی وقفه یه کاری کردم که هر وقت تو برنامم خواستم از gets استفاده کنم دیگه توی وقفه اطلاعاترو توی اون ارایه نریزه ولی باز هم نشد

                                دیدگاه

                                لطفا صبر کنید...
                                X