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



 

Урок 40

 

Часть 3

 

LAN. ENC28J60

 

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

 

При операции чтения мы читаем регистр ESTAT на предмет установки бита CLKRDY.

Напишем функцию чтения буфера (см. таблицу 4.1 выше)

 

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

static void enc28j60_readBuf(uint16_t len, uint8_t* data)

{

  SS_SELECT();

  SPI_SendByte(ENC28J60_READ_BUF_MEM);

  while (len—) {

    SPI_SendByte(0x00);

    *data++ = SPDR;

  }

  SS_DESELECT();

}

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

 

 

Создадим переменную для хранения номера текущего банка

 

#include «enc28j60.h»

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

static uint8_t Enc28j60Bank;

 

Ну и, соответственно, напишем функцию установки текущего банка

 

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

static void enc28j60_SetBank (uint8_t address)

{

  if ((address & BANK_MASK) != Enc28j60Bank)

  {

    enc28j60_writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_BSEL1|ECON1_BSEL0);

    Enc28j60Bank = address & BANK_MASK;

    enc28j60_writeOp(ENC28J60_BIT_FIELD_SET, ECON1, Enc28j60Bank>>5);

  }

}

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

 

Попробуем разобраться в том, что здесь происходит.

Ну, во первых, если у нас уже текущий банк равен тому, который мы хотим установить, то мы ничего не делаем и уходим

А затем мы в регистре ECON1 очищаем биты BSEL1 и BSEL0, отвечающие за банк, затем заносим в переменную наш банк из адреса, сдвигаем полученное значение вправо на 5 пунктов для того, чтобы нужные биты оказались в младших, и устанавливаем соответствующие биты в том же регистре

 

image08

 

Затем напишем универсальные функции для чтения и записи обычных регистров управления

 

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

static void enc28j60_writeRegByte (uint8_t address, uint8_t data)

{

  enc28j60_SetBank(address);

  enc28j60_writeOp(ENC28J60_WRITE_CTRL_REG, address, data);

}

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

static uint8_t enc28j60_readRegByte (uint8_t address)

{

  enc28j60_SetBank(address);

  return enc28j60_readOp(ENC28J60_READ_CTRL_REG, address);

}

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

 

Буфер, работающий и на чтение и на запись, необходимо настроить также с помощью регистров

 

image09

 

 

Так как все указатели у нас двухбайтовые, то создадим ещё функцию для записи данных в такие регистры

 

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

static void enc28j60_writeReg(uint8_t address, uint16_t data)

{

  enc28j60_writeRegByte(address, data);

  enc28j60_writeRegByte(address + 1, data >> 8);

}

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

 

Настроим буферы в функции инициализации

 

;

//настроим буферы

enc28j60_writeReg(ERXST, RXSTART_INIT);

enc28j60_writeReg(ERXRDPT, RXSTART_INIT);

enc28j60_writeReg(ERXND, RXSTOP_INIT);

enc28j60_writeReg(ETXST, TXSTART_INIT);

enc28j60_writeReg(ETXND, TXSTOP_INIT);

 

Включим broadcast, вдруг пригодится

 

enc28j60_writeReg(ETXND, TXSTOP_INIT);

//Enable Broadcast

enc28j60_writeRegByte(ERXFCON, enc28j60_readRegByte(ERXFCON) | ERXFCON_BCEN);

 

Также можно включить фильтрацию пакетов с проверкой контрольной суммы с помощью определённых регистров EPMM0-EPMM7 и EPMMCS, но пока мы этого делать не будем, мы хотим видеть все пакеты. Если будет впоследствии это нужно, то мы всегда успеем отфильтровать. Просто я хочу отметить, что наша микросхема очень хорошо умеет фильтровать пакеты по маске и контрольной сумме.

Добавим в наш файл глобальную переменную нашего физического адреса

 

static uint8_t Enc28j60Bank;

uint8_t macaddr[6] = MAC_ADDR;

 

Ну и, соответственно, настроим канальный уровень в инициализации

 

