STM Урок 34. HAL. USB. HID



Урок 34

HAL. USB. HID

 

Сегодня мы познакомимся с новым классом для USB — это Human Interface Device или как в народе говорят HID.

Данный класс отличается тем, что здесь мы посылаем короткие сообщения, у нас особой вероятности в том, что наши данные все дойдут, но в данный момент это не совсем и важно. Как правило скорость настраивается так, что данные все равно доходят. Самое главное, чтобы данные доходили быстро, поэтому такие интерфейсы, такие классы используют при программировании таких устройств, как манипулятор мышь, джойстик. клавиатура и им подобных. HID класс может быть как предопределённым, то есть предназначенным для конкретных существующих типов устройств, так и произвольный (custom). Со вторым типом мы немного поработаем на следующим занятием, а сегодня поработаем с первым классом и попробуем эмулировать манипулятор «мышь».

И чтобы с данным классом немного поподробнее разобраться, мы попробуем его реализовать в нашем контроллере STM32F407VG.

Для этого мы сначала конечно же сделаем проект.

Проект создаём из проекта TEST002. Назовем его USB_DEVICE_HID. Запустим проект в Cube, отключим выходные светодиоды, кнопку оставим

 

image00

 

 

Включим USB_OTG_FS в режим Device_Only.

 

image02

 

В USB Device выбираем Human Interface Device Class (HID)

 

image01

 

В Clock Configuration выберем следующие делители

 

image03

 

В Configuration ничего не трогаем.

Сгенерируем и запустим проект.

Соберем проект и настроим программатор на авторезет.

Скачаем файл USB Library User manual.pdf с официального сайта ST Microelectronics и откроем его на странице 39. Там дана функция отправки отчета устройством на host. В качестве хоста у нас будет выступать ПК

 

image04

 

 

Подключим файл в main.c

 

#include «main.h»

#include «usbd_hid.h»

/* USER CODE END Includes */

 

Добавим переменные туда же

 

/* USER CODE BEGIN PV */

/* Private variables ———————————————————*/

#define CURSOR_STEP     1

extern USBD_HandleTypeDef hUsbDeviceFS;

uint8_t HID_Buffer[4];

 

Напишем функцию подготовки буфера для передачи в шину

 

/* USER CODE BEGIN 0 */

static void GetPointerData(uint8_t *pbuf)

{

  static uint8_t cnt = 0; //счетчик циклов

  static uint8_t drct = 0; //направление курсора

  int8_t  x = 0, y = 0 , but = 0;

 

        if((cnt<20)&&(drct==0))

        {

                drct=0;

    x = CURSOR_STEP;

    y = CURSOR_STEP;

                cnt++;

  }

  else if (cnt>0)

  {

                drct=1;

    x = -CURSOR_STEP;

    y = -CURSOR_STEP;

                cnt—;

  }

        else drct=0;

        pbuf[0] = but;

        pbuf[1] = x;

        pbuf[2] = y;

        pbuf[3] = 0;

}

/* USER CODE END 0 */

 

В бесконечный цикл добавим код передачи буфера в шину

 

  /* USER CODE BEGIN WHILE */

  while (1)

  {

                HAL_Delay(100);

                GetPointerData(HID_Buffer);

USBD_HID_SendReport(&hUsbDeviceFS, HID_Buffer, 4);

  /* USER CODE END WHILE */

 

Соберем проект. Прошьем контроллер и посмотрим результат.

Курсор у нас ползает по диагонали вперёд-назад.

Чтобы всё это увидеть, рекомендую посмотреть видеоурок, который откроется, если Вы нажмёте картинку внизу страницы. Также в видеоуроке я даю некоторые пояснения по поводу видов дескрипторов класса HID и много ещё какой информации. Так что милости прошу на канал в YouTube, там вы ещё не то увидите.

Теперь поиграемся с эмуляцией кнопок мыши.

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

 

  int8_t  x = 0, y = 0 , but = 0;

 

//        if((cnt<20)&&(drct==0))

//        {

//                drct=0;

//    x = CURSOR_STEP;

//    y = CURSOR_STEP;

//                cnt++;

//  }

//  else if (cnt>0)

//  {

//                drct=1;

//    x = -CURSOR_STEP;

//    y = -CURSOR_STEP;

//                cnt—;

//  }

//        else drct=0;

        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_SET)                but=1;

        else but=0;

        pbuf[0] = but;

        pbuf[1] = x;

        pbuf[2] = y;

        pbuf[3] = 0;

}

 

Соберем, прошьем и попробуем нажать кнопку USER.

Заменим единичку на двойку

 

//        else drct=0;

        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_SET)                but=2;

        else but=0;

 

Посмотрим результат.

 

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Купить отладочную плату можно здесь STM32F4-DISCOVERY

 

 

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

 

STM32 HAL. USB. HID

9 комментариев на “STM Урок 34. HAL. USB. HID
  1. Михаил:

    Здравствуйте!

    Огромное спасибо за Ваши уроки!

    Я пытаюсь сделать эммулятор мыши на микроконроллере STM32F103RCT6.

    В качестве отправдяемых репортов служит следующий набор команд:

    uint8_t USB_Report_Buf[] = {0,   0,  0, 0,
                                1,   0,  0, 0, // Нажать кнопку
                                1,  50,  0, 0, // Переместиться влево на 50 пикселей
                                0,   0,  0, 0, // Отпустить кнопку
                                0,  50,  0, 0, // Переместиться влево на 50 пикселей
                                1,   0,  0, 0, // Нажать кнопку
                                1,  50,  0, 0, // Переместиться влево на 50 пикселей
                                0,   0,  0, 0, // Отпустить кнопку
                                0, 206,  0, 0, // Переместиться вправо на 50 пикселей
                                0, 206,  0, 0, // Переместиться вправо на 50 пикселей
                                0, 206,  0, 0, // Переместиться вправо на 50 пикселей
                                0,   0,  2, 0, // Переместиться вниз на 2 пикселя
                                0,   0,  0, 0}; 

    Отправка его осуществляется в главном цикле программы:

      /* USER CODE BEGIN WHILE */
      while (1)
      {
      /* USER CODE END WHILE */

      /* USER CODE BEGIN 3 */
        HAL_Delay(1000);
        pUSB_Report_Buf = &USB_Report_Buf[0]; // Установить указатель на начало списка коменд
        for (uint8_t i = 0; i < sizeof(USB_Report_Buf)/4; i++) { // Цикл по всем командам списка
          USBD_HID_SendReport(&hUsbDeviceFS, pUSB_Report_Buf, 4); // Отправка Репорта
          pUSB_Report_Buf += 4; // Увеличиваем указатель на 4 (количество байт в Репорте)
          HAL_Delay(500);
        }
      }
      /* USER CODE END 3 */

    }

    Но что-то не то происходит с первой командой (перемещает не на 50 пикселей, а меньше). И  это стабильно втечение всего времени работы (главного цикла).

     

    Если открыть редактор Paint, то на экране должно быть что-то типа:

    ___________________                    ___________________

    ___________________                    ___________________

    Но вместо этого выводит

              _________                    ___________________

    _________                    ___________________

    Подскажите в чем может быть проблема. Спасибо.

  2. P55:

    Добрый день.
    В режиме отладки в файле usb_hid.c
    не проходит проверку это условие
    if (pdev->dev_state == USBD_STATE_CONFIGURED)
    Что может быть не так с конфигурацией?

    • Изменилось, видимо, что-то в библиотеке, посмотрите пример в репозитории.

      • P55:

        Как зайти в репозиторий?

      • P55:

        Выяснил следующее.
        При включении платы без ST-link (можно просто снять одну ногу питание) пример заработал, в режиме отладки не работает.
        Другие программы в режиме отладке работают без проблем.
        Какой-то конфликт за USB между платой и ST-link-oм.
        Кто знает как это исправить?

        Если кому лень нажимать кнопку, то можно сделать вот так 🙂
        //if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_SET) but=2;
        // else but=0;
        if (but == 0 ) but=2;
        else but=0;
        //but — надо объявить как глобальную переменную.
        Если but в ноль не сбрасывать, то ПК будет думать, что Ваш HID-мышка нажала кнопку и держит.

  3. P55:

    Проверил плату с Stm32f103c8t6 на работу USB, в среде Ардуино IDE.
    Вот такой простой пример с клавиатурой заработал сразу же, без перетыкания проводов на SТ-линке.

    #include
    USBHID HID;
    HIDKeyboard Keyboard(HID);

    void setup() {
    HID.begin(HID_KEYBOARD);
    Keyboard.begin(); // useful to detect host capslock state and LEDs
    pinMode(PC13, OUTPUT);
    delay(1000);
    }
    void loop() {
    digitalWrite(PC13, HIGH); // turn the LED on (HIGH is the voltage level)
    delay(1000); // wait for a second
    Keyboard.println(«Hello world»);
    digitalWrite(PC13, LOW); // turn the LED off by making the voltage LOW
    delay(1000); // wait for a second
    }

  4. Максим:

    Приветствую!
    Не могли бы Вы ( или лучше на Ты? =-) ) конкретно сказать что за нога питания у ST-Link? Имеется в виду программатор или ST-Link на Discovery?
    У меня проблема в том, что ни один вариант USB не виден компьютером…
    Есть возможность указать какая именно перемычка или что отпаять/закоротить? 🙂
    Заранее благодарен!

  5. gena:

    Здравствуйте, подскажите пожалуйстаб а как организовать чтение координат текущего положения указателя (мыши)ю Спасибо!

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

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

*