راه اندازی کتابخانه LWIP با STM32 (بخش سوم)

0

برنامه نویسی سوکت با استفاده از کتابخانه LwIP

در این قسمت با استفاده رابط کاربری Raw کتابخانه LwIP نحوه نوشتن برنامه سوکت بیان شده است. رابط کاربری Raw مبتی بر توابع Callback است. بطوری ­که کاربر توابع متناظر با هر رویداد نظیر دریافت فریم یا رخداد خطا را مشخص می­کند و هسته LwIP  هنگامی که هر یک از رخدادهای موردنظر روی دهد تابع مشخص شده فراخوانی می­شود.

در جدول 1 توابعی که رابط کاربری Raw برای کار با سوکت  TCPدر اختیار برنامه نویس قرار داده است نشان داده شده است.

توابع TCP رابط کاربری Raw
توابع TCP رابط کاربری Raw

در جدول 2 توابع کار با سوکت UDP با رابط کاربری Raw نشان داده شده است.

توابع UDP رابط کاربری Raw
توابع UDP رابط کاربری Raw

مثال اول: سوکت TCP Server

در این بخش با استفاده از رابط کاربری Raw برنامه یک TCP Server توسعه داده داده شده است. در این مثال یک Server به پورت 7 گوش می­دهد و پس از ایجاد لینک، داده­ای که از Client دریافت کرده است را بررسی می­کند. در صورتی که رشته “A” را دریافت کند یک LED را روشن می­کند و اگر “B” دریافت کند LED را خاموش می­کند و همینطور داده دریافتی را مجددا به Client ارسال می­کند.

لازم به ذکر است که چگونگی تنظیم کتابخانه LwIP و پورت Ethernet در قسمت­های قبل بیان شده است. لذا از تکرار آن­ در بخش خودداری شده و فقط مفاهیم مرتبط با برنامه نویسی سوکت بیان شده است.

در این مثال IP بصورت Static تنظیم شده است.

تابع main برنامه بصورت زیر است:

int main(void)
{

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the GPIO PG6 as output */
  MX_GPIO_Init();
  
  /* Configure the ETH port and LwIP library */
  MX_LWIP_Init();
  
  /* initialize TCP Echo Server */
  tcp_echoserver_init();

  while (1)
  {
    MX_LWIP_Process();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 

در تابع tcp_echoserver_init ابتدا یک سوکت TCP تعریف شده است. سپس به پورت هفت Bind شده است و در نهایت با تابع فراخوانی تابع tcp_listen به حالت کاری Listen می­رود و هنگامی­که از هر Client یک درخواست دریافت کرد تابع Callback متناظر با Accept (در اینجا tcp_echoserver_accept) را فراخوانی می­کند. کد تابع tcp_echoserver_init بصورت زیر تعریف شده است.

void tcp_echoserver_init(void)
{
  /* create new tcp pcb */
  tcp_echoserver_pcb = tcp_new();

  if (tcp_echoserver_pcb != NULL)
  {
    err_t err;
    
    /* bind echo_pcb to port 7 (ECHO protocol) */
    err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7);
    
    if (err == ERR_OK)
    {
      /* start tcp listening for echo_pcb */
      tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);
      
      /* initialize LwIP tcp_accept callback function */
      tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);
    }
    else 
    {
      /* deallocate the pcb */
      memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
    }
  }
}
 

لازم به ذکر است که این پروژه ضمیمه گزارش شده است.

نتیجه برنامه TCP Server Socket

در شکل 6 چگونگی نتیجه این مثال نشان داده شده است. در اینجا از نرم افزار Hercules SETUP utility برای تست استفاده شده است. برای تست برنامه ابتدا IP میکروکنترلر که در قسمت Module IP  وارد کرده و سپس بر روی دکمه  Connect  کلیک کنید. لازم به ذکر است که حتما IP کارت شبکه کامپیوتر را بصورتی که در بخش قبل بیان شد، تنظیم شود.

