STM Урок 33. HAL. USB. Virtual Com Port

 

 

 

Урок 33

HAL. USB. Virtual Com Port

 

 

Отладочную плату ипользуем ту же: STM32F4-DISCOVERY.

Проект создаём из проекта I2CLCD80. Назовем его USB_OTG_CDC. Запустим проект в Cube, включим USB_OTG_FS в режим Device_Only

 

image00

 

В USB_DEVICE в разделе Class For FS IP выберем пункт Communication Device Class (Virtual Port Com).

 

image02

 

Лапки портов PD4-PD7, PB8, PB9 отключим, это пережиток прошлых занятий

 

image01

 

В Clock Configuration выберем следующие делители (нажмите на картинку для увеличения изображения)

 

image04_0500

 

В Configuration ничего не трогаем, т.к. прерывания там выставились сами.

Сгенерируем и запустим проект, подключим lcd.c и настроим программатор на автоперезагрузку.

Соберем проект. Прошьём контроллер. У нас появится неизвестное устройство, скачаем драйвер на наше виртуальное устройство usb. Для этого зайдем на сайт st.com, в строке поиска там вводим virtual com port, скачиваем и устанавливаем драйвер. Затем желательно зайти в папку с установленным драйвером, выбрать папку, соответствующую разрядности нашей операционной системы, и запускаем также установку и оттуда.

У нас скорей всего устройство установится с ошибкой (код 10)

 

image03

 

Есть несколько типов решений, мне понравился именно этот, т.к. более простой: в файле usbd_cdc.h заменим размер пакета, вместо 512 напишем 256 в данной строке:

 

#define CDC_DATA_HS_MAX_PACKET_SIZE                 256  /* Endpoint IN & OUT Packet size */

 

Соберём, прошьём и увидим, что ошибка исчезла.

Начнём писать код.

Сначала попытаемся передать данные на ПК.

Для этого мы сначала откроем файл usbd_cdc_if.c и исправим там в 2х строчках 4 на 64

 

/* It's up to user to redefine and/or remove those define */

#define APP_RX_DATA_SIZE  64

#define APP_TX_DATA_SIZE  64

 

В файле main.c закомментируем весь пользовательский код кроме инициализации и очистки дисплея

 

  /* USER CODE BEGIN 2 */

        LCD_ini();

//        sprintf(str,"Stm32F407VG");

//        LCD_String(str);

//        LCD_SetPos(10, 2);

//        sprintf(str,"ARM mc");

//        LCD_String(str);

//        HAL_Delay(2000);

        LCD_Clear();

//        LCD_SetPos(4, 0);

//        LCD_SendChar('s');

//        LCD_SetPos(8, 1);

//        LCD_SendChar('t');

//        LCD_SetPos(12, 2);

//        LCD_SendChar('m');

//        LCD_SetPos(16, 3);

//        LCD_SendChar('3');

//        LCD_SendChar('2');

//        HAL_Delay(2000);

  /* USER CODE END 2 */

 

 

Также в main.c подключим файл usbd_cdc_if.h для видимости функций приема и передачи

 

/* USER CODE BEGIN Includes */

#include "main.h"

#include "usbd_cdc_if.h"

 

Немного изменим в главной функции строковую переменную, убавив в ней размер и добавив префикс tx

 

  /* USER CODE BEGIN 1 */

        char str_tx[21];

  /* USER CODE END 1 */

 

В файле usbd_cdc_if.c добавим прототип функции передачи, скопировав объявление из реализации данной функции в том же файле

 

/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);

/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */

 

В main() внесём данные в строку

 

        sprintf(str_tx,"USB Transmit\r\n");

  /* USER CODE END 2 */

 

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

 

  while (1)

  {

                CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));

                HAL_Delay(500);

  /* USER CODE END WHILE */

 

Соберём код, прошьём контроллер и посмотрим результат в терминальной программе.

Вроде передать нам что-то удалось. Теперь попробуем что-нибудь принять. Здесь чуть посложнее, т.к. для этого используется уже обработчик прерывания, коим является в файле usbd_cdc_if.c функция CDC_Receive_FS.

Добавим ещё одну строковую глобальную переменную в main()

 

/* USER CODE BEGIN PV */

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

char str_rx[21];

/* USER CODE END PV */

Объявим её также и в файле usbd_cdc_if.c

/* USER CODE BEGIN PRIVATE_VARIABLES */

extern char str_rx[21];

/* USER CODE END PRIVATE_VARIABLES */

 

В функцию CDC_Receive_FS в этом же файле добавим некоторый код и кое-что закомментируем

 

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)

{

  /* USER CODE BEGIN 6 */

  //USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);

        strncpy(str_rx,(char*)Buf,*Len);

        str_rx[*Len]=0;

  USBD_CDC_ReceivePacket(&hUsbDeviceFS);

  return (USBD_OK);

Добавим переменную в main()

  /* USER CODE BEGIN 1 */

        uint8_t i=0;

        char str_tx[21];

 

Занесенные в наш буфер данные попробуем вывести на дисплей, для этого в бесконечном цикле в функции main() добавим определённый код

 

  while (1)

  {

                CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));

                LCD_SetPos(0, 0);

                LCD_String(str_rx);

                for(i=1;i<((uint8_t)(20-strlen(str_rx)));i++) LCD_SendChar(' ');

                HAL_Delay(500);

 

Соберём проект. Прошьём код и посмотрим результат, вводя в терминальной программе и отправляя в порт USB какие-нибудь строки.

 

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

 

Исходный код

 

 

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

 

 

Смотреть ВИДЕОУРОК

 

STM32 HAL. USB. Virtual Com Port

 

3 комментария на “STM Урок 33. HAL. USB. Virtual Com Port
  1. Артур:

    "Есть несколько типов решений, мне понравился именно этот, т.к. более простой: в файле usbd_cdc.h заменим размер пакета, вместо 512 напишем 256 в данной строке…."

    Просто измените размер кучи (Minimum Heap Size) в настройка CubeMX. Вместо значения 0x200 задайте 0x400.

    И комп увидит устройство без ошибок.

    При инициализации структур компилятору элементарно не хватает места, заданного по умолчанию, для выделения памяти.

  2. Valera:

    Спасибо огромное за ваши материалы по STM32 , подключил TFT 320×240 — все отлично работает . Вернулся к материалу для подключения флешки . Все отладочные средства у меня находятся на VirtualBox ( W7 ) . Скачал по вашей инструкции и поставил драйвер Virtual com port . Он поставился , но в диспетчере задач ничего не появилось ни в разделе com портов , ни в других . Может вы сталкивались с подобной проблемой ? Если нет — в любом случае еще раз спасибо за проделанную работу .

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

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

*