enc28j60_writeRegByte(ERXFCON, enc28j60_readRegByte(ERXFCON) | ERXFCON_BCEN);

//настраиваем канальный уровень

enc28j60_writeRegByte(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);

enc28j60_writeRegByte(MACON2, 0x00);

enc28j60_writeOp(ENC28J60_BIT_FIELD_SET, MACON3,

MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);

enc28j60_writeReg(MAIPG, 0x0C12);//

enc28j60_writeRegByte(MABBIPG, 0x12);//промежуток между фреймами

enc28j60_writeReg(MAMXFL, MAX_FRAMELEN);//максимальный размер фрейма

enc28j60_writeRegByte(MAADR5, macaddr[0]);// Set MAC address

enc28j60_writeRegByte(MAADR4, macaddr[1]);

enc28j60_writeRegByte(MAADR3, macaddr[2]);

enc28j60_writeRegByte(MAADR2, macaddr[3]);

enc28j60_writeRegByte(MAADR1, macaddr[4]);

enc28j60_writeRegByte(MAADR0, macaddr[5]);

 

Кратко о том, что здесь происходит.

У нас есть четыре регистра для настройки данного уровня MACON1-MACON4, хотя в документации только 3, второго нет

 

image10

Поэтому во второй мы отправим все нули.

В первом регистре мы включим следующие биты: MARXEN, разрешающий принимать пакеты, а также TXPAUS и RXPAUS, которые включают аппаратное управление потоком.

В третьем регистре включим паддинг, или выравнивание. Для этого есть три бита PADCFG, в них мы включим 001 для выравнивание пакета нулями до 60 байт и добавления контрольной суммы 4 байта. Также здесь мы включаем биты FRMLNEN, который автоматически проверяет длину пакетов и TXCRCEN, который автоматически добавляет к пакету контрольную сумму.

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

Затем MAMXFL, который устанавливает значения максимального размера фрейма (кадра).

Ну а дальше, я думаю, всем понятно, что мы обязаны занести в регистры наш MAC-адрес.

Дальше работаем с физическим уровнем.

Здесь не так всё просто.

Оказывается, чтобы занести значение в один из регистров, управляющих физическим уровнем (PHY), нужно это делать не напрямик, так как нет такой возможности, а через регистры MII.

У нас есть такой регистр MIREGADR, в который мы сначала обязаны занести значение адреса того или иного регистра PHY. А затем данные, предназначенные для этого регистра, мы заносим в регистры MIWRL (младший байт) и MIWRH (старший байт), причём именно в такой последовательности. Затем читаем регистр MISTAT на предмет сброса бита BUSY. Вот так вот.

Поэтому напишем отдельную функцию для записи регистра PHY

 

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

static void enc28j60_writePhy (uint8_t address, uint16_t data) {

  enc28j60_writeRegByte(MIREGADR, address);

  enc28j60_writeReg(MIWR, data);

  while (enc28j60_readRegByte(MISTAT) & MISTAT_BUSY)

  ;

}

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

 

Для чтения таких регистров также есть свои особенности, но мы пока чтение не используем.

 

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

 

 

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

 

 

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

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

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

 

 

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

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

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

 

 

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

 

AVR LAN. ENC28J60

4 комментария на “AVR Урок 40. LAN. ENC28J60. Часть 3
  1. Anthony:

    А можно поподробнее про выравнивание, т.к. из гугла в целом понятно, но вот применительно к данной микросхеме — не совсем.

  2. angrey19:

    Почему нет регистра MACON2?- «Ваша фраза из видео», в даташите он есть, смотрел по вашей ссылке…

  3. angrey19:

    Да вроде везде) , но дело не в этом. Кажется разобрался. Поскольку в данном уроке мы разбираем «Настройки инициализации MAC», то там действительно MACON2 не задействован, кроме как «очистите 7-й бит MARST в MACON2» стр.34 ДШ. Но мы и так его весь нулями заполняем. Все верно тогда.

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

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

*