اطلاعیه

Collapse
No announcement yet.

ارسال و دریافت دیتا با استفاده از وقفه USART

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

    ارسال و دریافت دیتا با استفاده از وقفه USART

    سلام.
    من یه رشته دیتا دارم که باید بصورت پاکت ارسال بشه و تو هر پاکت دو بایت استارت وجود داره و یه بایت CRC check برای خطایابی. به خاطر همین هم برای ارسال اونها از وقفه ارسال استفاده کردم. کدی که نوشتم به این صورت هست:
    کد:
    void comm_send(unsigned char ID,unsigned int par){
      char sum = 0;
      int i;
      
    #define COMM_SIZE 5
      char tx_buff[COMM_SIZE];
      unsigned char chksum;
      unsigned char *para = 0x00;
      
      tx_buff[0] = 0xAA;
      tx_buff[1] = 0x55;
      tx_buff[2] = ID;
      itoa(par,para);
      tx_buff[3] = *para;
      for (i=2;i<=3;i++){
        sum += tx_buff[i];
        chksum = -(sum+1);
      }
      tx_buff[4] = chksum;
      for (i=0;i<COMM_SIZE;i++){
        putchar(tx_buff[i]);
      }
    }

    اون 0xAA و 0x55 فلگ های ارسال هستن، و ID و par (و ایضاً para) هم پارامترهای دیگه این پاکت هستند. خودم فکر می کنم که این تابع برای ارسال اشکال داشته باشه، و البته از اونجائیکه دستگاه گیرنده dumb هست و هیچ گونه علائمی رو اصولاً از خودش بروز نمیده نمی تونم بفهمم درسته یا نه.
    این هم تابع برای دریافت اطلاعات:

    کد:
    void data_recv(void){
      
      getchar();
      if(rx_buffer[0] != 0xAA){
        lcd_gotoxy (0,1);
        lcd_putsf("step1");
        if(rx_buffer[1] == 0x55){
          lcd_gotoxy (7,1);
          lcd_putsf("step2");
        }
      }
    }

    البته این تابع فقط برای امتحان هست که می خوام ببینم آیا دستگاه اصلاً چیزی می فرسته به من یا نه. که البته جوابی ازش نمیاد.

    اگر هر کدوم از این تابع ها اشکال داره خوشحال میشم کمک کنید.
    دانش فني تا به عمل تبديل نشده، ذره اي ارزش نداره. اما بعضي وقت ها بايد از دانش براي باز کردن مرزهاي جديدي در علم استفاده کرد، نه اينکه اونها رو صرفاً فقط به عمل تبديل کرد.

    #2
    پاسخ : ارسال و دریافت دیتا با استفاده از وقفه USART

    با سلام

    1-
    برای آزمون فعالیت پورت سریال ( خروجی )
    مدار زیر را بسازید و بین TXD , GND وصل کنید.( چه TTL و چه +-10 ولت ... کاربرد دارد )
    در حالتی که خروجی فعال نباشد، یکی از ال وی دی ها روشن و دیگری خاموش است.
    در هنگام ارسال دیتا ( به خصوص اگر دیتا مستمر ارسال شود ) ال ئی دی ها چشمکزن بی نظم خواهند شد.

    2- برنامه فرستنده،
    بخش آماده سازی بافر دیتا برای ارسال که درست به نظر می رسد.
    بخش :
    for (i=0;i<COMM_SIZE;i++){
    putchar(tx_buff[i]);
    }

    باید اولا تنظیمات پورت سریال برای ارسال و فعال سازی صورت گرفته باشد.
    ضمنا در باره اینتراپت ، چیزی ننوشته اید، !

    معمولا در برنامه های ساده، putchar(tx_buff[i]); همه کارها شامل چک نمودن آمادگی برای ارسال + قرار دادن دیتا در رجیستر ارسال + انتظار برای پایان ارسال یک بایت را
    انجام می دهد.( با روتین اختصاصی متناسب با هر میکرو و کمپایلر - اگر روتین اختصاصی ارسال تک بایت ندارد، باید بنویسید.)

    ////////////////////////
    3-
    در بخش دریافت،
    معمولا getchar(); بایت در یافتی را به عنوان خروجی بازمی گرداند،
    شما باید 4 بایت را در یک حلقه انتظار، دریافت کرده و در یک بافر ذخیره کنید.
    شمارنده حلقه زمانی شروع می کند که 0XAA را دریافت کند به عنوان شروع.
    ( بدون مشغول شدن میکرو به روتینهای وقتگیر ال سی دی - چون دریافت از پورت سریال و پر شدن بافر، باید مرتبا کنترل شود تا سرریز رخ ندهد و اطلاعات کسر نشود.)
    پس از دریافت 4 بایت کامل، می توانید در ال سی دی نشان دهید.

    با سپاس
    فایل های پیوست شده
    گشتی در لاله زار
    http://www.eca.ir/forum2/index.php?topic=76138.0

    http://www.eca.ir/forum2/index.php?topic=76141

    دیدگاه


      #3
      پاسخ : ارسال و دریافت دیتا با استفاده از وقفه USART

      نوشته اصلی توسط Solsal
      1-
      برای آزمون فعالیت پورت سریال ( خروجی )
      مدار زیر را بسازید و بین TXD , GND وصل کنید.( چه TTL و چه +-10 ولت ... کاربرد دارد )
      در حالتی که خروجی فعال نباشد، یکی از ال وی دی ها روشن و دیگری خاموش است.
      در هنگام ارسال دیتا ( به خصوص اگر دیتا مستمر ارسال شود ) ال ئی دی ها چشمکزن بی نظم خواهند شد.
      نه، پورت سریال سالمه. دیتا رو میفرسته. مساله ای که گفتم اینه که ماژول معلوم نیست اینها رو درست میگیره یا نه.

      نوشته اصلی توسط Solsal
      2- برنامه فرستنده،
      بخش آماده سازی بافر دیتا برای ارسال که درست به نظر می رسد.
      بخش :
      for (i=0;i<COMM_SIZE;i++){
      putchar(tx_buff[i]);
      }

      باید اولا تنظیمات پورت سریال برای ارسال و فعال سازی صورت گرفته باشد.
      ضمنا در باره اینتراپت ، چیزی ننوشته اید، !

      معمولا در برنامه های ساده، putchar(tx_buff[i]); همه کارها شامل چک نمودن آمادگی برای ارسال + قرار دادن دیتا در رجیستر ارسال + انتظار برای پایان ارسال یک بایت را
      انجام می دهد.( با روتین اختصاصی متناسب با هر میکرو و کمپایلر - اگر روتین اختصاصی ارسال تک بایت ندارد، باید بنویسید.)
      تنظیمات پورت سریال و فعال سازی انجام شده. این هم کد وقفه و تابع putchar:
      کد:
      // USART Transmitter buffer
      #define TX_BUFFER_SIZE 62
      char tx_buffer[TX_BUFFER_SIZE];
      
      #if TX_BUFFER_SIZE<256
      unsigned char tx_wr_index,tx_rd_index,tx_counter;
      #else
      unsigned int tx_wr_index,tx_rd_index,tx_counter;
      #endif
      
      // USART Transmitter interrupt service routine
      interrupt [USART_TXC] void usart_tx_isr(void)
      {
      if (tx_counter)
        {
        --tx_counter;
        UDR=tx_buffer[tx_rd_index];
        if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
        };
      }
      
      #ifndef _DEBUG_TERMINAL_IO_
      // Write a character to the USART Transmitter buffer
      #define _ALTERNATE_PUTCHAR_
      #pragma used+
      void putchar(char c)
      {
      while (tx_counter == TX_BUFFER_SIZE);
      #asm("cli")
      if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
        {
        tx_buffer[tx_wr_index]=c;
        if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
        ++tx_counter;
        }
      else
        UDR=c;
      #asm("sei")
      }
      #pragma used-
      #endif

      این تابع معلومه که دیتا رو بصورت بایت به بایت ارسال می کنه. بنابراین فکر میکنم اون بخشی که نوشتید باید درست باشه.

      نوشته اصلی توسط Solsal
      3-
      در بخش دریافت،
      معمولا getchar(); بایت در یافتی را به عنوان خروجی بازمی گرداند،
      شما باید 4 بایت را در یک حلقه انتظار، دریافت کرده و در یک بافر ذخیره کنید.
      شمارنده حلقه زمانی شروع می کند که 0XAA را دریافت کند به عنوان شروع.
      ( بدون مشغول شدن میکرو به روتینهای وقتگیر ال سی دی - چون دریافت از پورت سریال و پر شدن بافر، باید مرتبا کنترل شود تا سرریز رخ ندهد و اطلاعات کسر نشود.)
      پس از دریافت 4 بایت کامل، می توانید در ال سی دی نشان دهید.

      با سپاس
      درسته، getchar مقدار گرفته شده رو در خودش بر می گردونه. اما تابع وقفه و تابع getchar رو ببین:

      کد:
      // USART Receiver buffer
      #define RX_BUFFER_SIZE 62
      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_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
        if (++rx_counter == RX_BUFFER_SIZE)
         {
         rx_counter=0;
         rx_buffer_overflow=1;
         };
        };
      }
      
      #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_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
      #asm("cli")
      --rx_counter;
      #asm("sei")
      return data;
      }
      #pragma used-
      #endif

      اون طوری که روتین وقفه نشون میده، گرفتن دیتا ادامه پیدا می کنه تا:
      کد:
      ++rx_wr_index == RX_BUFFER_SIZE

      بنابراین من بر اساس این حدس زدم که کل دیتا گرفته میشه تا یه پاکت تموم بشه. بنابراین من با فراخوانی getchar حدس زدم که کل یک پاکت گرفته میشه. اما به نظرم باید غلط باشه. درسته؟
      دانش فني تا به عمل تبديل نشده، ذره اي ارزش نداره. اما بعضي وقت ها بايد از دانش براي باز کردن مرزهاي جديدي در علم استفاده کرد، نه اينکه اونها رو صرفاً فقط به عمل تبديل کرد.

      دیدگاه


        #4
        پاسخ : ارسال و دریافت دیتا با استفاده از وقفه USART

        با سلام

        وقفه دریافت، یک بافر حلقوی را مرتبا با دریافتها پر می کند،( با شمارنده اختصاصی خودش rx_wr_index به محل نوشتن اشاره دارد.)

        تابع getchar با شمارنده اختصاصی خودش که سنکرون با بالایی نیست، rx_rd_index ، از بافر ،دریافت،می خواند،

        چون شما 4 بایت دریافت نموده اید،(در صورت دریافت صحیح) در کجای این بافر 64 تایی ذخیره شده؟

        تابع getchar از کجای این بافر 64 تایی می خواند؟

        باید رابطه این دو بخش را به صورت صحیح برقرار کنیم، تا به صورت صحیح همدیگر را تعقیب کنند ،

        این دو : rx_wr_index و rx_rd_index باید از احوال هم خبردار باشند،
        با سپاس
        گشتی در لاله زار
        http://www.eca.ir/forum2/index.php?topic=76138.0

        http://www.eca.ir/forum2/index.php?topic=76141

        دیدگاه


          #5
          پاسخ : ارسال و دریافت دیتا با استفاده از وقفه USART

          نوشته اصلی توسط Solsal
          با سلام

          وقفه دریافت، یک بافر حلقوی را مرتبا با دریافتها پر می کند،( با شمارنده اختصاصی خودش rx_wr_index به محل نوشتن اشاره دارد.)

          تابع getchar با شمارنده اختصاصی خودش که سنکرون با بالایی نیست، rx_rd_index ، از بافر ،دریافت،می خواند،

          چون شما 4 بایت دریافت نموده اید،(در صورت دریافت صحیح) در کجای این بافر 64 تایی ذخیره شده؟

          تابع getchar از کجای این بافر 64 تایی می خواند؟

          باید رابطه این دو بخش را به صورت صحیح برقرار کنیم، تا به صورت صحیح همدیگر را تعقیب کنند ،

          این دو : rx_wr_index و rx_rd_index باید از احوال هم خبردار باشند،
          با سپاس
          نه، 4 بایت گرفته نمیشه. پاکت های ارسالی من 4 بایتی هستن، اما پاکت هایی که می گیرم 32 بایتی هستن، که من بافر گیرنده رو 62 بایت گرفتم تا برای دوتا پاکت کافی باشه. وقفه هم شروع به گرفتن می کنه تا زمانی که دو پاکت کامل دریافت بشه (تا شماره rx_wr_index به 62 برسه) و بعد از اون هم تابع getchar شروع به خوندن از روی همون بافر میکنه تا دو پاکت کامل خونده بشه. بنابراین حداقل باید پاکت اول دیتا رو بتونم درست دریافت کنم. البته این چند روز یه مقدار سرم شلوغ بود، تست می کنم و اگه مشکلی داشت بازم میام خدمتتون
          دانش فني تا به عمل تبديل نشده، ذره اي ارزش نداره. اما بعضي وقت ها بايد از دانش براي باز کردن مرزهاي جديدي در علم استفاده کرد، نه اينکه اونها رو صرفاً فقط به عمل تبديل کرد.

          دیدگاه


            #6
            پاسخ : ارسال و دریافت دیتا با استفاده از وقفه USART

            من یسوال داشتم این که با استفاده از وقفه در گیرنده از میکروی فرستنده یک مقدا رو به صورت عددی گرفتم (فرستنده فقط یک لحظه دیتارو ارسال میکنه) حالا من میخوام با یک کلید مقدار UDR رو صفر کنم تا دفعه بعد که دوباره فرستنده دیتارو ارسال کنه .سوالم اینه که چه جور مقدار UDR رو صفر کنم؟

            دیدگاه


              #7
              پاسخ : ارسال و دریافت دیتا با استفاده از وقفه USART

              کسی نمیدونست چه جوری میشه صفرش کرد

              دیدگاه

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