Продолжаем работать с протоколом TCP и сегодня мы попытаемся уже созданные нами на прошлых занятиях сервер и клиент соединить между собой и научить их обмениваться данными. Думаю, такой урок может пригодиться в будущем, так как зачастую приходится соединять контроллеры между собой, не прибегая вообще к участию в сети компьютеров.
Начнём с сервера.
Проект для сервера создадим на основе проекта урока 124 LAN8742_TCP_SERVER_NETCONN и дадим ему имя немного другое — LAN8742_TCP_SERVER, чтобы наши проекты из разных занятий хоть как-то различались по именам.
Откроем наш проект в Cube MX и, ничего абсолютно в нём не трогая, сгенерируем проект для System Workbench и откроем его там. Установим уровень оптимизации в 1, уберём при наличии отладочные настройки и закомментируем неизвестные компилятору строки в файле main.c.
Попробуем собрать проект и начнём работать с файлом main.c.
Передавать мы будем уже не строку, а 32-битную величину, поэтому в связи с этим немного придётся переделать код.
Перейдём в функцию задачи соединения tcp_thread и объявим там переменную для хранения количества прошедших системных квантов с момента включения или перезагрузки контроллера, эта же переменная будет служить для хранения аналогичных данных, которые придут с клиента
struct_sock *arg_sock;
uint32_t syscnt = 0;
В этой же функции, после того, как мы забрали содержимое буфера приёма в наш локальный буфер, чтобы не запутаться, удалим весь код до конца тела условия. То есть там останется только вот это
if (recv_err == ERR_OK)
{
netbuf_data(inbuf, (void**)&buf, &buflen);
}
Остальной код мы сейчас допишем.
Сначала освободим память буфера, иначе он в один прекрасный момент перестанет принимать данные
netbuf_data(inbuf, (void**)&buf, &buflen);
netbuf_delete(inbuf);
Если длина буфера больше 1, то заберём 32-битную величину из локального буфера
netbuf_delete(inbuf);
if(buflen>1)
{
syscnt = *(uint32_t*) buf;
}
Отобразим величину на дисплее с помощью очереди
syscnt = *(uint32_t*) buf;
qstruct = osMailAlloc(strout_Queue, osWaitForever);
qstruct->y_pos = arg_sock->y_pos;
sprintf(qstruct->str,"%10lu",syscnt);
osMailPut(strout_Queue, qstruct);
Узнаем количество прошедших системных квантов и присвоим их значение переменной
osMailPut(strout_Queue, qstruct);
syscnt = osKernelSysTick();
Отправим данное количество клиенту и немного подождём
syscnt = osKernelSysTick();
netconn_write(newconn, (void *) &syscnt, 4, NETCONN_COPY);
osDelay(1);
На дисплее чуть ниже отобразим также и эту величину, а затем освободим память очереди
osDelay(1);
qstruct->y_pos = arg_sock->y_pos + 40;
sprintf(qstruct->str,"%10lu",syscnt);
osMailPut(strout_Queue, qstruct);
osMailFree(strout_Queue, qstruct);
Соберём код, прошьём контроллер, потому что вроде бы мы с сервером уже закончили.
Соответственно мы кроме шапки не увидим ничего, так как у нас пока нет клиента.
Поэтому отсоединим нашу плату от компьютера и подадим к ней независимое питание, а с компьютером соединим плату клиента. Также можно уже соединить платы между собой сетевым кабелем.
Проект для клиента создадим на остнове проекта прошлого урока LAN8742_TCP_CLIENT_NETCONN и назовём её просто LAN8742_TCP_CLIENT.
Также откроем наш проект в Cube MX и, ничего в нём не трогая, сгенерируем проект для System Workbench и откроем его там. Установим уровень оптимизации в 1, уберём при наличии отладочные настройки и закомментируем неизвестные компилятору строки для видеоускорителя в файле main.c.
Попробуем собрать проект и начнём работать с файлом main.c.
В функции задачи по умолчанию StartDefaultTask исправим IP-адрес сервера
IP4_ADDR(&ServerIPaddr, 192, 168, 1, 191);
Порт клиента будет также другим
err = netconn_bind(conn, NULL, 1555);
Также изменится и порт сервера
err = netconn_connect(conn, &ServerIPaddr, 80);
Перейдём в функцию задачи отправки пакетов send_thread и удалим вот эту часть кода
if(syscnt>50000)
{
netconn_close(conn);
netconn_delete(conn);
qstruct = osMailAlloc(strout_Queue, osWaitForever);
qstruct->y_pos = 160;
strcpy(qstruct->str,"Connection was closed!");
osMailPut(strout_Queue, qstruct);
osMailFree(strout_Queue, qstruct);
osDelay(2);
break;
}
sprintf(buf,"%lu\r\n",syscnt);
Строковый буфер нам здесь также будет не нужен
uint32_t syscnt = 0;
char buf[15] = {};
Исправим аргументы в вызове функции отправки данных
sent_err = netconn_write(conn, (void *) &syscnt, 4, NETCONN_COPY);
Удалим вот это
buf[strlen(buf)-2]=0;
strcpy(qstruct->str,buf);
Вместо этого строку для дисплея сформируем вот так
qstruct->y_pos = 60;
sprintf(qstruct->str,"%10lu",syscnt);
Мы уже можем проверить как у нас идёт передача с клиента на сервер.
Соберём код, прошьём контроллер и посмотрим показания на дисплеях узлов нашей сети. Возможно после прошивки придётся перезагрузить сервер и клиент
Отлично!
Данные передаются, также данные уже принимаются клиентом с сервера, просто некорректно отображаются в нижней строке.
Сейчас мы это исправим.
Перейдём в функцию задачи приёма пакетов recv_thread и объявим там также 32-битную переменную
u16_t buflen;
uint32_t syscnt = 0;
В теле условия вменяемости величины буфера заберём данные из локального буфера в нашу переменную
if(buflen>1)
{
syscnt = *(uint32_t*) buf;
Удалим в этом же теле всё вот это
strncpy(str_buf,(char*)buf,buflen);
str_buf[buflen-1]=0;
sprintf(qstruct->str,"%-20s", str_buf);
И вместо этого сформируем строку для дисплея вот так
qstruct->y_pos = 100;
sprintf(qstruct->str,"%10lu",syscnt);
Вроде бы всё.
Соберём код, перезагрузим сервер, прошьём контроллер клиента и посмотрим результат обмена на дисплеях наших соединённых плат
Всё передаётся и принимается.
Итак, в данном уроке нам удалось соединить между собой два контроллера по сети LAN посредством использования интерфейса NETCONN стека протоколов LWIP, а также организовать между ними обмен данными.
Всем спасибо за внимание!
Предыдущий урок Программирование МК STM32 Следующий урок
Отладочную плату можно приобрести здесь 32F746G-DISCOVERY
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий