Виртуальный COM-порт на STM32


Итак, у нас есть плата STM32F7 Discovery (например). На других платах всё должно быть аналогично.
Запускаем Stm32CubeMX, создаём новый проект, выбираем наш микроконтроллер из списка и производим некоторую настройку проекта.
1. Вкладка Pinout:
открываем Peripherials/USB_OTG_FS, выбираем Mode - Device Only
открываем Peripherials/RCC, выбираем High Speed Clock (HSE)- Crystal/Ceramic Resonator
открываем Peripherials/SYS, выбираем Debug - Serial Wire
открываем MiddleWares USB_DEVICE, выбираем Class For FS IP - Communication Device Class (Virtual Com Port)
2. Вкладка Clock Configuration:
устанавливаем HCLK = 216MHz (или другое значение, в зависимости от микроконтроллера)
CubeMX настраивает всё автоматически
3. Вкладка Configuration:
Нажимаем на кнопку USB_FS, ставим VBUS sensing = Disabled
В меню Project/Settings:
Вкладка Project: выбираем нужную IDE, например, EWARM, также настраиваем пути к папкам проекта
Вкладка Code Generator:
включаем опцию Add necessary library files...
включаем Generate peripherial initialization...
включаем Set all free pins as analog...
Закрываем окно, генерируем код (Project/Generate Code)
Генерируем код, открываем IDE.
В файле usbd_cdc_if.c пишем следующее:
в функции CDC_Transmit_FS:
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) { uint8_t result = USBD_OK; /* USER CODE BEGIN 7 */ USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); /* USER CODE END 7 */ return result; }
в функции 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]); CDC_Transmit_FS(Buf, *Len); USBD_CDC_ReceivePacket(&hUsbDeviceFS); return (USBD_OK); /* USER CODE END 6 */ }
Этот код обеспечивает "эхо", при приеме символа в виртуальный com-порт он будет сразу передан обратно.
Компилируем и прошиваем контроллер. Подключаем плату (разъем USB_FS) к компьютеру.
И ту нас ожидают первые грабли. Windows видит, что подключено устройство, но драйвер не работает. Примерно так (кликабельно):

Другие ОС плату вообще не видят.
Что делать? Ищем в исходниках проекта и заменяем:
в файле usbd_cdc_if.c:
#define USB_HS_MAX_PACKET_SIZE
с 512 на 256.
в файле usbd_cdc.c:
#define CDC_DATA_HS_MAX_PACKET_SIZE
с 512 на 256.
Прошиваем снова, теперь всё работает. Открываем любую программу терминала (я использую putty), и проверяем.
Подключаем плату к Mac, смотрим, что появилось:
ls /dev/tty*
плата появилась под именем /dev/tty.usbmodemfd121. Я не знаю, почему именно такое имя, но теперь можно проверить её работу:
screen /dev/tty.usbmodemfd121
(или можно поставить ту же putty). Всё работает без проблем.
Теперь Linux. Аналогично, проверяем ls /dev/tty*, появилось устройство /dev/ttyACM0. Проверяем, и здесь нас ждут ещё одни грабли: отказано в доступе. Нужно добавить себя в группу dialout:
sudo adduser user dialout
su - user
(где user - ваше имя пользователя)
Проверяем, теперь всё работает.
|
</> |