خروجی برنامه TCP Server Socket
خروجی برنامه TCP Server Socket

مثال دوم: سوکت UDP Server

  • در مثال قبل نحوه راه اندازی TCP Server بیان شد. در این مثال نحوه انجام همان کار با استفاده از UDP Server  شرح داده شده است.

    تابع main این برنامه بصورت زیر است:

int main(void)
{

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();


  /* Configure the system clock */
  SystemClock_Config();
  
  /* Configure the GPIO PG6 as output */
  MX_GPIO_Init();
  
  /* Configure the ETH port and LwIP library */ 
  MX_LWIP_Init();
  
  /* initialize UDP Echo Server */
  udp_echoserver_init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    MX_LWIP_Process();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 

در این مثال تابع udp_echoserver_init بصورت زیر تعریف شده است. در این یک سوکت UDP تعریف شده و سپس سوکت را به پورت هفت Bind شده است. udp_recv تابع Call-back دریافت را مشخص می­کند. هنگامی که فریم UDP دریافت شود هسته LwIP تابع udp_echoserver_receive_callback را فراخوانی می­کند.

void udp_echoserver_init(void)
{
   struct udp_pcb *upcb;
   err_t err;
   
   /* Create a new UDP control block  */
   upcb = udp_new();
   
   if (upcb)
   {
     /* Bind the upcb to the UDP_PORT port */
     /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
      err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
      
      if(err == ERR_OK)
      {
        /* Set a receive callback for the upcb */
        udp_recv(upcb, udp_echoserver_receive_callback, NULL);
      }
      else
      {
        udp_remove(upcb);
      }
   }
}
 

تابع udp_echoserver_receive_callback نیز بصورت زیر تعریف شده است.

void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
  struct pbuf *p_tx;
  
  /* allocate pbuf from RAM*/
  p_tx = pbuf_alloc(PBUF_TRANSPORT,p->len, PBUF_RAM);
  
  if(p_tx != NULL)
  {
    pbuf_take(p_tx, (char*)p->payload, p->len);
    /* Connect to the remote client */
    udp_connect(upcb, addr, UDP_CLIENT_PORT);
    
    if (*(uint8_t*)(p_tx->payload) == 'A')
    {
      HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_SET);
    }
    else if (*(uint8_t*)(p_tx->payload) == 'B')
    {
      HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
    }
    /* Tell the client that we have accepted it */
    udp_send(upcb, p_tx);
    
    /* free the UDP connection, so we can accept new clients */
    udp_disconnect(upcb);
    
    /* Free the p_tx buffer */
    pbuf_free(p_tx);

    /* Free the p buffer */
    pbuf_free(p);
  }
}
 

خروجی برنامه UDP Server Socket

  • در شکل 7 خروجی این مثال نشان داده شده است. همانطور که ملاحظه می­کنید میکروکنترلر داده دریافتی را ارسال نموده است
خروجی برنامه UDP Server Socket
خروجی برنامه UDP Server Socket

مشاهده فریم ها با استفاده از نرم افزار Wireshark

Wireshark بهترین نرم افزار آنالیز پروتکل های شبکه است که با استفاده از آن می­توان کلیه فریم­های ورودی و خروجی را مشاهده و آنالیز کرد. در این­جا با استفاده از این نرم افزار فریم­های ارسالی و دریافتی مشاهده شده است. در شکل 8 فریم­هایی که بین کامپیوتر و میکروکنترلر جابجا شده اند نشان داده شده است.

مشاهده فریم های ارسالی و دریافت شده به میکروکنترلر با گذرگاه Ethernet
مشاهده فریم های ارسالی و دریافت شده به میکروکنترلر با گذرگاه Ethernet
Choose your Reaction!
دیدگاه خود را بنویسید

آدرس ایمیل شما منتشر نخواهد شد.

redronic.com