Урок 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 пунктов для того, чтобы нужные биты оказались в младших, и устанавливаем соответствующие биты в том же регистре
Затем напишем универсальные функции для чтения и записи обычных регистров управления
//—————————————-
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);
}
//—————————————-
Буфер, работающий и на чтение и на запись, необходимо настроить также с помощью регистров
Так как все указатели у нас двухбайтовые, то создадим ещё функцию для записи данных в такие регистры
//—————————————-
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, второго нет
Поэтому во второй мы отправим все нули.
В первом регистре мы включим следующие биты: 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 Сетевой Модуль.
Смотреть ВИДЕОУРОК (нажмите на картинку)
А можно поподробнее про выравнивание, т.к. из гугла в целом понятно, но вот применительно к данной микросхеме — не совсем.
Почему нет регистра MACON2?- «Ваша фраза из видео», в даташите он есть, смотрел по вашей ссылке…
Не во всех даташитах.
Да вроде везде) , но дело не в этом. Кажется разобрался. Поскольку в данном уроке мы разбираем «Настройки инициализации MAC», то там действительно MACON2 не задействован, кроме как «очистите 7-й бит MARST в MACON2» стр.34 ДШ. Но мы и так его весь нулями заполняем. Все верно тогда.