Продолжаем работать с интерфейсом USB, и сегодня пришло время практики. Как вы помните, теоретические аспекты мы уже рассмотрели (вот), так что сегодня возьмем в руки STM32 и напишем небольшой примерчик. Сразу скажу, что я решил поэкспериментировать с контроллером STM32F303 и, соответственно, с платой STM32F3Discovery.
На плате уже есть два USB разъема, один под ST-Link и второй для пользовательских задач, то есть как раз то, что нам надо.
С платой разобрались, теперь по поводу софта. STMicroelectronics любезно предоставили библиотеки для работы с USB для различных семейств микроконтроллеров, а кроме того, выпустили кучу примеров под разные отладочные платы. Но плат Discovery в этом списке нет, поэтому не станем вносить свои изменения в уже готовые проекты от ST, а лучше создадим свой новый проект, взяв из примеров и библиотек только то, что нам реально понадобится.
Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32, а также несколько статей на смежную тему из нового курса:
Задача будет такая - по приему байта данных по USB, контроллер зажигает определенное количество светодиодов. Если пришел байт 0х01 - светится один диод, 0х02 - два, 0х03 - три, ну и так далее. Для того, чтобы реализовать отправку данных с компьютера, поставим драйвер виртуального ком-порта и будем общаться с платой через обычный терминал (я использую Advanced Serial Port Monitor).
Нужный драйвер без проблем можно скачать на официальном сайте STMicroelectronics. Устанавливается тоже без проблем и в итоге в диспетчере устройств появляется следующее:
С этим разобрались, давайте теперь откроем какой-нибудь примерчик от ST и посмотрим как же вообще в их библиотеках устроен обмен данными по USB. Вот архив со всеми библиотеками и примерами - ST USB Library.
Заходим в папку с примерами и выбираем Virtual Com Port, там без труда находим нужную нам папку с проектом для Keil'а и запускаем его. Давайте сразу же посмотрим на файл main.c:
int main(void) { Set_System(); Set_USBClock(); USB_Interrupts_Config(); USB_Init(); while(1) { } }
Видим, что в теле цикла while(1) пусто, соответственно вся работа происходит в прерываниях. В функции main() всего лишь вызываются функции инициализации. Все эти функции реализованы в файле hw_config.c, его мы поправим под себя чуть позже. Для приема и передачи данных по USB в файле usb_endp.c предусмотрены соответствующие обработчики:
void EP1_IN_Callback (void) void EP3_OUT_Callback(void)
Как вы помните из предыдущей статьи, транзакции IN нужны для передачи данных хосту (то есть ПК), а транзакции OUT для приема данных от хоста. Соответственно, для отправки данных используется конечная точка 1 (End Point 1), а для приема - End Point 3. Как программа попадает в эти обработчики? Сейчас разберемся! В файле stm32_it.c есть обработчик прерывания:
void USB_LP_CAN1_RX0_IRQHandler(void)
В его теле вызывается всего лишь одна функция - USB_Istr(), которая описана в файле usb_istr.c. Идем в этот файл и изучаем функцию... А там все в принципе просто, программа выясняет какое именно событие вызвало прерывание и в соответствии с этим происходит дальнейшая работа. Соответственно, при транзакциях IN или OUT вызываются именно те функции которые мы уже рассмотрели выше, а именно:
void EP1_IN_Callback (void) void EP3_OUT_Callback(void)
Этот проект вообще по умолчанию адаптирован для контроллеров STM32F10x, да и файлов очень много лишних, так что давайте-ка создадим свой новый пустой проект и в нем уже будем работать. Напоминаю, что я буду работать с STM32F3Discovery, поэтому проект создаю для контроллера STM32F303VC. Забираем из папки с библиотеками и примерами все файлы, которые нам понадобятся. Вот их полный список:
В папку SPL я просто запихал все файлы из Standard Peripheral Library для STM32F303. Не забываем в настройках проекта указать все пути к файлам и прописать подключение SPL ( в общем, все как тут - ссылка). Проект создан, файлы все на месте, давайте писать код. И начинаем с функций инициализации, расположенных в файле hw_config.c:
void Set_System(void) { GPIO_InitTypeDef GPIO_InitStructure; // Включаем тактирование нужной периферии RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); // Настройка пинов GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_15 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_12 | GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_14); GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_14); // Внешнее прерывание, которое внутри контроллера подключено к // функциям USB EXTI_ClearITPendingBit(EXTI_Line18); EXTI_InitStructure.EXTI_Line = EXTI_Line18; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }
Что за пины мы настраиваем тут? А вот:
С PA11 и PA12 разобрались, а все остальные ножки - это светодиоды, которые есть на плате.
Идем дальше... Из функций для работы с USART'ом я просто все удалил, поскольку мы приемопередатчиком пользоваться не будем. Настраиваем прерывания:
void USB_Interrupts_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_Init(&NVIC_InitStructure); }
И еще я добавил небольшую функцию в этот же файл. Она просто гасит все светодиоды:
void GPIO_ResetLeds() { GPIO_ResetBits(GPIOE, GPIO_Pin_8); GPIO_ResetBits(GPIOE, GPIO_Pin_9); GPIO_ResetBits(GPIOE, GPIO_Pin_10); GPIO_ResetBits(GPIOE, GPIO_Pin_11); GPIO_ResetBits(GPIOE, GPIO_Pin_12); GPIO_ResetBits(GPIOE, GPIO_Pin_13); GPIO_ResetBits(GPIOE, GPIO_Pin_14); GPIO_ResetBits(GPIOE, GPIO_Pin_15); }
Не забываем в файл hw_config.h дописать прототип для этой функции:
void GPIO_ResetLeds(void);
С инициализацией вроде бы все. Открываем файл usb_endp.c. Мы будем только анализировать принятые от хоста данные, поэтому обработчик транзакций IN нам не понадобится:
void EP1_IN_Callback (void) { }
В обработчике транзакций OUT принимаем данные и в зависимости от того, какой байт принят зажигаем определенное количество светодиодов, которые у нас висят на GPIOE:
void EP3_OUT_Callback(void) { uint16_t USB_Rx_Cnt; // Принимаем данные USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, USB_Rx_Buffer); // Анализируем принятый байт switch(USB_Rx_Buffer[0]) { case 0x01: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0x0100); break; case 0x02: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0x0300); break; case 0x03: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0x0700); break; case 0x04: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0x0F00); break; case 0x05: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0x1F00); break; case 0x06: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0x3F00); break; case 0x07: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0x7F00); break; case 0x08: GPIO_ResetLeds(); GPIO_Write(GPIOE, 0xFF00); break; } // Включаем прием данных для конечной точки 3 SetEPRxValid(ENDP3); }
Так... Ну вроде бы на этом все. Вот полный проект: Проект для USB
Прошиваем микроконтроллер и тестируем! Вот, что получилось:
Послали байт 0х04 - загорелось 4 светодиода, аналогично работает и для любого другого количества светодиодов. Так что, на сегодня, пожалуй все, но опыты с USB, на этом только начинаются!
А не могли бы Вы дать подсказку как настроить передачу, с помощью функции USB_SIL_Write(), и может ли плата только передавать хосту, не принимая ничего.
В принципе при передаче все точно также, callback само собой для транзакций IN используется
Огромный респект и спасибо автору. Начал практическое изучение МК с STM32, до этого была только теория. Очень интересует тема управления контроллером с компа по USB, прием-передача данных, настройка параметров периферии (например, задание частоты дискретизации АЦП). Опробовал Ваш проект из этой статьи на STM32F3Discovery. При компиляции выскочило 3 предупреждения, вот они:
..\source\hw_config.c(198): warning: #188-D: enumerated type mixed with another type
return 0;
..\source\usb_endp.c(74): warning: #550-D: variable "USB_Rx_Cnt" was set but never used
uint16_t USB_Rx_Cnt;
linking...
.\usb.axf: Warning: L6304W: Duplicate input file .\system_stm32f30x.o ignored.
Но все заработало на ура.
С нетерпением буду ждать новых (а лучше расширенного цикла) статей на эту тематику.
Спасибо за описание, но проект по ссылке не полный нет файла самого проекта и он не собирается сразу.
Сорри. Всё нормально. У меня архив чем-то порезало
=))
Доброе время суток! 🙂
очень хорошая статья! большое спасибо! вот начинаю пробовать работать с ЮСБ, очень интересно! вот только вопросы возникают! можно ли на 10х процессорах сделать преобразователь например в 2 кома, или сделать хид клавиатуры и мыши? или хотябы на 207?! по одному устройству примеры работоспособны. заранее спасибо!
HID можно я думаю без проблем сделать)
буду пробовать! 🙂
Пиши, если будут какие-нибудь трудности )
Здравствуйте.
Спасибо за статью. Но появились проблемы при отладке. Постоянно возникает прерывание USB_LP_IRQHandler. Это нормально? При этом отладчик уходит в завис и прервать его можно только насильно. Процессор STM32F373V8, установленный в STM32F3Discovery вместо 303-го. Может в этом проблема кроется?
Пробовал и исходный проект от STM - тоже самое.
Видимо да, проблема в контроллере
Здравствуйте.
Подскажите пожалуйста, а как переменную типа uint32_t ( ADC_Result из вашей статьи Работа с ADC и DMA) можно передать по USB, так как в этом проэкте переменная которая передается по USB - типа uint8_t.
Заранее благодарен за ответ!
Передавать 4 байта просто:
ADC_Result_1 = (ADC_Result & 0xFF000000) >> 24;
ADC_Result_2 = (ADC_Result & 0x00FF0000) >> 16;
ADC_Result_3 = (ADC_Result & 0x0000FF00) >> 8;
ADC_Result_4 = (ADC_Result & 0x000000FF);
или так:
uint8_t tBuff[4];
uint32_t *tADC;
tADC = (uint32_t) tBuff;
*tADC = ADC->DATA;
Здравствуйте.
Подскажите пожалуйста, программировал через Keil было все в норме потом вдруг стало. Error
No target connected.
Flash Download failed-Target DLL has beeh cancelled. На втором компе уже такое произошло. Дрова переустанавливал не помогло. Через STM32 ST-LINK Utility зашивает без проблем.
Может настройки в Кейле слетели?
Нет все настройки на месте. Сам не пойму почему так.
Здравствуйте. А может уважаемый автор выложить проект под STM32F10x, который, как я понял, он брал за основу, а то чего-то проект собрать не получается.
Да, и где в проекте вышеизложенная функция:
void EP3_OUT_Callback(void). Она в main.c отсутствует.
И еще, можно по подробнее о функциях USB_SIL_Write и USB_SIL_Read, можно ли просто бит считать без всяких буферов?
этот вопрос отпал)
Под F1 у меня нет проекта - надо на сайте ST смотреть, вроде бы у них были примеры.
Только пример от ST глюченый, мк без соединения с компом зависает намертво даже отладчик от него отваливается.
Вроде бы, STM32 с нуля, а как его питать, шить и отлаживать статей нет. Все на готовых платах.
Ну "с нуля", но в разумных пределах ) Нет никакого смысла делать платы, которые уже есть, лучше изучить программирование и сделать что-то новое и интересное. Если есть конкретные вопросы по схемам подключения, то на каждую плату ST можно найти официальную принципиальную схему, опять же, нет смысла дублировать их документацию и копировать схемы, которые и так можно найти.
Тогда это не STM32 с нуля, а программирование STM32 для начинающих.
С нуля, это как у буржуев, когда закрыта пропасть между МК и готовой платой, а в этой пропасти односторонняя макетка утюгом, прошивка всеми способами, моргание лампочкой, отладка и прочие радости.
Ну из всего перечисленного не описана разве что макетка утюгом, это же "STM с нуля", а не "ЛУТ с нуля".
Может Вы открыли рубрику "STM32 с нуля" и не пролистали страницы до первых записей, и поэтому возникло недопонимание?)
Скажите пож что делать Я запрограммировал STM32SISCOVERY проектом который вы выложили, но после этого не могу больше запрограммировать чип Программатор выдает : Internal command error Похоже , что где-то установилась защита по записи в чип. Спасибо
При программировании попробуй так:
- зажимай кнопку reset на плате
- нажимай кнопку Program
- через секунду-две отпускай кнопку reset
Спасибо за статью. Наконец-то удалось запустить usb на stm32f3discovery. Возникла такая проблема. Если я использую библиотеки из Вашего проекта в своем проекте, то все работает нормально. Если же я беру исходные ST USB Library то проект не собирается, хотя список файлов, прикрепленных к проекту, идентичен. Нужно ли вносить какие-либо изменения в библиотеки, за исключением описанных Вами в статье? Хотел бы разобраться в этом вопросе, т к собираюсь использовать usb библиотеку для stm32f103.
Вроде бы я тут все описывал, что менял в файлах библиотек...
Посмотрел внимательнее - в Вашем проекте отличается заголовочный файл platform_config.h, раздел include. Но даже после его исправления проект не собрался, похоже есть еще какие-то различия.
Установил все драйвера с официального сайта. USB ST-LINK работает исправно, а вот при подключении разъема USB USER в диспетчере устройств плата отображается как Unknown Device. Подскажите пожалуйста, в чем может быть проблема ?
А драйвер virtual com-port поставил?
Добрый день, что означают эти строчки ?
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
Где можно почитать это?
В даташите описаны режимы, в которых может работать вывод микроконтроллера. В этих строках вывод просто настраивается.
Могли бы Вы указать страницу даташита
Разобрался
Ставил, даже несколько разных скачивал
Тогда еще вариант ) Может система 64 битная? Были случаи (и не единичные), когда на х64 отказывалось напрочь работать.
Та же проблема - virtual com-port установил, com-порт не появился, при подключении USB USER появляется сообщение -> Unknown Device.
У меня Win 7 32 бит
Сам понял свою ошибку - пытался подключить непрошитое устройство. После прошивки примера - все заработало и com-порт появился.
Хорошо, что заработало )
Здравствуйте! Пытаюсь собрать проект в Keil, но выходят ошибки. Не подскажите в чём проблема.
src\hw_config.c(68): warning: #177-D: variable "GPIO_InitStructure" was declared but never referenced
GPIO_InitTypeDef GPIO_InitStructure;
src\hw_config.c(231): error: #20: identifier "EVAL_COM1_IRQn" is undefined
NVIC_InitStructure.NVIC_IRQChannel = EVAL_COM1_IRQn;
src\hw_config.c(257): error: #20: identifier "USB_DISCONNECT" is undefined
GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
src\hw_config.c(257): error: #20: identifier "USB_DISCONNECT_PIN" is undefined
GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
src\hw_config.c(261): error: #20: identifier "USB_DISCONNECT" is undefined
GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
src\hw_config.c(261): error: #20: identifier "USB_DISCONNECT_PIN" is undefined
GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
src\hw_config.c(291): warning: #223-D: function "STM_EVAL_COMInit" declared implicitly
STM_EVAL_COMInit(COM1, &USART_InitStructure);
src\hw_config.c(291): error: #20: identifier "COM1" is undefined
STM_EVAL_COMInit(COM1, &USART_InitStructure);
src\hw_config.c(294): error: #20: identifier "EVAL_COM1" is undefined
USART_ITConfig(EVAL_COM1, USART_IT_RXNE, ENABLE);
src\hw_config.c(376): warning: #223-D: function "STM_EVAL_COMInit" declared implicitly
STM_EVAL_COMInit(COM1, &USART_InitStructure);
src\hw_config.c(376): error: #20: identifier "COM1" is undefined
STM_EVAL_COMInit(COM1, &USART_InitStructure);
src\hw_config.c(395): error: #20: identifier "EVAL_COM1" is undefined
USART_SendData(EVAL_COM1, *(data_buffer + i));
src\hw_config.c(451): error: #20: identifier "ENDP1_TXADDR" is undefined
UserToPMABufferCopy(&USART_Rx_Buffer[USB_Tx_ptr], ENDP1_TXADDR, USB_Tx_length);
src\hw_config.c(468): error: #20: identifier "EVAL_COM1" is undefined
USART_Rx_Buffer[USART_Rx_ptr_in] = USART_ReceiveData(EVAL_COM1) & 0x7F;
src\hw_config.c(472): error: #20: identifier "EVAL_COM1" is undefined
USART_Rx_Buffer[USART_Rx_ptr_in] = USART_ReceiveData(EVAL_COM1);
src\hw_config.c(495): error: #20: identifier "ID1" is undefined
Device_Serial0 = *(uint32_t*)ID1;
src\hw_config.c(496): error: #20: identifier "ID2" is undefined
Device_Serial1 = *(uint32_t*)ID2;
src\hw_config.c(497): error: #20: identifier "ID3" is undefined
Device_Serial2 = *(uint32_t*)ID3;
src\hw_config.c: 3 warnings, 15 errors
compiling stm32_it.c...
.\inc\hw_config.h(53): error: #20: identifier "FunctionalState" is undefined
void USB_Cable_Config (FunctionalState NewState);
.\inc\hw_config.h(56): error: #20: identifier "uint8_t" is undefined
void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes);
.\inc\hw_config.h(56): error: #20: identifier "uint8_t" is undefined
void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes);
src\stm32_it.c(187): error: #20: identifier "EVAL_COM1" is undefined
if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)
src\stm32_it.c(194): error: #20: identifier "EVAL_COM1" is undefined
if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)
src\stm32_it.c: 0 warnings, 5 errors
compiling usb_endp.c...
src\usb_endp.c(89): error: #20: identifier "ENDP1_TXADDR" is undefined
UserToPMABufferCopy(&USART_Rx_Buffer[USB_Tx_ptr], ENDP1_TXADDR, USB_Tx_length);
src\usb_endp.c(103): error: #247: function "NOP_Process" has already been defined
void EP3_OUT_Callback(void)
src\usb_endp.c: 0 warnings, 2 errors
compiling usb_prop.c...
src\usb_prop.c(173): error: #20: identifier "ENDP1_TXADDR" is undefined
SetEPTxAddr(ENDP1, ENDP1_TXADDR);
src\usb_prop.c(179): error: #20: identifier "ENDP2_TXADDR" is undefined
SetEPTxAddr(ENDP2, ENDP2_TXADDR);
src\usb_prop.c(185): error: #20: identifier "ENDP3_RXADDR" is undefined
SetEPRxAddr(ENDP3, ENDP3_RXADDR);
src\usb_prop.c: 0 warnings, 3 errors
".\5.axf" - 25 Error(s), 3 Warning(s).
Скорее всего файлы не подключены к проекту, в которых определяются переменные, на которые компилятор ругается
Готовый ваш проект работает нормально, но если пытаюсь собрать сам, то лечу в ошибку:
system_stm32f30x.c: Error: C4065E: type of input file 'USB' unknown
И ещё, у вас в списке указаны файлы и около них стоят плюсики, а у меня их нет.
Так же в списке нет файла hw_config.h, хотя у вас написано:
"Не забываем в файл hw_config.h дописать прототип для этой функции:
void GPIO_ResetLeds(void);"
Похоже я упускаю где-то какую-то мелочь *think*.....
Попробовал поработать к STM32L-Discovery. Однако нарвался на вопрос -
что делать с файлом platform_config,h? Он подключён в hw_config.h и содержит некоторые определения и инклюды, некорректные без использования тех Eval Board, для которых пример предназначен.
Убери оттуда просто все лишнее или вообще удали этот файл, если там нет ничего нужного и include с ним удали.
Cпасибо за статью! не могли бы вы рассказать как сделать настройку на передачу данных в комп. никак не могу разобраться с USB_SIL_Write();
Вот статья про передачу, по идее как раз то, что тебе нужно )
https://microtechnics.ru/stm32-peredacha-dannyx-po-usb/
Спасибо!
Дмитрий, можно узнать какая была причина Вашей проблемы и как вы с ней справились?
В статье, походу, используется более старая версия библиотек. Та же проблема. Или придется разбираться в новых, или юзай то, что автор положил.
Здравствуйте! Приобрел программатор NAND на STM32F4. При коннекте определяется как linuxg_printer. Драйвер не могу найти и прогер работает без драйверов. Но запарило каждый раз это видеть. Что это за устройство? Может ему все-таки дрова дать? Найти их не могу, вот сведения об устройстве USBPRINT\LINUXG_PRINTER\7&2181D5ED&0&USB001
Добрый день! Подскажите пожалуйста! Хочу Ваш пример адаптировать под свою плату. Она на STM32F107RCTx. Подскажите что нужно убрать и поправить в готовом проекте, не считая того что все ЧТО ДЛЯ STM32F4 заменить на STM32F1 ну там библиотеки и прочее. USB разъем совпадает полностью по схеме, а диоды у меня на РА4-7. Схему могу привести, если нужно. Главное что убирать, чтобы лишнего не было. А то я сделал сходу (то что изложил) и осталась одна ошибка: ..\Virtual_COM_Port\src\system_stm32f10x.c(261): error: #20: identifier "FLASH_BASE" is undefined
На самом деле проще всего создать вообще пустой проект для нового контроллера, а потом в него перетащить по очереди все файлы
Спасибо! Попробую!
Сделал все свое! Не пойму что править или откуда брать - platform_config.h На него ссылается и ошибки выдает, там моей платформы нет, мне что там все закоментировать?
Да, то что там определяется сделай под свою плату, а все остальное можно убрать.
Спасибо!
Вылезла вот такая ошибка:
source\hw_config.c(70): error: #20: identifier "RCC_APB2Periph_SYSCFG" is undefined
Что не сделал или убрал лишнее?
Я это прописал согласно настройкам в примере, где не описаны? Чего не хватает?
На другой шине скорее всего просто висит - APB1 или AHB, надо в исходниках SPL посмотреть.
Спасибо за подсказку! Рою далее.
А как быть если нужно отправить 2 посылки хосту через УЗБ?
Например:
CDC_Send_DATA ("One", 3);
CDC_Send_DATA ("Two", 3);
То в терминалку приходит только последняя отправленная строка. Если выждать хотя бы 1мс, то обе посылки проходят нормально.
Ну логично по сути. Функция кладет в буфер данные, хост раз в 1 мс забирает.
Так, а как можно обойти это ожидание без "костылей"? Часто есть потребностью в подобной отправке данных, использовать ф-цию задержки выглядит как "костыль" при чем не очень хороший, вот с ЮАРТом все проще - отправили символ - ждем в цикле флаг. С УЗБ можно что-то подобное сделать?
6 байт сразу отправлять вместо двух раз по 3)
Это не всегда удобно. Так нет никакого флага на проверку того, что можно следующую порцию данных отправлять?
Ну кадр вообще начинается с SOF-пакета (start of frame), можно в исходниках драйвера USB найти обработку этого пакета и туда добавить выставление флага.
А коллбеке - EP1_IN_Callback если выставлять флаг? По идее же эта ф-ция выполняется, когда данные были отправлены или я не прав?
Да, можно и там.
Да, так получилось.
Выставлю флаг в коллбеке EP1_IN_Callback, а в ф-ции отправки данных жду пока этот флаг выставиться.
Подскажите пожалуйста,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
Устанавливает "1" в RCC_APB2ENR, AFIOEN[0] бит.
AFIOEN: Alternate function IO clock enable
За что этот бит отвечает? Какие "Alternate function" он enable-ит?
Заранее - спасибо!
Извиняюсь, моя вина.
Не в тот мануал заглянул.
Подскажите пожалуйста последовательность - какие прерывания генерирует USB, где находится обработчик этих прерываний и как вообще программа попадает в функции EP3_IN/OUT_Callback?
Сначала void USB_LP_CAN1_RX0_IRQHandler(void), затем USB_Istr()
Спасибо за статью, все работает. Возник небольшой вопрос, после прошивки и запуска отладчика, bDeviceState у меня равен 0 (UNCONNECTED) хотя плата сразу подключена к компу через usb и нормально отображается в устройствах. И для того чтобы bDeviceState сменился на рабочий CONFIGURED необходимо переткнуть usb. Подскажите, что необходимо вызывать для конфигурирования usb при инициализации в рабочий режим.
Advanced Serial Port Monitor установилась вроде бы нормально но виртуальный COM порт в диспетчере устройств не отобразился. Пробовал на 3 компьютерах с разными версиями Windows и разрядностью системы. Одно и тоже... установку произвожу согласно файла readme.
И еще не совсем ясно могу возможно ли используя Advanced Serial Port Monitor осуществить обмен между ПК и МК как Вашей статье :
https://microtechnics.ru/qt-usb-custom-hid-biblioteka-libusb/
и
https://microtechnics.ru/stm32cube-usb-custom-hid-priem-i-peredacha-dannyx/
Вместо программы написанной на Qt.
Нет, через Advanced Serial Port Monitor только если реализован класс виртуального ком-порта на микроконтроллере, с hid так не получится. И, соответственно, com-порт появится только если контроллер подключить, сам терминал com-порт не создает.