Урок 41
Часть 5
LAN. ENC28J60. ARP
В предыдущей части нашего занятия мы написали функцию заполнения таблицы ARP, добавили таймер для счёта времени и проверили наш код на практике.
Давайте теперь, как мы и хотели, вернёмся в функцию ARP-запроса arp_request и пока вставим туда цикл, который будет перебирать записи по отысканию существующего IP-адреса
uint8_t i;
//проверим, может такой адрес уже есть в таблице ARP, а заодно и удалим оттуда просроченные записи
for(i=0;i<5;i++)
{
}
В тело цикла добавим условие
for(i=0;i<5;i++)
{
//Если записи уже более 12 часов, то удалим её
if ((clock_cnt-arp_rec[i].sec)>43200)
{
memset(arp_rec+(sizeof(arp_record_ptr)*i),0,sizeof(arp_record_ptr));
}
}
Из коментария вполне ясно, что мы здесь проделали. Мы забили нулями всю память отведённую под запись.
Теперь после этого условия добавим следующее, после выполнения тела условия (не цикла)
memset(arp_rec+(sizeof(arp_record_ptr)*i),0,sizeof(arp_record_ptr));
}
if (arp_rec[i].ipaddr==ip_addr)
{
return 0;
}
В теле данного условия перед тем, как нам выйти из функции с помощью return 0, мы посмотрим нашу таблицу
if (arp_rec[i].ipaddr==ip_addr)
{
//смотрим ARP-таблицу
for(i=0;i<5;i++)
{
sprintf(str1,"%ld.%ld.%ld.%ld - %02X:%02X:%02X:%02X:%02X:%02X - %lu\r\n",
arp_rec[i].ipaddr & 0x000000FF,(arp_rec[i].ipaddr>>8) & 0x000000FF,
(arp_rec[i].ipaddr>>16) & 0x000000FF, arp_rec[i].ipaddr>>24,
arp_rec[i].macaddr[0],arp_rec[i].macaddr[1],arp_rec[i].macaddr[2],
arp_rec[i].macaddr[3],arp_rec[i].macaddr[4],arp_rec[i].macaddr[5],
arp_rec[i].sec);
USART_TX((uint8_t*)str1,strlen(str1));
}
return 0;
}
Соберём код, прошьём контроллер и поиграмем с запросами
IP-адреса в таблице у нас больше не дублируются, на существующие адреса запросы не посылаются. 12 часов я ждать не стал, но я пробовал максимальное количество секунд в условии менять на значительно меньшее — устаревшие адреса удалялись. Так что всё работает.
Таким образом, мы создали теперь вполне полноценный ARP-клиент-сервер, который не только отзывается на ARP-запросы, но и умеет теперь их посылать.
Предыдущая часть Программирование МК AVR Следующий урок
Техническая документация:
Документация на микросхему ENC28J60
Перечень ошибок ENC28J60 (Errata)
Приобрести плату Atmega 328p Pro Mini можно здесь.
Программатор (продавец надёжный) USBASP USBISP 2.0
Ethernet LAN Сетевой Модуль можно купить здесь (модуль SD SPI в подарок) ENC28J60 Ethernet LAN Сетевой Модуль.
Смотреть ВИДЕОУРОК (нажмите на картинку)
В функции arp_request() — должно быть:
memset(arp_rec+i,0,sizeof(arp_record_ptr));
или
memset((uint8_t*)arp_rec+(sizeof(arp_record_ptr)*i),0,sizeof(arp_record_ptr));