STM Урок 123. LAN87XX. LWIP. NETCONN. UDP. Соединяем три контролера. Часть 2

В предыдущей части нашего урока мы настроили проект для сервера, а также создали и написали проект для первого клиента и проверили работу соединения на практике.

 

Теперь поработаем со вторым клиентом. В качестве него будет ещё одна плата STM32F746G-DISCOVERY.

Отключим плату нашего первого клиента от ПК и подключим к независимому источнику, а плату 32F746G-DISCOVERY подключим к ПК, ну и. соответственно, также и к нашей сети (нажмите на картинку для увеличения изображения)

 

 

Проект для второго клиента мы создадим из проекта сервера, так как платы одни и те же. А имя данному проекту мы присвоим LAN8742_UDP_CLIENT_NETCONN. От проекта для первого клиента имя данного проекта отличается циферкой в маркировке микросхемы.

Запустим наш проект в Cube MX и перейдём в Configuration. Настроим сначала MAC-адрес в конфигурации сетевого интерфейса. Данные адреса не могут быть одинаковыми в одной сети

 

 

Теперь зайдём в LWIP и немного поменяем сетевой адрес

 

 

Сгенерируем проект, откроем его в System Workbench, настроим уровень оптимизации в 1, удалим при наличии отладочные настройки. Также закомментируем неизвестные компилятору две строки, касающиеся DMA2D, попробуем собрать проект.

Если всё нормально, то начнём потихоньку преобразовывать сервер в клиент.

Первым делом — оформление экрана

 

TFT_DisplayString(0, 10, (uint8_t *)"UDP Client", CENTER_MODE);

 

 

Удалим глобальную структуру, предназначенную для сокета

 

typedef struct struct_sock_t {

  uint16_t y_pos;

  uint16_t port;

} struct_sock;

 

Также удалим и переменные данной структуры

 

struct_sock sock01, sock02;

 

Вместо этого добавим структуру для соединения и создадим переменную данной структуры

 

  } struct_out;

typedef struct struct_conn_t {

  uint32_t conn;

  uint32_t buf;

} struct_conn;

struct_conn conn01;

 

Из функции задачи соединения udp_thread удалим пока всё тело.

 

 

Добавим над этой функцией функцию передачи пакета, полностью аналогичную той, которую мы написали в проекте для первого клиента

 

//---------------------------------------------------------------

static void send_thread(void *arg)

{

  struct_conn *arg_conn;

  struct_out *qstruct;

  struct netconn *conn;

  struct netbuf *buf;

  uint32_t syscnt = 0;

  arg_conn = (struct_conn*) arg;

  conn = (void*)arg_conn->conn;

  for(;;)

  {

    syscnt = osKernelSysTick();

    buf = netbuf_new();

    netbuf_alloc(buf, 4);

    pbuf_take(buf->p, (void *) &syscnt, 4);

    netconn_send(conn,buf);

    netbuf_delete(buf);

    qstruct = osMailAlloc(strout_Queue, osWaitForever);

    qstruct->y_pos = 60;

    sprintf(qstruct->str,"%16lu",syscnt);

    osMailPut(strout_Queue, qstruct);

    osMailFree(strout_Queue, qstruct);

    osDelay(1000);

  }

}

//---------------------------------------------------------------

 

Также ниже функции udp_thread добавим функцию обратного вызова, реагирующую на приём пакетов, также полностью аналогичную той, которую мы использовали в первом клиенте

 

//---------------------------------------------------------------

void udp_receive_callback(struct netconn* conn, enum netconn_evt evt, u16_t len)

{

  struct_out *qstruct;

  uint32_t syscnt;

  unsigned short port;

  err_t recv_err;

  struct netbuf *buf;

  if(evt==NETCONN_EVT_RCVPLUS)

  {

    recv_err = netconn_recv(conn, &buf);

    if (recv_err == ERR_OK)

    {

      port = netbuf_fromport(buf);

      qstruct = osMailAlloc(strout_Queue, osWaitForever);

      qstruct->y_pos = 100;

      syscnt = *(uint32_t*) buf->p->payload;

      sprintf(qstruct->str,"%5u %7lu", port, syscnt);

      osMailPut(strout_Queue, qstruct);

      osMailFree(strout_Queue, qstruct);

      netbuf_delete(buf);

    }

  }

}

//---------------------------------------------------------------

 

Создадим прототип для данной функции

 

void TaskStringOut(void const * argument);

void udp_receive_callback(struct netconn* conn, enum netconn_evt evt, u16_t len);

 

Теперь добавим тело нашей функции, также аналогичное телу функции проекта первого клиента

 

static void udp_thread(void *arg)

{

  err_t err;

  struct netconn *conn;

  ip_addr_t DestIPaddr;

  TFT_SetTextColor(LCD_COLOR_BLUE);

  conn = netconn_new_with_callback(NETCONN_UDP,udp_receive_callback);

  IP4_ADDR(&DestIPaddr, 192, 168, 1, 191);

  if (conn!= NULL)

  {

    err = netconn_bind(conn, NULL, 1551);

    if (err == ERR_OK)

    {

      err = netconn_connect(conn, &DestIPaddr, 8);

      if (err == ERR_OK)

      {

        conn01.conn = conn;

        sys_thread_new("send_thread1", send_thread, (void*)&conn01, DEFAULT_THREAD_STACKSIZE, osPriorityNormal );

      }

    }

    else

    {

      netconn_delete(conn);

    }

  }

  for(;;)

  {

    osDelay(1);

  }

}

 

Из функции задачи по умолчанию  удалим весь пользовательский код до бесконечного цикла и добавим создание задачи для соединения

 

/* USER CODE BEGIN 5 */

sys_thread_new("udp_thread1", udp_thread, NULL, DEFAULT_THREAD_STACKSIZE, osPriorityNormal );

/* Infinite loop */

 

Соберём код, прошьём контроллер и посмотрим результат (нажмите на картинку для увеличения изображения)

 

 

Всё у нас отлично передаётся и принимается. Независимо друг от друга работают два соединения UDP.

Таким образом, сегодня мы создали клиент UDP с применением операционной системы FreeRTOS и интерфейса NETCONN, а также испытали его на двух различных платах, причём в работе одновременно обоих клиентов.

Всем спасибо за внимание!

 

 

 

Исходный код сервера

Исходный код первого клиента

Исходный код второго клиента

 

 

Отладочную плату можно приобрести здесь STM32F746G-DISCOVERY

Отладочную плату можно приобрести здесь STM32F4-DISCOVERY

Модуль LAN можно приобрести здесь: LAN8720

Плату расширения можно приобрести здесь: STM32F4DIS-BB

Дисплей LCD 16×2

Переходник I2C to LCD можно приобрести здесьI2C to LCD1602 2004

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

STM LAN87XX. LWIP. NETCONN. UDP. Соединяем три контролера

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

STM LAN87XX. LWIP. NETCONN. UDP. Соединяем три контролера

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*