|
|
  |
как организовать передачу данных по USB из прерывания |
|
|
|
Sep 18 2014, 13:01
|
Частый гость
 
Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944

|
Есть устройство на 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. А вот передачи по шине просто нет. В чём может быть дело? Ведь таймер на время выполнения функции остановлен.
|
|
|
|
|
Sep 18 2014, 17:43
|
Частый гость
 
Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944

|
Согласен, что вопрос сформулирован достаточно косноязычно, но подробно расписывать (мне кажется) нет смысла - только место занимать. Суть в следующем. Написана фирмвара на основе примера STM. В программе есть функция DataIN_OUT_toUSB, которая опрашивает АЦП , пихает данные в массив на передачу по USB. Функция вызывается в модуле app.c ( обычно именуется main.с, но так сделано в примере - менять не стал), определена в модуле usbd_cdc_vcp.c. При этом всё работает - АЦП опрашивается, данные пихаются в буфер и идут наружу в ПК. Изменил фирмвару - в модуле app.c оставил пустой цикл, а функцию стал вызывать из прерывания по таймеру из модуля usbd_cdc_vcp.c . Таймер сработал - вызвал функцию опроса АЦП, функция отработала, данные в буфере, снова запускается таймер. Всё прекрасно крутится - АЦП опрашивается, в буфер данные идут, а вот из буфера в USB не уходят. В чём может быть причина? Изменилось только то, что функция стала вызываться из другого места, сама она не изменилась.
|
|
|
|
|
Sep 19 2014, 11:00
|
Местный
  
Группа: Свой
Сообщений: 271
Регистрация: 6-12-11
Из: Taganrog
Пользователь №: 68 701

|
Очень вероятно, что прерывание от таймера имеет приоритет выше, чем от USB -- в ОС время очень важно. Поэтому второе не происходит внутри первого, фунция DataIN_OUT_toUSB() ничего не видит и т.д... Я бы лично в обработчике прерывания просто устанавливал флаг, в основном цикле его ждал и вызывал DataIN_OUT_toUSB(). Хотя если в последней есть просто поллинг запроса от хоста на заполнение ответной фифошки USB, то она (очень!) не всегда сможет попасть на него и вернуть нужные данные. Тогда живым будет только оригинальный непрерывный вариант. USB -- вещь очень громоздкая, без изучения хотя бы основ и даташита на контроллер в этой части обычные понятия fread/fwrite будут работать редко. Возможно, если просто так данных напихать "впрок" в фифошку после их насчитывания, то они сотрутся прерыванием от USB при запросе хоста, именно в котором и должны быть напиханы only. Я бы лично без отладчика эти вещи и не трогал -- там хоть можно поставить точку останова на любой стадии и пару операций ухватить замедленно в понимательный орган, потом всё порушится, начать сначала, переставить ТО чуть далее... Составить общую картину потом.
|
|
|
|
|
Sep 24 2014, 10:28
|
Местный
  
Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925

|
Так-то автор пишет, что Цитата АЦП опрашивается, в буфер данные идут . Правда, он не сказал, как он это выяснил, методом медитации или отладчиком. То, что осциллографом видны тики таймера еще не говорит, что "АЦП опрашивается, в буфер данные идут". Я не знаю наполнение функции DataIN_OUT_toUSB, но не может ли получиться так, что 2мс не хватает (или хватает, но впритык) для полного выполнения этой ф-ции, и МК почти все время висит в обработчике таймера? Раньше все работало, потому что не было жесткой привязки к запуску этой ф-ции, т.е. когда закончила (может это занимало и более 2мс), тогда и опять начала выполняться, но при этом она могла быть прервана контроллером USB.
|
|
|
|
|
Sep 26 2014, 10:49
|
Частый гость
 
Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944

|
Спасибо за замечание 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В данные не передаст?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|