21. STM32. Програмування STM32F103. USB


01.11.2016

На тестовій платі STM32F103 маємо microUSB роз’єм. І він служить не тільки для подачі живлення. STM32F103 може працювати з USB у якості різних USB - пристроїв. Як USB HID пристрій, у тому числі - як клавіатура чи мишка, як віртуальний послідовний порт, USB Mass Storage, тощо. Ми розглянемо лише пару прикладів. У першому - комп`ютер буде сприймати STM32F103 як віртуальний послідовний порт. У другому прикладі STM32F103 емулюватиме клавіатуру і мишку.  STM32F103 буде рухати мишкою, (звісно на екрані :), та емулювати натискання кнопок на клавіатурі.

Опис роботи USB

Загалом, Ви маєте розуміти що:
  • USB пристрої підключаються до Хоста (частіше за все, це - комп’ютер). Хост – головний, він усім керує.
  • USB пристрій не може бути ініціатором передачі даних. Тобто, він сидить і мовчить, поки його не запитають. Спитали чи надіслали дані, - він відповів чи прийняв дані і замовк.
  • USB пристрій має унікальний ідентифікатор. Кожний USB пристрій може мати декілька кінцевих точок, кожна з яких має унікальну адресу. Саме через кінцеві точки передаються дані чи команди.
  • USB пристрій має Дескриптор. Це масив даних, у якому міститься опис пристрою. Завдяки дескриптору, операційна система отримує інформацію про USB пристрій та використовує для спілкування з ним відповідний драйвер.
  • Хост ідентифікує USB-пристрій по ID вендора и ID продукту (Vendor ID - VID и Product ID - PID)
Я не хочу копіпастити фрагменти чужих статей про те, як саме працює USB, та деякі аспекти використання USB у STM32. Тому просто дам декілька посилань, де можна на дозвіллі почитати про USB: http://microtechnics.ru/osnovy-interfejsa-usb/ http://webhamster.ru/mytetrashare/index/mtb0/1410507212bb4zf8gacj http://radiokot.ru/circuit/digital/pcmod/63/ http://microtechnics.ru/mikrokontroller-stm32-i-usb/ http://microtechnics.ru/stm32-peredacha-dannyx-po-usb/ Ми можемо досить тривалий час заглиблюватися у вивчення USB інтерфейсу, та ми тримаємо у руках плату STM32F103 з USB. Ми готові негайно підключити її до комп`ютера. І нам вже кортить "помацати USB за вим`я". Тоді мерщій "переходимо до слайдів".

Бібліотека STM32 USB FS Device Lib

Для роботи з USB, існує бібліотека для STM32. Я використовую версію STM32_USB-FS-Device_Lib_V4.0.0. Архів з бібліотекою містить декілька прикладів. Нажаль, для CoIDE проектів немає. Зверніть увагу, що тактування USB інтерфейсу вимагає фіксованої частоти 48МГц. STM32_Clock_01 Я наведу два, на мій погляд, найбільш цікавих приклади. Перший: емуляція віртуального порту.

Віртуальний послідовний порт

Перш за все, нам треба подбати про те, щоб комп’ютер зміг адекватно сприйняти наш STM32 як послідовний порт. Для цього треба встановити драйвер, який дуже складно знайти на сайті st.com, тому я його виклав на GITHUB: https://github.com/avislab/STM32F103/tree/master/Example_USB_Virtual_Com_Port/Drivers Драйвер для Win7, Win8 - VCP_V1.4.0_Setup.exe, для WindowsXP - VCP_V1.3.1_Setup.exe. Ці драйвери потрібні тільки для Windows. Для Linux (Ubuntu) драйвер не потрібен. Ubuntu його і так розпізнає. Зазвичай Ubuntu бачить віртуальний порт як /dev/ttyACM0. Тепер пара слів про приклад Example_USB_Virtual_Com_Port. Після підключення прошитої плати з мікроконтролером до порта USB комп’ютера, комп’ютер сприйматиме її, як послідовний порт. У Windows це буде COM порт, у Linux - щось схоже на /dev/ttyACM0. У прикладі програма мікроконтролера реалізує лише відлуння (echo). Тобто, відправляє назад усі прийняті дані. Тому, коли Ви підключитесь до послідовного порту за допомогою термінальної програми (наприклад Putty), і почнете набирати текст, Ви побачите його на екрані терміналу. Якщо набрати символ `1` загориться світлодіод на платі, коли мікроконтролер отримає будь-який інший символ - він гасить світлодіод. Цей функціонал реалізований у головному циклі програми:

