Главная » Микроконтроллеры » Микроконтроллер STM32 в качестве преобразователя USB-2xRS232

Микроконтроллер STM32 в качестве преобразователя USB-2xRS232

Данное решение обеспечивает 2 виртуальных последовательных порта, которые могут использоваться независимо одновременно. Проект не поддерживает RTS, линии DTR и т. Д., Но их можно легко добавить (за исключением линии CTS, которая не поддерживается классом USB CDC). Электрическая схема предлагаемого решения приведена на рис. 1.

Рис. 1. Электрическая схема преобразователя

В проекте может использоваться один или два виртуальных последовательных порта, в зависимости от определений, содержащихся в заголовке converter.h. Наиболее важный элемент этого файла для конфигурации показан на примере 1.

Пример 1. Параметры конфигурации проекта

#define USE_VCOM1 1
#define USE_VCOM2 1
#if (USE_VCOM1)
#define VCOM1_USART_NUM 1
#endif
#if (USE_VCOM2)
#define VCOM2_USART_NUM 2
#endif

Если для определения USE_VCOMx задано значение 1, выбранный виртуальный COM будет виден на компьютере. Определение VCOMx_USART_NUM указывает, к какому физическому последовательному порту процессора подключаться. Чтобы иметь возможность одновременно передавать данные в два USART, они были подключены к USB с использованием кольцевых буферов, и вся передача происходит с прерываниями, как показано на рис. 3.

Рис. 3. Модель передачи данных через конвертер

Два виртуальных устройства vcom1 и vcom2 видны со стороны USB и библиотеки vCOM. Когда мы получаем данные через выбранный vcom с компьютера, мы перезаписываем их в кольцевой буфер отправки (назначенный данному порту USART) и разрешаем прерывание при отправке данных через USART. В этом прерывании мы проверяем, есть ли данные в буфере отправки — если это так, то мы читаем и отправляем их — если нет, то мы блокируем прерывание.

Аналогично в случае получения данных USART — если генерируется прерывание приема, мы вводим полученные данные в буфер приема. Когда данный vcom может отправлять дополнительные данные на хост, вызывается соответствующая функция, связанная с данным объектом vcom. Он проверяет, есть ли у нас данные в приемном буфере порта USART, с которым работает данный vcom. Если есть какие-либо данные, то мы читаем столько, сколько можно отправить в одном пакете на хост, и отправляем его.

Основным элементом конвертера является файл converter.c. Его заголовок содержит все необходимые настройки — отображение элементов vcom на отдельные порты USART, номера портов и контакты интерфейсов USART и т. Д.

Инициализация библиотеки USB выполняется при запуске системы. Не вдаваясь в подробности, скажем, что мы используем готовый компьютер для создания конфигураций, благодаря чему создание дескриптора конфигурации и необходимых структур, используемых библиотекой USB, очень просто. Инициализация USB осуществляется с помощью функции, показанной в примере 2 .

Пример 2. Функция запуска интерфейса USB в микроконтроллерах STM32

void usbd_init (void) {
USBD_device_descriptor * usbd_dev_desc;
CCM_session_params ccm_session;
// -----------------------------
// Инициализация конфигурации
// -----------------------------
// открыть конфигурацию для автоматического создания
// используя библиотеку CCM
CCM_open_config (USBD_STM32, & usbdc, & ccm_session);
// добавление виртуального последовательного порта (vCOM)
// (или 2 vCOM) к конфигурации, которую мы создаем
#if (USE_VCOM1)
CDC_VCOM_add_item (& (vcom1_params.vcom), & ccm_session);
#endif
#if (USE_VCOM2)
CDC_VCOM_add_item (& (vcom2_params.vcom), & ccm_session);
#endif
// закрываем сеанс CCM и устанавливаем конфигурацию
// - после выхода из этой функции у нас есть готовый дескриптор конфигурации
// в массиве usbd_conv_descriptor и заполнены и установлены
// структура usbdc.
CCM_close_and_install_config (usbd_conv_descriptor, & ccm_session);
// ------------------------------------------------ ----
// Изменить поля дескриптора устройства (Devce Descriptor)
// ------------------------------------------------ ----
usbd_dev_desc = USBD_get_dev_descriptor_pointer (
& usbdc);
// здесь заполняем параметры vendorID и productID
// выборочные значения, установленные в этом проекте, как в демонстрационной версии ST
usbd_dev_desc-> idVendor = 0x0483;
usbd_dev_desc-> idProduct = 0x5740;
// какую версию USB мы используем
usbd_dev_desc-> bcdUSB = 0x0110;
// класс устройства немедленно информирует вас
// что это устройство связи
usbd_dev_desc-> bDeviceClass = 0x02;
// ------------------------------
// Необязательные элементы
// ------------------------------
// установить строку
USBDS_install ((uint8_t *) Manufacturer_String_Descriptor,
& (usbd_dev_desc-> iManufacturer),
& usbdc);
USBDS_install ((uint8_t *) Product_String_Descriptor,
& (usbd_dev_desc-> iProduct),
& Usbdc);
// подготовить SerialNumber_String_Descriptor
SerialNumber_fill ();
USBDS_install ((uint8_t *) SerialNumber_String_Descriptor,
& (usbd_dev_desc-> iSerialNumber),
& Usbdc);
// наконец - включить периферийные устройства USB
USBD_activate (& usbdc);
}

