AVR Урок 40. LAN. ENC28J60. Часть 7



 

Урок 40

 

Часть 7

 

LAN. ENC28J60

 

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

 

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

 

if( (msg->op == ARP_REQUEST) && (msg->ipaddr_dst == IP_ADDR) )

{

  sprintf(str1,«requestrnmac_src %02X:%02X:%02X:%02X:%02X:%02Xrn»,

  msg->macaddr_src[0], msg->macaddr_src[1], msg->macaddr_src[2], msg->macaddr_src[3], msg->macaddr_src[4], msg->macaddr_src[5]);

  USART_TX((uint8_t*)str1,strlen(str1));

  sprintf(str1,«ip_src %ld.%ld.%ld.%ldrn»,

  msg->ipaddr_src & 0x000000FF, (msg->ipaddr_src>>8) & 0x000000FF, (msg->ipaddr_src>>16) & 0x000000FF, msg->ipaddr_src>>24);

  USART_TX((uint8_t*)str1,strlen(str1));

  sprintf(str1,«mac_dst %02X:%02X:%02X:%02X:%02X:%02Xrn»,

  msg->macaddr_dst[0], msg->macaddr_dst[1], msg->macaddr_dst[2], msg->macaddr_dst[3], msg->macaddr_dst[4], msg->macaddr_dst[5]);

  USART_TX((uint8_t*)str1,strlen(str1));

  sprintf(str1,«ip_src %ld.%ld.%ld.%ld»,

  msg->ipaddr_dst & 0x000000FF, (msg->ipaddr_dst>>8) & 0x000000FF, (msg->ipaddr_dst>>16) & 0x000000FF, msg->ipaddr_dst>>24);

  USART_TX((uint8_t*)str1,strlen(str1));

  res=1;

}

 

Ну тут всё просто. Только есть один вопрос. С какой стати какое-то устройство будет нам посыть ARP-запрос, мы же ведь никому не говорили о нашем IP-адресе.

А мы ему поможем. Мы воспользуемся утилитой ping, встроенной в любую операционную систему. Хотя ping посылает ICMP-запрос, но если он видит, что в таблице соответствия адресов ARP нет нашего IP-адреса, то сначала он посылает ARP-запрос.

Поэтому мы и пошлём ping на назначенный нами IP-адрес из командной строки, понятное дело, собрав перед этим код и прошив контроллер.

 

image03

 

 

Мы видим, что наша плата на ping не откликнулась, но это ничего страшного, мы же ведь не писали ответ не только на ICMP-запросы, но и на ARP, но зато мы вот что видим в нашей терминальной программе

 

image04

 

Мы видим и физический и сетевой адреса устройства, пославшего нам запрос (это наш основной ПК с адресом 192.168.1.89), а также сетевой адрес приёмника. Так как физический адрес приёмника пока неизвестен, то мы получаем нулевой адрес.

Очередная задача, стоящая перед нами — ответить на ARP-запрос.

Но мы помним, что мы написали только функцию приёма пакетов Ethernet (или кадров). А чтобы на что-то ответить, мы должны уметь также такие пакеты отправлять. Поэтому нам придётся вернуться в файл enc28j60.c и добавить функцию для передачи пакетов

 

//—————————————-

void enc28j60_packetSend(uint8_t *buf, uint16_t buflen)

{

}

//—————————————-

 

 

Подождём, пока установится бит TXRTS в регистре ECON1, что означает готовность нашего передатчика передавать информацию

 

void enc28j60_packetSend(uint8_t *buf, uint16_t buflen)

{

  while (enc28j60_readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_TXRTS)

  {

  }

}

 

Дальше борьба с ошибкой микросхемы, согласно которой бит TXRTS сам не сбрасывается. Мы сначала проверяем регистр EIR на установку бита TXERIF, а затем сбрасываем бит

 

while (enc28j60_readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_TXRTS)

{

  if (enc28j60_readRegByte(EIR) & EIR_TXERIF)

  {

    enc28j60_writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);

    enc28j60_writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);

  }

}

 

Добавим функцию записи в буфер

 

//—————————————-

static void enc28j60_writeBuf(uint16_t len, const uint8_t* data) {

  SS_SELECT();

  SPI_SendByte(ENC28J60_WRITE_BUF_MEM);

  while (len—)

  SPI_SendByte(*data++);

  SS_DESELECT();

}

//—————————————-

 

Продолжаем функцию отправки пакета. Затем записываем и отправляем пакет

 

      enc28j60_writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);

    }

  }

  enc28j60_writeReg(EWRPT, TXSTART_INIT);

  enc28j60_writeReg(ETXND, TXSTART_INIT+buflen);

  enc28j60_writeBuf(1,(uint8_t*)«\x00»);

  enc28j60_writeBuf(buflen, buf);

  enc28j60_writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);

}

 

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

 

USART_TX((uint8_t*)«; arp»,5);

if(arp_read(frame, len sizeof(enc28j60_frame_ptr)))

{

}

 

Добавим физический адрес нашего устройства, унаследовав его из другого модуля

 

uint8_t net_buf[ENC28J60_MAXFRAME];

extern uint8_t macaddr[6];

 

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

 

//———————————————————

void eth_send(enc28j60_frame_ptr *frame, uint16_t len)

{

  memcpy(frame->addr_dest, frame->addr_src, 6);

  memcpy(frame->addr_src, macaddr, 6);

  enc28j60_packetSend((void*)frame, len + sizeof(enc28j60_frame_ptr));

}

//———————————————————

 

Добавим также функцию отправки ответного пакета ARP сразу после функции eth_send

 

//———————————————————

void arp_send(enc28j60_frame_ptr *frame)

{

}

//———————————————————

 

В следующей части нашего урока мы наконец-то ответим на запрос ARP, а также изучим заголовок протокола IP.

 

 

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

 

 

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

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

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

 

 

Приобрести плату Atmega 328p Pro Mini можно здесь.

Приобрести программатор USBASP USBISP с адаптером можно здесь USBASP USBISP 3.3 с адаптером

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

 

 

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

 

AVR LAN. ENC28J60

2 комментария на “AVR Урок 40. LAN. ENC28J60. Часть 7
  1. angrey19:

    Добрый день.
    Нет описания значения EIR_TXERIF в текстовой версии,
    В функции записи в буфер ENC28J60_WRITE_BUF_MEM undeclared (first use in this function)
    В общем проект не собирается…

  2. angrey19:

    Нашел в видео-уроке значения EIR_TXERIF, поставил.
    с ENC28J60_WRITE_BUF_MEM, так же поставил ENC28J60_READ_BUF_MEM как в видео.
    Где истина не уяснил, но пока все работает как у Admina.

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

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

*