int main(void)
{
Set_System();
SetSysClockTo72();
Set_USBClock();
USB_Interrupts_Config();
USB_Init();
/* Initialize Leds mounted on STM32 board */
GPIO_InitTypeDef  GPIO_InitStructure;
/* Initialize LED which connected to PC13, Enable the Clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
while (1)
{
if (bDeviceState == CONFIGURED)
{
CDC_Receive_DATA();
// Check to see if we have data yet
if (Receive_length  != 0)
{
// If received symbol `1` then LED turn on, else LED turn off
if (Receive_Buffer[0]==`1`) {
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
}
else {
GPIO_SetBits(GPIOC, GPIO_Pin_13);
}
// Echo
if (packet_sent == 1) {
CDC_Send_DATA ((uint8_t*)Receive_Buffer,Receive_length);
}
Receive_length = 0;
}
}
}
}
Повний код прикладу можна скачати тут: https://github.com/avislab/STM32F103/tree/master/Example_USB_Virtual_Com_Port

Клавіатура і мишка

Цей приклад можна використати, коли треба створити пристрій на кшталт сканеру штрих-кодів, який емулює натиск клавіш на клавіатурі. Для використання  подібних пристроїв не потрібно спеціальних драйверів чи окремих програмних рішень. Після підключення до USB порту комп’ютера плата з мікроконтролером емулює послідовність натиску кнопок на клавіатурі (функція KEYBOARD_SEND_word), і  пересуває курсор мишки на один піксель праворуч і уверх (функція MOUSE_move):

int main(void)
{
Set_System();
SetSysClockTo72();
USB_Interrupts_Config();
Set_USBClock();
USB_Init();
while (1)
{
if (bDeviceState == CONFIGURED)
{
if (PrevXferComplete)
{
KEYBOARD_SEND_word("HELLO!!!");
MOUSE_move(1,-1);
//RHIDCheckState();
}
}
}
}
Бажано відкрити текстовий редактор і після цього підключати плату, тоді Ви зможете побачити як набирається текст "HELLO!!!". Зверніть увагу, що  мікроконтролер емулює натиск кнопок, а не передачу символів. Якщо у Вас буде включена українська розкладка ви побачите "РУДДЩ!!!" замість "HELLO!!!". Повний код прикладу можна скачати тут: https://github.com/avislab/STM32F103/tree/master/Example_USB_Keyboard

USB Mass Srorage

Цей приклад демонструє можливість використання Flash пам`яті мікроконтролера у якості USB носія, тобто невеличкої флешки. Розмір пам`яті доступний для використання усього 54Кб. З практичної точки зору це не має особливої цінності, але у деяких проектах можливість використовувати STM32 як USB Mass Storage може стати у нагоді.

#include "stm32f10x.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h"
int main(void)
{
Set_System();
Set_USBClock();
USB_Interrupts_Config();
USB_Init();
while (bDeviceState != CONFIGURED);
while (1)
{
}
}
Повний код прикладу можна скачати тут: https://github.com/avislab/STM32F103/tree/master/Example_USB_Mass_Storage

Захист USB

Нажаль, STM32 виявився слабким перед електростатичними зарядами на лініях USB (а можливо і не тільки на лініях USB). Ви з легкістю можете спалити порт мікроконтролера і навіть не помітити цього. Комп’ютер просто перестане розпізнавати STM32 як USB пристрій. Усі інші частини мікроконтролера можуть далі справно працювати і Вам може здатися, що це проблеми у контактах, чи у прошивці контролера. Нажаль, таке трапляється. STM32F103C8_01 Якщо пильно роздивитися цю плату, Ви не помітите нічого, що могло б захистити мікроконтролер від згубного впливу електростатичної напруги. Ніжки, які відповідають за USB, підключені до роз’єму через резистори 22 Ом. Для захисту USB  від статичних розрядів стандартно використовують супресори або TVS-диод (Transient Voltage Suppressor). Є спеціалізовані мікросхеми для USB - це збірка супрессорів з низькою ємністю, які не впливають на швидкість передачі даних. Деякі мікросхеми, які працюють с USB, мають вбудовані захисні супресори, але  STM32 - ні. Тому рекомендую подбати про безпеку USB у своїх розробках. Як вихід, можна зробити захисні перехідники - USB "тато-мама", а між ними - захисні діоди. Саме так я і зробив. Це вирішило мої проблеми зі статикою, особливо взимку, і не лише щодо STM32. В мене на комп’ютері часто висла мишка при підключенні до  USB будь чого, навіть простого USB кабелю. Таке рішення хоча і є дієвим, та на практиці виявилось не зовсім зручним. Детальніше про захист USB читайте тут: http://www.mirpu.ru/interface/86-usb/179-xaschita-usb.html Бажаю успіхів!

Дивись також:

STM32
Коментарі:
Сергій говорить:
08.11.2016 19:46
Чи є можливість зробити аналог виходу CBUS PWREN# в FT232RL?
Суть така (на прикладі світлодіода PC13): коли подаємо живлення на нашу плату - світлодіод не світиться (не повинен навіть блимнути), коли підключаємо через USB до хоста, після повної ініціалізаціі USB вмикаємо світлодіод. Без встановленного драйвера на хості світлодіод не повинен засвітитися взагалі. Навіщо це треба: для можливості включення живлення частини схеми приладу не одразу, а тільки після повної ініціалізації USB, коли хост виділить на порт 500мА. Актуально для приладів з живленням від USB. Нагадаю що згідно до вимог USB ми маємо обмежувати споживання нашим приладом до тих пір доки порт не буде налаштовано на видачу 500мА. В ідеалі споживати не більше 10мА, але я не впевнений що вдасться цього досягти, бо STM32 для роботи USB має тактуватися 72 МГц (?), а в такому випадку вона сама вже буде споживати більше ніж 10 мА.

andre говорить:
08.11.2016 21:41
Дякую за цікаве питання. Я спробую таке реалізувати, і якщо вийде поділюся досвідом.

andre говорить:
10.11.2016 11:31
Можна перевіряти bDeviceState. У прикладах саме так і робиться. Можуть бути наступні варіанти:

UNCONNECTED,
ATTACHED,
POWERED,
SUSPENDED,
ADDRESSED,
CONFIGURED.

Саме після CONFIGURED, якщо я не помиляюсь, можна спокійно вмикати живлення решті частині Вашого пристрою.

Сергій говорить:
10.11.2016 19:43
Дуже дякую. Спробую, відпишусь.

PS Чи дозволяє функціонал сайта отримувати сповіщення про оновлення та відповіді на коментарі?

Сергій говорить:
11.11.2016 00:48
Дуже дякую. Спробую.

Якаксь біда з коментарами тут. Втретє пишу за день, не хочу публікуватися,

Сергій говорить:
11.11.2016 00:53
Якщо можна - пару слів про підключення бібліотеки якої немає в списках CoIDE. Я так розумію, що STM32_USB-FS-Device_Lib_V4.0.0 підключалася саме вручну.

andre говорить:
14.11.2016 09:23
Нажаль ні.

Микола говорить:
31.01.2017 14:55
Підкажіть, будь-ласка.
В мене такий же девайс із програмою "Клавіатура і мишка". Комп його розпізнає коректно десь кожен 10-й раз, а так пише "Device Descriptor Failed".
Win 10-64, USB3, USB2. 
Як з цим поборотись?

Сергій говорить:
07.03.2017 16:29
Не можу знайти в статті найголовнішого. Яка ділянка коду відповідає за те, як саме наш пристрій роспізнається компом: VCP чи MASS Storage? Шукаю різницю в проектах, але можливо буде швдше, якщо хтось підкаже.

Papygai4ik говорить:
21.04.2020 18:30
Цей код призводить до неможливого підключення МК через ST-LINK
Якщо хтось має цю проблему, я її вирішив так:
1) У ST-Link Utility клацаємо на ST-LINK (зверху) -> Firmware update та 
 Чекаємо завершення процессу
2) Відключаємо ST-Link від USB
3) Підключаємо ST-Link
4) На самому МК тикаємо на кнопку Reset та тримаємо! у ST-Link Utility клацаємо на Target->Connect
5) Відпускаємо кнопку Reset
6) Післця цього очищаємо пам'ять Target->Erase chip

Додати коментар
Code
* - обов'язкові поля

Архіви