Он создает и устанавливает конфигурацию (вызывая первые 4 функции), а затем дополнительно изменяет некоторые поля дескриптора устройства и устанавливает строки — строки Unicode, описывающие устройство.

Конфигурация, созданная для двух объектов vcom, имеет 4 интерфейса: 2 интерфейса CCI (Communication Class Interface) для уведомления и 2 CDI (Communication Data Interface) для передачи данных. Каждый интерфейс CCI имеет одну конечную точку типа прерывания, в то время как интерфейс CDI имеет 2 конечных точки массового типа — один IN и один OUT для передачи данных Tx и Rx данного объекта vcom.

Отсюда следует, что виртуальный последовательный порт имеет 3 конечных точки. Микроконтроллеры STM32 со встроенными интерфейсами USB имеют 8 из них, поэтому легко подсчитать, что вы можете реализовать макс. 2 виртуальных COM. Они получат 7 конечных точек — 3 из 2 портов + нулевая точка, всегда используемая для передачи управления.

Инициализация порта USART происходит  в соответствии с идеей класса CDC — только во время работы преобразователя, когда с хоста поступает запрос на открытие порта. В этот момент соответствующая функция, связанная с объектом vcom, вызывается библиотекой CDC. Он анализирует рабочие параметры порта USART, отправленные хостом.

В этом приложении реализованы такие параметры настройки, как: скорость передачи, количество стоп-битов и тип четности. Затем для этой цели вызывается простая функция для инициализации порта USART, показанная для примера 3 .

Пример 3. Функция инициализации порта USART

static void configure_usart (uint8_t usart_num,
uint32_t скорость передачи, uint16_t stop_bits,
uint16_t patity, uint8_t enable_irq) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
USART_TypeDef * USARTx;
GPIO_TypeDef * GPIO_Rx_Port;
GPIO_TypeDef * GPIO_Tx_Port;
uint16_t GPIO_Rx_Pin;
uint16_t GPIO_Tx_Pin;
uint8_t NVIC_IRQChannel;
// определить номер USART, перезагрузить периферийное устройство и включить его часы
{
if (usart_num == 1) {
USARTx = USART1;
GPIO_Rx_Port = USART1_RX_PORT;
GPIO_Tx_Port = USART1_TX_PORT;
GPIO_Rx_Pin = USART1_RX_PIN;
GPIO_Tx_Pin = USART1_TX_PIN;
NVIC_IRQChannel = USART1_IRQn;
// сбросить периферийное устройство и включить его часы
RCC_APB2PeriphResetCmd (RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphResetCmd (RCC_APB2Periph_USART1, DISABLE);
RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1, ENABLE);
}
else if (usart_num == 2) {
USARTx = USART2;
GPIO_Rx_Port = USART2_RX_PORT;
GPIO_Tx_Port = USART2_TX_PORT;
GPIO_Rx_Pin = USART2_RX_PIN;
GPIO_Tx_Pin = USART2_TX_PIN;
NVIC_IRQChannel = USART2_IRQn;
// сбросить периферийное устройство и включить его часы
RCC_APB1PeriphResetCmd (RCC_APB1Periph_USART2, ENABLE);
RCC_APB1PeriphResetCmd (RCC_APB1Periph_USART2, DISABLE);
RCC_APB1PeriphClockCmd (RCC_APB1Periph_USART2, ENABLE);
}
else if (usart_num == 3) {
USARTx = USART3;
GPIO_Rx_Port = USART3_RX_PORT;
GPIO_Tx_Port = USART3_TX_PORT;
GPIO_Rx_Pin = USART3_RX_PIN;
GPIO_Tx_Pin = USART3_TX_PIN;
NVIC_IRQChannel = USART3_IRQn;
// сбросить периферийное устройство и включить его часы
RCC_APB1PeriphResetCmd (RCC_APB1Periph_USART3, ENABLE);
RCC_APB1PeriphResetCmd (RCC_APB1Periph_USART3, DISABLE);
RCC_APB1PeriphClockCmd (RCC_APB1Periph_USART3, ENABLE);
}
else {
return;
}
}
// настроить GPIO
{
GPIO_InitStructure.GPIO_Pin = GPIO_Tx_Pin;
GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init (GPIO_Tx_Port, & GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Rx_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init (GPIO_Rx_Port, & GPIO_InitStructure);
}
// настройка периферийного устройства USART
// и включить его
{
USART_InitStructure.USART_BaudRate = скорость передачи данных;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = stop_bits;
USART_InitStructure.USART_Parity = patity;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// Инициализируем регистры
USART_Init (USARTx, & USART_InitStructure);
// Включить USART
USART_Cmd (USARTx, ENABLE);
}
// Включаем прерывание USART
if (enable_irq)
{
NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (& NVIC_InitStructure);
// Настройка передачи и получения ISR
USART_ITConfig (USARTx, USART_IT_TXE, ENABLE);
USART_ITConfig (USARTx, USART_IT_RXNE, ENABLE);
}
}

