STM Урок 68. LAN. ENC28J60. Часть 7



 

Урок 68

 

Часть 7

 

LAN. ENC28J60

 

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

 

Очередная задача, стоящая перед нами — ответить на 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)

  {

  {

}

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

 

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,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 только в случае, если ARP-запрос вернёт единицу

 

if(frame->type==ETH_ARP)

{

  ...

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

  {

   

  }

}

 

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

 

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_send занесём в ARP-заголовок код ответа ARP

 

void arp_send(enc28j60_frame_ptr *frame)

{

  arp_msg_ptr *msg = (void*)frame->data;

  msg->op = ARP_REPLY;

 

анесём также в заголовок физические адреса

 

msg->op = ARP_REPLY;

memcpy(msg->macaddr_dst,msg->macaddr_src,6);

memcpy(msg->macaddr_src,macaddr,6);

 

Затем занесём IP-адреса

 

memcpy(msg->macaddr_src,macaddr,6);

memcpy(msg->ipaddr_dst,msg->ipaddr_src,4);

memcpy(msg->ipaddr_src,ipaddr,4);

 

И в завершении функции отправим пакет

 

  memcpy(msg->ipaddr_src,ipaddr,4);

  eth_send(frame,sizeof(arp_msg_ptr));

}

 

В функции eth_read ответим на ARP-запрос

 

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

{

  arp_send(frame);

}

 

Соберём код, прошьём контроллер. Для того, чтобы увидеть наш ответ, желательно установить бесплатную программу Wireshark. Это анализатор сетевых пакетов.

Установим в данной программе фильтр только на пакеты arp

 

image33

 

Пропинугем наш IP-адрес таким же образом, как и прежде. Ответа на пинг мы не получим, но на запрос ARP в утилите мы увидим ответ

 

image34

 

Можно также открыть и посмотреть структуру пакета ARP

 

image35

 

Также в таблице соответствия адресов ARP компьютера мы видим теперь наши данные

 

image36

 

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

 

 

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

 

 

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

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

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

 

 

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

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

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

 

 

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

 

STM LAN. ENC28J60

 

Один комментарий на “STM Урок 68. LAN. ENC28J60. Часть 7
  1. Sir why you didn't use LWIP TCP/ip stack with ENC28j60?

    Please make tutorial on ENC28j60 with LWiP TCP/ip stack

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

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

*