Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: как организовать передачу данных по USB из прерывания
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
NikP
Есть устройство на STM32F207, которое периодически вводит данные с датчика (внешний АЦП) и передаёт во внешний ПК по виртуальному COM порту , фирмвара - на базе примера для STM322хG-EVAL. Когда передача идёт из главного модуля программы - всё работает, но передача происходит через разные интервалы времени - видно зависит от занятости шины USB.

Программа примерно такая:
CODE

app.c
{
....
int main(void)
{
while (1) {..DataIN_OUT_toUSB(...) }
}
....
}

usbd_cdc_vcp.c
{
....
DataIN_OUT_toUSB(...){...}
....
}



Чтобы опрос АЦП и передача шли через равные интервалы, я решил сделать прерывание от таймера ( с интервалом ~ 2 мс - времени должно с запасом хватить на преобразование ) и из него вызывать функцию передачи :

CODE

app.c
{
....
int main(void)
{
while (1) {}
}
....
}

usbd_cdc_vcp.c
{
....
DataIN_OUT_toUSB(...){...}
....

void TIM7_IRQHandler(void)
{
TIM7->SR &= ~TIM_SR_UIF; // reset interrupt flag

DataIN_OUT_toUSB(...)

TIM_Cmd(TIM7, ENABLE); // start TIM7
}
}


В результате передача по USB вообще прекратилась. По осциллографу вижу синхроимпульсы, т.е. прерывания происходят, по отладчику вижу, что программа заходит в функцию DataIN_OUT_toUSB. А вот передачи по шине просто нет. В чём может быть дело? Ведь таймер на время выполнения функции остановлен.






A. Fig Lee
Не понятно как в деталях все это сделано и насколько автор знает работу USB.
Дивайс сам по себе не может ничего инициировать, он может приготовить данные и высылать по запросу от хоста.
Если Вы без запроса от хоста пытаетесь послать, ничего не получится
NikP
Согласен, что вопрос сформулирован достаточно косноязычно, но подробно расписывать (мне кажется) нет смысла - только место занимать.
Суть в следующем.
Написана фирмвара на основе примера STM. В программе есть функция DataIN_OUT_toUSB, которая опрашивает АЦП , пихает данные в массив на передачу по USB. Функция вызывается в модуле app.c ( обычно именуется main.с, но так сделано в примере - менять не стал), определена в модуле usbd_cdc_vcp.c. При этом всё работает - АЦП опрашивается, данные пихаются в буфер и идут наружу в ПК.
Изменил фирмвару - в модуле app.c оставил пустой цикл, а функцию стал вызывать из прерывания по таймеру из модуля usbd_cdc_vcp.c . Таймер сработал - вызвал функцию опроса АЦП, функция отработала, данные в буфере, снова запускается таймер. Всё прекрасно крутится - АЦП опрашивается, в буфер данные идут, а вот из буфера в USB не уходят. В чём может быть причина? Изменилось только то, что функция стала вызываться из другого места, сама она не изменилась.
WitFed
Очень вероятно, что прерывание от таймера имеет приоритет выше, чем от USB -- в ОС время очень важно.
Поэтому второе не происходит внутри первого, фунция DataIN_OUT_toUSB() ничего не видит и т.д...
Я бы лично в обработчике прерывания просто устанавливал флаг, в основном цикле его ждал и вызывал DataIN_OUT_toUSB().
Хотя если в последней есть просто поллинг запроса от хоста на заполнение ответной фифошки USB, то она (очень!) не всегда сможет попасть на него и вернуть нужные данные. Тогда живым будет только оригинальный непрерывный вариант.
USB -- вещь очень громоздкая, без изучения хотя бы основ и даташита на контроллер в этой части обычные понятия fread/fwrite будут работать редко. Возможно, если просто так данных напихать "впрок" в фифошку после их насчитывания, то они сотрутся прерыванием от USB при запросе хоста, именно в котором и должны быть напиханы only.
Я бы лично без отладчика эти вещи и не трогал -- там хоть можно поставить точку останова на любой стадии и пару операций ухватить замедленно в понимательный орган, потом всё порушится, начать сначала, переставить ТО чуть далее... Составить общую картину потом.
billidean
Так-то автор пишет, что
Цитата
АЦП опрашивается, в буфер данные идут
. Правда, он не сказал, как он это выяснил, методом медитации или отладчиком. То, что осциллографом видны тики таймера еще не говорит, что "АЦП опрашивается, в буфер данные идут".
Я не знаю наполнение функции DataIN_OUT_toUSB, но не может ли получиться так, что 2мс не хватает (или хватает, но впритык) для полного выполнения этой ф-ции, и МК почти все время висит в обработчике таймера?
Раньше все работало, потому что не было жесткой привязки к запуску этой ф-ции, т.е. когда закончила (может это занимало и более 2мс), тогда и опять начала выполняться, но при этом она могла быть прервана контроллером USB.
NikP
Спасибо за замечание A. Fig Lee - до меня дошло, что мой подход идеологически неправильный, мою задачу надо решать по-другому.

Поэтому вопрос по теме представляет уже чисто спортивный интерес.
Значит что касается DataIN_OUT_toUSB :
CODE
void DataIN_OUT_toUSB (void)
{
...
Capture_and_convert(..)//опрос датчиков, преобразование и заполнение массива Data[i] данными с АЦП
...
VCP_DataTx ((uint8_t*)&Data, 4096);
...

}



После прошивки МК запускал программу под отладчиком ( оба варианта!!! - с вызовом DataIN_OUT_toUSB из модуля арр.с и из прерывания по таймеру) - отладчик показал, что в обоих вариантах программа заходит в VCP_DataTx, но в первом случае данные в шину передаются, во втором - нет . Контроль данных в шине USB проводил USB-монитором. Приоритет прерывания для таймера поставил самый низший (точнее - перебирал методом тыка от 5 до 85), интервал перезагрузки таймера отрабатывал разный - от 2 мс до 10 мс. Неужто за 10 мс USВ данные не передаст?


Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.