Эта функция разделена на разделы, иллюстрирующие, что необходимо делать для запуска порта USART на процессоре STM32.

В первом разделе указан номер порта, который мы инициируем, — 1, 2 или 3. Там же мы завершаем переменные функции и, что более важно, перезапускаем USART и инициируем часы в контроллере RCC. Это очень важное действие, потому что в процессоре STM32 у каждого периферийного устройства отключены часы, а после включения процессора все интерфейсы выключены.

Второй раздел настраивает линию GPIO. Для того чтобы USART мог взаимодействовать с внешним миром, необходимо настроить линии GPIO, поскольку по умолчанию после сброса процессора все они настроены как универсальные входные линии. Они должны быть установлены в режим: GPIO_Mode_AF_PP для линий Tx и GPIO_Mode_IN_FLOATING для Rx.

Третий раздел настраивает порт USART и включает его в свой собственный контроллер. Это делается с помощью библиотечных функций. Заполняем соответствующую структуру параметрами интерфейса и вызываем функцию инициализации. Затем выполните команду, чтобы включить порт.

В последнем разделе — если нам это нужно (и в этом приложении это необходимо) — следует настройка и включение прерывания порта USART в контроллере NVIC, а затем включение прерывания в его собственном контроллере. Мы настраиваем приоритеты канала и затем включаем генерацию данного прерывания при передаче и приеме.

Драйверы

В настоящее время конвертер работает с операционной системой Linux. Модуль CDC_ACM используется в качестве драйвера. Очень хорошо продуманная идея построения драйвера под эту операционную систему означает, что не имеет значения, обеспечивает ли устройство один или несколько виртуальных последовательных портов, запоминающее устройство большой емкости, устройство интерфейса HID и т. Д. Если это позволяет количество конечных точек, драйверы всегда будут обрабатывать их должным образом.

После подключения представленного конвертера к компьютеру обнаруживаются 2 устройства: / dev / ttyACM0 и / dev / ttyACM1, которые можно проверить в каталоге / dev / или в терминале с помощью команды dmesg, отображающей системный журнал — в конце вы должны увидеть что-то похожее на:

[5564.891091] usb 2-3.3: новое высокоскоростное USB-устройство с использованием ehci_hcd и адреса 5
[5565.004053] USB 2-3.3: конфигурация № 1 выбрана из 1 выбора
[5565.021979] cdc_acm 2-3.3: 1.0: Это устройство не может выполнять вызовы самостоятельно. Это не модем.
[5565.022006] cdc_acm 2-3.3: 1.0: ttyACM0: устройство USB ACM
[5565.022856] cdc_acm 2-3.3: 1.2: Это устройство не может выполнять вызовы самостоятельно. Это не
модем.
[5565.022880] cdc_acm 2-3.3: 1.2: ttyACM1: USB ACM-устройство

Эти файлы могут использоваться как обычные последовательные порты в Linux. Если файлы устройства не созданы, либо у нас не загружен модуль CDC_ACM, либо модуль не распознает номера VendorID и ProductID нашего устройства — тогда вы можете вручную передать эти номера контроллеру. Конечно, вы можете подключить больше таких устройств к вашему компьютеру — тогда у вас будет больше устройств ttyACMx.

Из-за особой идеи построения драйверов в Windows дело обстоит сложнее: драйвер, который используется с демонстрационной версией ST USB компании, работает здесь (после установки соответствующих VendorID и ProductID) только с одним виртуальным последовательным портом, использующим систему usbser.sys — с двумя, к сожалению, вам придется изменить драйвер.

Для скачивания

[USB / 2xRS232 конвертер в версии для Linux] (339,5 KiB, скачано: 292)

[USB / 2xRS232 конвертер для Windows] (1,4 MiB, скачано: 286)

3 комментария

  1. Здравствуйте, понравилась схема и хочу сделать по ней проект но картинка недостаточно четкая и поэтому можно ее сделать четче или выслать на почту, потому что не видно выводы и номиналы элементов. Спасибо

  2. здравствуйте, а есть ли к этой схеме проект печатной платы в сапр altium?

Оставить комментарий

Ваш email нигде не будет показан. Обязательные для заполнения поля помечены *

*