STM Урок 71. LAN. ENC28J60. ARP. Часть 2



 

Урок 71

 

Часть 2

 

LAN. ENC28J60. ARP

 

В предыдущей части урока мы настроили проект, поправили ошибки прошлого занятия, вынесли функции реализации протокола ARP в отдельный модуль и создали обработчик прерываний USART на приём.

 

Теперь начнём обрабатывать результат, своевременно меняя все статусы, и в конце вызовем приём из USART

 

  b = str[0];

  //если вдруг случайно превысим длину буфера

  if (usartprop.usart_cnt>20)

  {

    usartprop.usart_cnt=0;

  }

  else if (b == 'a')

  {

    usartprop.is_ip=1;//статус отрпавки ARP-запроса

  }

  else

 {

    usartprop.usart_buf[usartprop.usart_cnt] = b;

    usartprop.usart_cnt++;

  }

  HAL_UART_Receive_IT(&huart1,(uint8_t*)str,1);

}

 

Я думаю, тут и объяснять нечего, так всё ясно. То что строк много, это ничего, я просто везде использовал фигурные скобки независимо от количества строк кода, так как пока мы работаем только с ARP, а в последствии, я думаю подтянутся другие протоколы, соответственно появятся статусы и нам не придется ничего добавлять, то есть для простоты написания будущего кода. А символ «a» мы отслеживаем для того, что введенную строку мы будем им заканчивать, чтобы как-то отследить окончание данной строки. То есть мы будем в терминале вводить IP-адрес устройства, MAC-адрес которого мы хотим узнать.

Теперь отловим изменение статуса в функции net_poll, создав в ней для начала локальный четырехэлементный массив

 

uint16_t len;

uint8_t ip[4]={0};

 

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

 

    eth_read(frame,len);

  }

  if (usartprop.is_ip==1) //статус отправки ARP-запроса

  {

    HAL_UART_Transmit(&huart1,usartprop.usart_buf,usartprop.usart_cnt,0x1000);

    HAL_UART_Transmit(&huart1,(uint8_t*)"\r\n",2,0x1000);

    usartprop.is_ip = 0;

    usartprop.usart_cnt=0;

  }

}

 

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

Давайте соберём код, прошьём контроллер и попробуем что-то ввести в терминальную программу

 

image00

 

Как видим, у нас всё получилось. Мы вводим на данный момент ip-адрес нашего ПК или какой-то другой и получаем его в нашей программе в виде строки.

Но запрос ARP посылать мы пока не сможем, так как нам теперь нужно из строки преобразовать данный адрес в четырехэлементный беззнаковый целочисленный массив.

 

 

Для этого добавим в этом же модуле соответствующую функцию где-то над функцией eth_read, добавив в неё сразу несколько локальных переменных. Результат функции будет записываться по адресу ipextr

 

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

//функция преобразования строкового значения IP в 32-битное числовое

void ip_extract(char* ip_str,uint8_t len, uint8_t* ipextr)

{

  uint8_t offset = 0;

  uint8_t i;

  char ss2[5] = {0};

  char *ss1;

  int ch = '.';

}

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

 

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

 

int ch = '.';

for(i=0;i<3;i++)

{

  ss1 = strchr(ip_str,ch);

}

 

Опять мы используем новую интересную функцию, которая следит за вхождением символа в строке, добавленной в качестве первого аргумента, а затем возвращает адрес в памяти вхождения данного символа. Только нам удобнее работать не с адресом а со смещением относительно начала строки с IP-адресом, поэтому вычислим это смещение

 

ss1 = strchr(ip_str,ch);

offset = ss1-ip_str+1;

 

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

 

offset = ss1-ip_str+1;

strncpy(ss2,ip_str,offset);

ss2[offset]=0;

 

 

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

 

ss2[offset]=0;

ipextr[i] = atoi(ss2);

 

Далее мы соответствующим образом сдвинем указатели нашей строки с IP-адресом и длины этой строки, а затем выйдем из цикла for

 

  ipextr[i] = atoi(ss2);

  ip_str+=offset;

  len-=offset;

}

 

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

 

    len-=offset;

  }

  strncpy(ss2,ip_str,len);

  ss2[len]=0;

  ipextr[3] = atoi(ss2);

}

 

Продолжим писать тело функции net_pool, используя вышенаписанную функцию, вставив код в соответствующее место в этой функции, также здесь мы выведем результат нашей функции в порт USART в целях проверки правильности написания кода вышенаписанной функции

 

HAL_UART_Transmit(&huart1,(uint8_t*)"\r\n",2,0x1000);

ip_extract((char*)usartprop.usart_buf,usartprop.usart_cnt,ip);

sprintf(str1,"%d.%d.%d.%d\r\n", ip[0],ip[1],ip[2],ip[3]);

HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);

 

Давайте это проверим, собрав код и прошив контроллер и затем введя такую же строку, какую и вводили, в терминальной программе

 

image01

 

Функция прекрасно работает.

 

Теперь перейдём в файл arp.с и начнём писать там функцию отправки ARP-запроса, так как для этого у нас теперь всё готово

 

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

uint8_t arp_request(uint8_t *ip_addr)

{

  uint8_t i;

 

  return 1;

}

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

 

Добавим прототип этой функции и вызовем её в net.c в функции net_pool. Вызов функции напишем вместо отправки ip-адреса в USART, он нам там уже не нужен, так как это была просто проверка работы функции преобразования строкового значения IP-адреса в целочисленный массив

 

sprintf(str1,"%d.%d.%d.%d\r\n", ip[0],ip[1],ip[2],ip[3]);

HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);

arp_request(ip);

 

Также зайдём в файл net.h и добавим там макросы для нулевого и широковещательного MAC-адресов

 

#define IP_ADDR {192,168,1,197}

#define MAC_BROADCAST {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}

#define MAC_NULL {0x00,0x00,0x00,0x00,0x00,0x00}

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

 

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

 

 

Предыдущий урок Программирование МК STM32 Следующая часть

 

 

Техническая документация:

Документация на микросхему ENC28J60

Перечень ошибок ENC28J60 (Errata)

 

 

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

Программатор недорогой можно купить здесь ST-Link V2

Ethernet LAN Сетевой Модуль можно купить здесь ENC28J60 Ethernet LAN Сетевой Модуль.

Переходник USB to TTL можно приобрести здесь ftdi ft232rl

 

 

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

STM LAN. ENC28J60. ARP

 

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

STM LAN. ENC28J60. ARP

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

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

*