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 можно приобрести здесь STM32F103C8T6

Программатор недорогой можно купить здесь ST-Link V2

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

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

 

 

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

STM LAN. ENC28J60

 

 

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

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 не будет опубликован. Обязательные поля помечены *

*