NikP 0 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба Изучаю STM32. Взял пример с сайта STM для STM322xG-EVAL, в котором шина USB используется как виртуальный COMport, и пытаюсь его немного переделать. Хочу, чтоб при нажатии кнопки на клавиатуре контроллер передавал компьютеру в ЦИКЛЕ массив из цифр 1-32, при повторном нажатии- чтоб останавливался. Возникла проблема: когда я пытаюсь организовать передачу из main вызывая функцию VCP_DataТx, то программа не компилируется - пишет либо "функция не определена" при простом вызове VCP_DataTx (), либо "недопустимо двойное определение" - на определение функции как "extern uint16_t VCP_DataTx ();". Функция VCP_DataTx () определена в исходной программе в модуле usbd_cdc_vcp.c . Как правильно поступить в данной ситуации? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Marto 0 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба подключить соотвествующий заголовочный файл (там где её прототип, должно называться usbd_cdc_vcp.h)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikP 0 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба Попробовал. Компиляция прошла с предупреждением: warning: #223-D: function "VCP_DataTx" declared implicitly. А линковщик выдал ошибку: Error: L6218E: Undefined symbol VCP_DataTx (referred from app.o). Это можно обойти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flexz 0 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба В файле usbd_cdc_vcp.c функция VCP_DataTx определена как static. Поэтому ее нельзя использовать в другом модуле, уберите static в объявлении и тогда можно будет подцепить ее в другом модуле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikP 0 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба Меня смущает определение "static". Наверно, при написании программы его ввели с определённой целью. Если я его уберу, то не появятся новые "косяки"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Marto 0 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба Весьма странно. Нет ли на VCP_DataTx() модификатора static? Надо бы проект выложит сюда. __ упс, уже опередили. косяки не появятся, static нужен для того, чтобы отрубать доступ к функции вне единицы трансляции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба Меня смущает определение "static". Наверно, при написании программы его ввели с определённой целью. Если я его уберу, то не появятся новые "косяки"?Исходников не видел, но ваши рассуждения кажутся мне очень и очень логичными. Отсюда следует вывод - для передачи данных из вашего, пользовательского кода предусмотрена другая функция. И вам надо ее найти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flexz 0 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба Отсюда следует вывод - для передачи данных из вашего, пользовательского кода предусмотрена другая функция. Не предусмотрена. Этот пример - банальный переходник USB-UART. Указанная функция вызывается из прерывания по RXNE и берет данные из UART, что бы передавать ей свои данные ее нужно слегка переписать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 17 июня, 2013 Опубликовано 17 июня, 2013 · Жалоба Не предусмотрена. ... чтобы передавать ей свои данные ее нужно слегка переписать. Значит это пример того, как не надо писать программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikP 0 18 июня, 2013 Опубликовано 18 июня, 2013 · Жалоба Иногда полезно обращаться к первоисточникам: почитал про то, как определяются функции, переопределил VCP_DataTx() как extern (вместо static) в модуле usbd_cdc_vcp.c , и всё прекрасно увиделось из модуля app.c ( из main). Может кому пригодится этот опыт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 18 июня, 2013 Опубликовано 18 июня, 2013 · Жалоба Что это за первоисточник такой? Если в объявлении функции отсутствует спецификатор класса памяти, то по умолчанию принимается класс extern. Вам написали, что надо сделать заголовочный файл в котором перечислить прототипы функций, которые вы хотите использовать не только в текущем исходном файле, и уже подключать это заголовочный файл к другим исходным файлам (это все с условием что нет static) Заголовочный файл Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikP 0 19 июня, 2013 Опубликовано 19 июня, 2013 · Жалоба Я далеко не специалист в программировании, и не особо настаиваю на правильности того, что написал. Может, это совсем неправильно с точки зрения программирования на Си. Просто на практике так сделал - и заработало, без сбоев и тормозов. Сведения же я взял так : набрал в яндексе "static в си" и первая ссылка оказалась helloworld.ru›texts/comp/lang/c/c/h16.htm . Там и прочитал следующее : "Спецификатор класса памяти в объявлении переменной может быть auto, register, static или extern. Если класс памяти не указан, то он определяется по умолчанию из контекста объявления. " и далее "При объявлении переменной на внутреннем уровне может быть использован любой из четырех спецификаторов класса памяти, а если он не указан, то подразумевается класс памяти auto. " Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 19 июня, 2013 Опубликовано 19 июня, 2013 · Жалоба переопределил VCP_DataTx() как extern (вместо static) в модуле usbd_cdc_vcp.c , и всё прекрасно увиделось из модуля app.c ( из main).Если автор программы определил в модуле функцию как static, это значит, что он не предполагал, что этой функцией будут пользоваться снаружи модуля. Когда вы сделали ее extern, до нее стало можно добраться и снаружи, но намерения первоначального автора модуля при этом не изменились :rolleyes: Так что позвать вы ее (функцию) теперь можете, но последствия этого вызова целиком на вашей совести. Яркий пример - вы вытащили наружу функцию, которая работает с регистрами какого то аппаратного модуля и вызывается только из прерываний. Вызов этой функции снаружи (не из прерывания) может нарушить работу этого самого модуля, если в процессе ее вызова произойдет прерывание, и обработчик снова позовет эту функцию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikP 0 19 июня, 2013 Опубликовано 19 июня, 2013 · Жалоба Яркий пример - вы вытащили наружу функцию, которая работает с регистрами какого то аппаратного модуля и вызывается только из прерываний. Точно, на такие грабли я уже наступал. Спасибо за напоминание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться