اطلاعیه

Collapse
No announcement yet.

درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt

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

    درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt

    با درود و احترام خدمت همه دوستان و همکاران عزیز. میخام با استفاده از ارتباط سریال یه رشته 10 کارکتری رو دریافت کنم. در حالت عادی و بدون استفاده از وقفه دریافت ارتباط سریال، با دستور gets برنامه به خوبی کار میکنه و هر 10 بایت دیتای ارسالی بدون نقص در گیرنده دریافت میشه ولی چون وقتی میکرو به این دستور میرسه تا زمان دریافت دیتا روی این خط از برنامه متوقف میشه، نمیتونم همزمان سون سگمنتهایی که به میکرو وصل هستن رو رفرش کنم. بنابراین از وقفه دریافت استفاده کردم که متاسفانه این وقفه که با شماره وکتور 12 قابل دسترسی هستش، هر دفعه فقط یک بایت از رشته ارسالی رو دریافت میکنه. لطفا اگر راهکاری به نظرتون میرسه برای دریافت کامل 10 بایت ارائه بفرمایید. از دستورات حلقه و ... استفاده کردم ولی جواب نداد.

    #2
    پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt

    نوشته اصلی توسط soleimani_m نمایش پست ها
    با درود و احترام خدمت همه دوستان و همکاران عزیز. میخام با استفاده از ارتباط سریال یه رشته 10 کارکتری رو دریافت کنم. در حالت عادی و بدون استفاده از وقفه دریافت ارتباط سریال، با دستور gets برنامه به خوبی کار میکنه و هر 10 بایت دیتای ارسالی بدون نقص در گیرنده دریافت میشه ولی چون وقتی میکرو به این دستور میرسه تا زمان دریافت دیتا روی این خط از برنامه متوقف میشه، نمیتونم همزمان سون سگمنتهایی که به میکرو وصل هستن رو رفرش کنم. بنابراین از وقفه دریافت استفاده کردم که متاسفانه این وقفه که با شماره وکتور 12 قابل دسترسی هستش، هر دفعه فقط یک بایت از رشته ارسالی رو دریافت میکنه. لطفا اگر راهکاری به نظرتون میرسه برای دریافت کامل 10 بایت ارائه بفرمایید. از دستورات حلقه و ... استفاده کردم ولی جواب نداد.
    سلام
    استفاده از حلقه و معطل کردن برنامه در سرویس وقفه کار درستی نیست! سرویس وقفه باید تا حد ممکن کوتاه باشه.
    شما کافیه یک بافر و یک متغیر گلوبال تعریف کنید که این متغیر وظیفه شمارش روی بافر رو انجام بده. به این شکل که با هر بار وارد شدن به سرویس وقفه، داده پورت سریال رو داخل بافر و توی خونه ای که اون شمارنده مشخص میکنه کپی کنید و یک واحد شمارنده رو افزایش بدید. به محض این که شمارنده به عدد ۱۰ رسید دوباره صفرش میکنید. فقط باید به وسیله پرچمی به برنامه اصلی اطلاع بدید بافر پر شده.
    برای عملکرد بهتر میتونید از ۲ بافر استفاده کنید. زمانی که برنامه در حال پردازش روی بافر اول هستش سرویس وقفه بافر دوم رو پر کنه و برعکس. مدیریت این عملکرد هم کار زیاد سختی نیست و کمی فکر کنید روش مناسبی براش پیدا میکنید.

    دیدگاه


      #3
      پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt

      نوشته اصلی توسط hossein.m98 نمایش پست ها
      سلام
      استفاده از حلقه و معطل کردن برنامه در سرویس وقفه کار درستی نیست! سرویس وقفه باید تا حد ممکن کوتاه باشه.
      شما کافیه یک بافر و یک متغیر گلوبال تعریف کنید که این متغیر وظیفه شمارش روی بافر رو انجام بده. به این شکل که با هر بار وارد شدن به سرویس وقفه، داده پورت سریال رو داخل بافر و توی خونه ای که اون شمارنده مشخص میکنه کپی کنید و یک واحد شمارنده رو افزایش بدید. به محض این که شمارنده به عدد ۱۰ رسید دوباره صفرش میکنید. فقط باید به وسیله پرچمی به برنامه اصلی اطلاع بدید بافر پر شده.
      برای عملکرد بهتر میتونید از ۲ بافر استفاده کنید. زمانی که برنامه در حال پردازش روی بافر اول هستش سرویس وقفه بافر دوم رو پر کنه و برعکس. مدیریت این عملکرد هم کار زیاد سختی نیست و کمی فکر کنید روش مناسبی براش پیدا میکنید.
      ممنونم از پاسختون مهندس. با قسمت آخر جوابتون خیلی مشکلی ندارم ولی قسمت اول رو درست متوجه نشدم. اگه نمونه برنامه ای دارید ممنون میشم بذارید.
      مشکل اینجاست در حالت بدون وقفه، همه 10 بایت روی یک رشته با دستور gets قرار میگیره اما در حالت وقفه باید 10 بار دیتا رو پشت سر هم ارسال کنم چون هر بار هم فقط یه بایت دربافت میشه. ولی خوب بعد از 10 بار ارسال، رشته مزبور بطور کامل دریافت میشه.
      جدیدترین ویرایش توسط soleimani_m; ۰۰:۲۰ ۱۴۰۰/۰۳/۱۹.

      دیدگاه


        #4
        پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt

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

        unsigned char Counter = 0;
        volatile unsigned char BufferFullFlag = 0;
        unsigned char Buffer[10];


        void ISR_UART(void)
        {
        Buffer[Counter] = UDR;
        Counter++;
        if (Counter == 10)
        {
        Counter = 0;
        BufferFullFlag = 1;
        }
        }


        void main(void)
        {
        // Some code


        while (1)
        {
        if (BufferFullFlag != 0)
        {
        BufferFullFlag = 0;
        // Some code
        }
        }
        }


        اینم یه نمونه کد ساده که متونید ازش الگو بگیرید. فقط حواستون باشه این برنامه در مقابل از دست رفتن داده ها ایمن نیست و قبل از رسیدن بایت 0 ام باید توی برنامه اصلی بافر خالی بشه وگرنه داده ها از بین میرن.

        دیدگاه


          #5
          پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt

          نوشته اصلی توسط hossein.m98 نمایش پست ها
          شما اگر 10 بایت ارسال کنید 10 بار هم وقفه دریافت میکنید.

          unsigned char Counter = 0;
          volatile unsigned char BufferFullFlag = 0;
          unsigned char Buffer[10];


          void ISR_UART(void)
          {
          Buffer[Counter] = UDR;
          Counter++;
          if (Counter == 10)
          {
          Counter = 0;
          BufferFullFlag = 1;
          }
          }


          void main(void)
          {
          // Some code


          while (1)
          {
          if (BufferFullFlag != 0)
          {
          BufferFullFlag = 0;
          // Some code
          }
          }
          }


          اینم یه نمونه کد ساده که متونید ازش الگو بگیرید. فقط حواستون باشه این برنامه در مقابل از دست رفتن داده ها ایمن نیست و قبل از رسیدن بایت 0 ام باید توی برنامه اصلی بافر خالی بشه وگرنه داده ها از بین میرن.
          بازم ممنونم مهندس که وقت گذاشتید. با استفاده از راهنمایی شما و سایر دوستان در انجمن برنامه زیر رو نوشتم که به خوبی جواب داد.
          کد:
          [FONT=Yekan]/*******************************************************[/FONT]Date    : 6/8/2021
          Chip type               : ATmega32A
          AVR Core Clock frequency: 11.059200 MHz
          *******************************************************/
          
          
          #include <mega32a.h>
          #include <alcd.h>
          #include <stdio.h>
          #include <delay.h>
          
          
          #ifndef RXB8
          #define RXB8 1
          #define TXB8 0
          #define UPE 2
          #define DOR 3
          #define FE 4
          #define UDRE 5
          #define RXC 7
          #endif
          
          
          #define DATA_REGISTER_EMPTY (1<<UDRE)
          #define RX_COMPLETE (1<<RXC)
          #define FRAMING_ERROR (1<<FE)
          #define PARITY_ERROR (1<<UPE)
          #define DATA_OVERRUN (1<<DOR)
          
          
          // USART Receiver buffer
          #define RX_BUFFER_SIZE 11
          char rx_buffer[RX_BUFFER_SIZE];
          bit rx_buffer_overflow;
          unsigned char rx_wr_index =0;
          
          
          // 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_wr_index == RX_BUFFER_SIZE)rx_buffer_overflow=1;
              }
           }
          
          
          void main(void)
           {
              DDRB.0=1;
          
          
             // USART initialization
             // Communication Parameters: 8 Data, 1 Stop, No Parity
             // USART Receiver: On
             // USART Transmitter: Off
             // USART Mode: Asynchronous
             // USART Baud Rate: 9600
             UCSRA=0;
             UCSRB=0x90;
             UCSRC=0x86;
             UBRRH=0x00;
             UBRRL=0x47;
          
          
             // Global enable interrupts
             #asm("sei")
          
          
             lcd_init(16);
             lcd_puts("USART Interrupt");
             delay_ms(2000);
             lcd_clear();
             lcd_puts("Receive:");
          
          
          while (1)
           {
             if(rx_buffer_overflow)
              {
                rx_buffer_overflow =0;
                rx_wr_index=0;
                lcd_gotoxy(2,1);
                lcd_puts(rx_buffer);
              }
            
             PORTB.0 =~PORTB.0;
             delay_ms(400);
           }
          [FONT=Yekan]}[/FONT]

          دیدگاه


            #6
            پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt

            برادر عزیز هیچ وقت سون سگمت را در داخل main رفرش نکنید.یعنی تابع نمایش سگمنت هارا در وقفه تایمر صفر یا یک قراربدید.هر وقت تایمر سرریز کرد، در روتین وقفه تایمر صفر پایه هارا رفرش کنید.اینجوری هیچ وقت به مشکل نخواهید خورد.از انجایی که کلاک تایمر مستقیم از واحدمقسم فرکانس تامین میشه همیشه ثابته و همین قابت بودن باعث میشه که شما یک سرعت بسیار خوبی برای رفرش سگمنت ا داشته باشید.
            جدیدترین ویرایش توسط Namvar14; ۰۲:۰۳ ۱۴۰۰/۰۳/۲۰.
            eshop-hodhod.ir

            دیدگاه

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