Урок 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 с адаптером можно здесь USBASP USBISP 3.3 с адаптером
Ethernet LAN Сетевой Модуль можно купить здесь ENC28J60 Ethernet LAN Сетевой Модуль.
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
В функции 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));