Новичок
Регистрация: 28.07.2015
Сообщений: 1
Репутация: 10
|
День добрый, есть система которая должна получать команды в байтовом формате по ethernet и при необходимости в байтовом же формате передавать какой-то ответ, опять же по ethernet.
В качестве базового котнроллера Arduino UNO, в качестве ethernet shield контроллер на базе ENC28j60. Если делать на W5100, то там поставленная задача решается просто, например вот так EthernetClient client = server.available(); if (client.available()>0) { serial_data=client.read(); if (serial_data==3) server.write('1'); Но на руках есть именно ENC28j60. Так что комментарии типа забей и возьми W5100 не конструктивны Для чипа ENC28j60 использовал разные библиотеки в итоге заработала только EherCard, взятая с github, причем старая версия от 2014 года. С остальными библиотеками столкнусля с ошибками на стадии компиляции примеров (среда arduino ide 1.6.5 с оф сайта) причина их не понятна, но не в этом суть. От сетей я довольно далек поэтому после нескольких дней копания библиотеки и чтения форумов не смог ничего придумать на замену примера выше. Почти все примеры имеют отношение к общению через веб. У меня задача другая, открываю какой-либо порт и из приложения кидаю команды, представляющие собой числа в hex объемом 1 байт, arduino их принимает, что-то делает и если надо отвечает через этот же порт в приложение каким-то числом в такой же форме. Смотрел видео Осипова https://www.youtube.com/watch?v=PPB2Xvubt4s https://www.youtube.com/watch?v=RgJnYsTmM5A но то что нужно я там не нашел Я хочу забирать из ТСР пакета байт 0х0036, выделен черным. Как мне казалось можно использовать конструкции как у Осипова типа word len = ether.packetReceive(); word pos = ether.packetLoop(len); if (pos){ Serial.println(pos); bfill = ether.tcpOffset(); char *data = (char *) Ethernet::buffer + pos; if (strncmp("T", data, 1) != 0) { //сравниваем первый значащий символ в полученном пакете Serial.println('1'); } else {Serial.println('2');} } Serial здесь для отладки стоят. В результате в мониторе пусто. то есть даже нет захода в первое условие. Погонял через Wireshark скетч Осипова с выводом содержимого pos в монитор, получил следующую статистику, при нажатии кнопки на странице происходит отправка 10 ТСР пакетов, а в монитор выводится два раза число 54. После анализа содержимого переданных пакетов первая мысль pos - содержит первый байт передаваемых данных в пакете, так как пакеты с данными (их всего два из 10) содержали число "54" но по адресу 0х0038, так как по идее данные должны начинаться с адреса 0х0036, этот вариант был отвергнут, перевел адрес 0х0036 в десятичную систему получил искомое "54", то есть адрес первого байта полезных данных. Начал эксперементировать с участком кода,приведенным выше и о чудо получил ответ, но опять странный. Ответ появляется только если я отправляю больше 8-ми байт данных. И похоже получил подтверждение что приходит в pos адрес первого байта полезных данных. Потому что в коде нет функции подтверждения о получении пакета и с ПК он шлется несколько раз, сколько отправит столько и сообщений в мониторе. Пока писал это сообщение на часть вопросов уже сам нашел ответ, но не факт что правильный, поэтому небольшой итог По функциям: word len = ether.packetReceive(); //как описано в библиотеке копирует принятые данные в буфер и возвращает длину пакета данных word pos = ether.packetLoop(len); //как описано в библиотеке анализирует полученные данные определенной длины, возвращает адрес смещения полезных данных в пакете или ноль, если ничего нет или служебные данные, как выяснилось также возвращает ноль если длина данных меньши восьми байт. Погружаясь глубже в библиотеку нашел участок кода этой функции в файле tcpip.cpp if (tcp_client_state==3 && len>0) { //TCP connection established so read data if (client_tcp_result_cb) { uint16_t tcpstart = TCP_DATA_START; // TCP_DATA_START is a formula if (tcpstart>plen-8) tcpstart = plen-8; // dummy but save uint16_t save_len = len; if (tcpstart+len>plen) save_len = plen-tcpstart; (*client_tcp_result_cb)((gPB[TCP_DST_PORT_L_P]>>5)&0x7,0,tcpstart,save_len); //Call TCP handler (callback) function Мне кажется ответ про восемь байт скрыт где-то здесь, особые подозрения вызывает последняя строчка, но не могу понять что в ней происходит, кто-нибудь может подсказать? и вопрос вызывает tcpstart, как она вычисляется, формулу то я нашел, но что в ней происходит не очень понял: TCP_DATA_START ((uint16_t)TCP_SRC_PORT_H_P+(gPB[TCP_HEADER_LEN_P]>>4)*4) Ну и еще один вопрос как работать с функцией вывода bfill.emit_p(), как выбрать параметры чтобы отправить один байт? А также как отправить подтверждение о получении ТСР пакета, а то клиент кидает 6-7 пакетов в ожидании ответа, а потом разрывает соединение? Заранее спасибо! |
||
Оценка
|
Новичок
Регистрация: 14.06.2018
Сообщений: 112
Репутация: 17
|
В каждой библиотеке, где обмен ведется пакетами, должна быть функция flash - опорожение буфера до его заполнения.
xxx.writeOneByte (<...>); // запис в буфер, но нет еще передачи xxx.flash (); // передача пакета, независимо насколько заполнен |
||
Оценка
|
Обратная связь РадиоЛоцман Вверх |