Top.Mail.Ru

STM32CubeMx. USB Custom HID. Прием и передача данных.

Вот и подоспела вторая часть из цикла статей, посвященных реализации класса USB Custom HID на микроконтроллерах STM32 при помощи утилиты STM32CubeMx. Как и обещал в конце предыдущей статьи, сегодня мы займемся непосредственно обменом данными между хостом и нашим устройством.

Начнем, пожалуй, с передачи данных хосту. Тут все просто - для передачи в HAL реализована специальная функция:

uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,
                                   uint8_t *report,
                                   uint16_t len)

Аргументы у функции типичные для любой передающей функции - указатель на передаваемые данные и количество байт, которые нужно отправить. Кроме того, мы должны передать в функцию объект USBD_HandleTypeDef. Эта переменная у нас определена в файле usnd_custom_hid_if:

USBD_HandleTypeDef *hUsbDevice_0;

Поскольку передачу мы будем производить из функции main(), то давайте сразу же объявим в файле main.c:

extern USBD_HandleTypeDef *hUsbDevice_0;

Передавать мы будем (как решили в предыдущей статье) по 4 байта, поэтому заодно объявим и массив для хранения передаваемых данных:

uint8_t dataToSend[4];

В принципе с приготовлениями на этом все, теперь просто вызываем функцию отправки, ну и не забываем заполнить массив данных какими-нибудь тестовыми значениями:

/* USER CODE BEGIN 2 */
dataToSend[0] = 'S';
dataToSend[1] = 'n';
dataToSend[2] = 'd';
dataToSend[3] = '\0';
/* USER CODE END 2 */

/* USER CODE BEGIN 3 */
/* Infinite loop */
while (1)
{
	HAL_Delay(1000);
	USBD_CUSTOM_HID_SendReport(hUsbDevice_0, dataToSend, 4);
}
/* USER CODE END 3 */

Теперь наше устройство будет отправлять данные хосту раз в секунду. Как видите, с передачей все оказалось совсем несложно.

На самом деле, с приемом тоже нет никаких трудностей и если его организация и сложнее, то ненамного. Итак, предлагаю реализовать следующее - пусть хост у нас отправляет два разных пакета, к примеру строки "Rcv" и "Snd". Мы же будем в зависимости от принятого пакета гасить или зажигать светодиод (на моей плате я использую PC6). Вот в общем-то и все, переходим к реализации...

Объявим в файле usbd_custom_hid_if.c буфер для сохранения принятых данных:

/* USER CODE BEGIN 2 */
uint8_t dataToReceive[4];
/* USER CODE END 2 */

А теперь идем в функцию CUSTOM_HID_OutEvent_FS(), тут то мы и будем принимать и анализировать данные:

static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
	/* USER CODE BEGIN 6 */
	USBD_CUSTOM_HID_HandleTypeDef     *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDevice_0->pClassData;

	for (uint8_t i = 0; i < 4; i++)
	{
		dataToReceive[i] = hhid->Report_buf[i];
	}

	if ((dataToReceive[0] == 'R') && (dataToReceive[1] == 'c') && (dataToReceive[2] == 'v'))
	{
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
	}

	if ((dataToReceive[0] == 'S') && (dataToReceive[1] == 'n') && (dataToReceive[2] == 'd'))
	{
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
	}

	return(0);
	/* USER CODE END 6 */
}

Собственно, тут нет ничего фантастического и непонятного - все принятые данные сохраняются в наш объект для работы с USB (hUsbDevice_0). Мы просто копируем их оттуда и сохраняем в массив. Ну а после просто анализируем данные и в зависимости от того, какой пакет принят, меняем состояние вывода, к которому подключен светодиод. Вот и все!

Статья получилась небольшая, но все аспекты, которые я хотел описать, я описал ) В следующей статье, посвященной USB Custom HID мы напишем свою собственную программу для хоста (ПК), которая и будет отправлять данные нашему устройству, а на сегодня на этом заканчиваем, до встречи в новых статьях 🤝

Следующая статья по Custom HID - USB Custom HID.

Подписаться
Уведомить о