Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кармин Новиелло - Освоение STM32.pdf
Скачиваний:
2743
Добавлен:
23.09.2021
Размер:
47.68 Mб
Скачать
ioLibrary_Driver

Разработка IoT-приложений

719

26.2.1. Как использовать шилд W5500 и модуль ioLibrary_Driver

Как уже говорилось, W5500 без проблем совместим со всеми шестнадцатью платами Nucleo. На рисунке 517 показана распиновка шилда. Интерфейс SPI направлен к выводам D13, D12 и D11, и они соответствуют тем же выводам периферийного устройства SPI1 (кроме платы Nucleo-F302R8, где эти выводы соответствуют периферийному устройству SPI2). Вывод Slave Select (SS) для вывода W5500 соответствует выводу D10 Arduino, а вывод SS для SD-карты соответствует выводу D4 Arduino.

Рисунок 5: Распиновка шилда W5500

Взглянув на рисунок 5, вы можете увидеть, что вывод D2 играет важную роль. Микросхема W5500 спроектирована с возможностью необязательной установки низкого уровня на выводе INTn, когда происходит несколько событий, связанных с сетевым интерфейсом (например, коллизия IP-адресов и т. д.) или с одним сокетом (например, установлено соединение, получены данные и т. д.). Эта функция позволяет сконфигурировать соответствующий вывод микроконтроллера в режиме GPIO_MODE_IT_FALLING, чтобы срабатывал соответствующий IRQ, когда микросхема устанавливает низкий уровень на выводе INTn. Это позволяет писать асинхронные приложения, особенно если вы используете в

17 Рисунок взят с веб-сайта WIZnet (http://www.wiznet.co.kr/product-item/w5500-ethernet-shield/).

Разработка IoT-приложений

720

сочетании с ОСРВ (например, ISR может использовать семафор для пробуждения спящего потока, который начинает выполнять операцию с сокетом).

Рисунок 6: Чтобы разрешить работу вывода INTn, необходимо замкнуть выводы 1-2

Обратите внимание, что в шилде W5500 вывод D2 не подключен к выводу INTn микросхемы W5500. Чтобы активировать его, вам необходимо припаять резистор 0603 с сопротивлением 0 Ом между выводами 1-2, как показано на рисунке 6 (также достаточно соединения каплей припоя).

Как только платы соединены друг с другом, мы можем сосредоточить наше внимание на программной части. Импортировать модуль ioLibrary_Driver в существующий проект Eclipse довольно просто. Сначала вам нужно перетащить всю библиотеку в корневой каталог проекта Eclipse. Затем вам нужно добавить следующий путь в список путей включения Include paths в настройках проекта:

"../ioLibrary_Driver/Ethernet"

"../ioLibrary_Driver/Internet"

Наконец, вам нужно указать точный тип микросхемы W5XXX, установив макрос

_WIZCHIP_ в файле ioLibrary_Driver/Ethernet/wizchip_conf.h.

26.2.1.1. Конфигурирование интерфейса SPI

Модуль ioLibrary_Driver предназначен для абстрагирования от конкретного микроконтроллера и процедур управления интерфейсом SPI. Его можно использовать с STM32, AVR, с Microchip и так далее. Итак, нам нужен способ взаимодействия с модулем HAL_SPI, необходимым для программирования периферийного устройства SPI.

Как пользователи данной библиотеки, мы должны предоставить 6 процедур обратного вызова, которые реализуют всю необходимую логику управления SPI. Это следующие процедуры:

void cs_sel(): этот обратный вызов вызывается библиотекой каждый раз, когда

ей нужно выбрать (установить НИЗКИМ) вывод, зафиксированный на выводе SS микросхемы W5500.

Разработка IoT-приложений

721

void cs_desel(): этот обратный вызов вызывается библиотекой каждый раз, когда

ей нужно отменить выбор (установить ВЫСОКИМ) вывода, зафиксированного на выводе SS микросхемы W5500.

uint8_t spi_rb(): эта процедура вызывается, когда нужно прочитать один байт по

интерфейсу SPI.

void spi_wb(uint8_t b): эта процедура вызывается, когда нужно отправить один

байт через интерфейс SPI.

void spi_rb_burst(uint8_t *buf, uint16_t len): этот дополнительный и необяза-

тельный обратный вызов вызывается, когда необходимо прочитать более трех байт по SPI. Это позволяет нам реализовать обратный вызов, обрабатывающий SPI в режиме DMA, что увеличивает скорость передачи (этот режим также назы-

вается режимом пакетной передачи (burst mode)).

void spi_wb_burst(uint8_t *buf, uint16_t len): этот дополнительный и необяза-

тельный обратный вызов вызывается, когда необходимо отправить более трех байт по SPI. Это позволяет нам реализовать обратный вызов, обрабатывающий

SPI в режиме DMA.

Предполагая, что интерфейс SPI сконфигурирован в соответствии с микросхемой, мы можем просто реализовать эти обратные вызовы следующим образом:

void cs_sel() {

HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_RESET); // CS НИЗКИЙ

}

void cs_desel() {

HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_SET); // CS ВЫСОКИЙ

}

uint8_t spi_rb(void) { uint8_t rbuf;

HAL_SPI_Receive(&hspi1, &rbuf, 1, HAL_MAX_DELAY); return rbuf;

}

void spi_wb(uint8_t b) { HAL_SPI_Transmit(&hspi1, &b, 1, HAL_MAX_DELAY);

}

void spi_rb_burst(uint8_t *buf, uint16_t len) { HAL_SPI_Receive_DMA(&hspi1, buf, len); while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY_RX);

}

void spi_wb_burst(uint8_t *buf, uint16_t len) { HAL_SPI_Transmit_DMA(&hspi1, buf, len); while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY_TX);

}

После того как мы определили низкоуровневые функции, мы должны «передать» их в библиотеку ioLibrary. Эту работу можно выполнить с помощью следующих процедур:

Разработка IoT-приложений

722

...

reg_wizchip_cs_cbfunc(cs_sel, cs_desel); reg_wizchip_spi_cbfunc(spi_rb, spi_wb); reg_wizchip_spiburst_cbfunc(spi_rb_burst, spi_wb_burst);

Все готово. Этими несколькими строками кода мы успешно интегрировали CubeHAL в

библиотеку ioLibrary_Driver.

26.2.1.2. Настройка буферов сокетов и сетевого интерфейса

А сейчас мы, наконец, готовы приступить к использованию микросхемы W5500. Первый шаг заключается в инициализации микросхемы W5500 специальной процедурой. Первая функция, которую нужно вызвать после настройки обратных вызовов, следующая:

int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);

Данная процедура выполняет две функции: сбрасывает микросхему W5500 (обязательная процедура) и конфигурирует размер буфера приема и передачи для каждого отдельного сокета. Все микросхемы W5X00 имеют две внутренние области общей памяти, предназначенные для буфера приема и передачи. В чипе W5500 размер каждой из этих областей составляет 16 КБ. Эти две области, в свою очередь, должны быть разделены между сокетами, которые мы хотим использовать. В конфигурации по умолчанию каждому из восьми сокетов выделяется 2 КБ этих областей. Но если, например, нашему приложению требуется всего 4 сокета, мы можем разделить буфер приема и передачи на четыре. Или, если одному сокету требуется больше комнат для обмена данными (rooms to exchange data) с другим узлом, мы можем выделить больше места только для одного сокета и уменьшить пространство для других.

Мы можем выделить память буфера приема и передачи, передав процедуре wizchip_init() два массива, каждый с восемью значениями. Единственное требование – сумма этих значений не должна превышать 16. Например, предполагая, что мы хотим использовать только два сокета в нашем приложении, мы можем определить конфигурацию массива следующим образом:

uint8_t bufSize[] = {12, 4, 0, 0, 0, 0, 0, 0}; wizchip_init(bufSize, bufSize);

Приведенный выше код просто выделяет 12 КБ буфера приема и передачи первому сокету, а оставшиеся 4 КБ – второму сокету. Ясно, что мы можем организовать буфер приема и передачи, если мы соблюдаем общий размер 16 КБ.

После инициализации микросхемы мы можем сконфигурировать сетевой интерфейс с помощью функции:

void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);

где структура wiz_NetInfo, используемая для передачи в библиотеку параметров конфигурации сети, определенная следующим образом: