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

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

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

 

 

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

 

STM LAN. ENC28J60. ARP

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

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

*