Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не работает прерывание USB
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > MCS51
NikP
Решаем задачу:считать данные 4К из внешней микросхемы памяти и передать по USB. Читали в оперативку, перекладывали в фифо USB - работало, но медленно. Решили читать из внешней памяти сразу в фифо в прерывании, т.е. просто перенести код из main в модуль interrupt (с недольшими переделками). И передача пропала. Как будто при компиляции часть программы на Си проигнорировалось. Среда Cygnal IDE (старая, но добросовестно работает с небольшими объёмами (в принципе, нам больше и не надо). Что может быть: недостатки IDE, сам контроллер не любит больших программ в прерывании для USB, или всё же только программу смотреть? Повторю, что код пракически без изменения перенесли !
редактор
WDT случайно вас не вырубает???
в main() оно может почаще крутилось и сбрасывалось, а когда в прерывание ушли, копирование стало много времени кушать, из-за этого main() не успевает собаку сбросить.
Как вариант не более.
Цитата
контроллер не любит больших программ в прерывании

А больших программ в прерывании мало кто любит. Часто вызываемое прерывание с очень длинной обработкой может подвесить любую отлаженную программу.
NikP
WDT точно ни при чём, я его выключаю сразу при инициализации.

Поработал сегодня с программой через отладчик, заметил следующие заморочки и понял, что вопрос должен относиться скорее к пограммированию или работе со средой Cygnal IDE. Я уж не буду его формулировать в другом разделе форума, может здесь кто ответит.

Программа сделана из нескольких модулей . В main забито внешнее прерывание по уровню. В этом прерывании выставляется флаг готовности микросхемы внешней памяти к считыванию (присвоение FlagReady=1), в прерывании от USB идёт анализ флага if ( FlagReady) и передача накопленных данных. Передача закончилась - FlagReady=0, и новый опрос системы.
Так вот, в начале модуля main определяю unsigned char FlagReady. Модуль usb_isr тоже просит определить FlagReady. Пожалуйста: делаю unsigned char FlagReady. Система даёт ошибку многократное определение. Меняю в main - extern FlagReady. Компилируется без ошибок, при работе в прерывание модуля main о готовности к передаче заходим, а присвоения FlagReady=1 не происходит(видно в отладчике). Делаю наоборот: в main -unsigned char FlagReady, в usb_isr -extern FlagReady. Теперь в прерывании о готовности к передаче присвоение есть, но в прерывании usb_isr строка if ( FlagReady) игнорируется, отладчик показал, что теперь из этого модуля FlagReady видится как 0. Как заставить компилятор и линкер всё собирать в рабочую программу?
_Артём_
Цитата(NikP @ Dec 21 2012, 19:17) *
Так вот, в начале модуля main определяю unsigned char FlagReady.

Не знаю актуально ли для 51-х...
Определите так:
Код
volatile unsigned char FlagReady.
редактор

Цитата
Не знаю актуально ли для 51-х...

Определите так:
Код
volatile unsigned char FlagReady.

для 51 актуально.
Цитата
Компилируется без ошибок...
А что насчет варнигов?
Если в IDE используете компилятор от KEIL то могу посоветовать следующее
Опции компилятора для модулей не отличаются (модели памяти)?. Если модели памяти указаны разные, то необходимо дополнительно указать тип памяти, например
Код
data unsigned char FlagReady;
...
extern data unsigned char FlagReady;

Если используете переключение банков в прерывании, то в опциях компилятора должно быть установлена галка "Don`t use absolute register access". (Это в Keil, в вашей среде скорее всего опция компилятора "NOAREGS")
Ну и напоследок посмотреть ассемблер, к каким адресам обращается в прерывании и в фоне.
Со связкой кейл-силабс работал много, на такие ошибки не нарывался.
NikP
Попробовал определять переменную как посоветовали, но лучше не стало. Выкрутились так: определили функцию MemFull в модуле usb_isr , всё что было написано в обработке внешнего прерывания в main() перенесли в эту функцию, а в самой этой обработке в main() просто вызвали функцию MemFull. Кривовато, но работает.
Попутно возник ещё вопрос, над чем раньше не задумывался. У меня порт Р1 используется попеременно на вывод команд и на ввод данных . Возникло чувство, что после вывода читаю это же самое число число (на шине стоят буферы, позволяющие разделять ). Нужно ли "перенаправлять" направление работы порта : т.е. перед выводом конфигурировать на Out, а перед приёмом на In?
редактор
В этих МК нет явного направления ввод-вывод. Чтобы правильно считывать значения с порта, достаточно записать в него все 1. Реальное чтение идет непосредственно с вывода МК. При этом если в порт-защелку записан 0, то при чтении скорее всего и будет считан 0 (если только внешний сигнал его не вытянет к +VDD :-) ). Ну и обратная ситуация более предпочтительна. Если в порт-защелку записана 1, то внешний сигнал низкого потенциала должен "просадить" выход, и это значение будет считано в МК.
NikP
А если к порту подключен мало потребляющий компонент , то при конфигурации с открытым стоком (PnMDOUT=0x00) может случиться, что притянуть к нулю не удасться или же будут ошибки при считывании? И другая ситуация: записали Pn=0xFF, на шине появилось 0x00, считали. Что останется в Pn? Если 0x00, то возникает неприятная ситуация, про которую Вы упоминали. Получается, что после каждого чтения надо перезаписывать Pn=0xFF. Или проблема решается конфигурацией (PnMDOUT=0xFF- push-pull)?
При этом возникает ещё вопрос. В даташите сказано, что при PnMDOUT=0x00 и записи Pn=0xFF соответствующие выводы будут high impedance. Однако если порт подключен к шине, где передаются данные между другими устройствами, то не будет ли открытый сток влиять на данные в шине , если входы внешних устройств мало потребляют?
Harbinger
В данном случае нужно установить open drain режим с включенными "weak pull-up". Получится обычный для классических 51 квазидвунаправленный порт.
Цитата
то при конфигурации с открытым стоком (PnMDOUT=0x00) может случиться, что притянуть к нулю не удасться или же будут ошибки при считывании
Наоборот - встроенная подтяжка на открытом стоке ток единицы ограничивает.
редактор
если сделать PnMDOUT=0, то вывод можно использовать только как вход уровни формируются внешним источником сигнала, Если же снаружи притянуть вывод к питанию, то он сможет функционировать и как выход.
Цитата
Получается, что после каждого чтения надо перезаписывать Pn=0xFF

При записи в Pn=0xFF значение остается в регистре-защелке, при чтении считывается непосредственно с вывода. Поэтому после чтения перезаписывать необязательно (значение в защелке не меняется). А вот при использовании команд чтение-модификация-запись может потребоваться.
NikP
Я так понял, что регистр-защёлка порта Pn и регистр Pn - это не одно и то же? Соответственно PnMDOUT - управляет режимом вывода данных, PnMDIN - режимом ввода, причём ввод и вывод идут по разным каналам к регистру Pn? Задаю вопрос, потому что пока нигде не нашёл простого и толкового описания. Везде пишут так, будто это всё само собой разумеется, без подробностей.
редактор
Цитата
Я так понял, что регистр-защёлка порта Pn и регистр Pn - это не одно и то же?

Для аналогии приведу регистр SBUF0. Один адрес для чтения и записи, но физически регистры разные. Чтение производится из одного регистра, запись в другой.
Примерно то же самое с портами ввода-вывода. Регистр-защелка только для записи (в качестве буфера порта ввода-вывода). Чтение осуществяется непосредственно с пина (он же выход регистра-защелки)
Такая схемотехника была заложена в классический MCS-51 Intel-ом. Только не спрашивайте зачем именно так.
Все остальные производители поддерживают это для совместимости. Некоторые добавляют свои навороты (как Силабс например).
Цитата
Задаю вопрос, потому что пока нигде не нашёл простого и толкового описания. Везде пишут так, будто это всё само собой разумеется, без подробностей.

DataShit на C8051F32X v1.4 стр.132 П 14.3
Цитата
When writing to a Port, the value written to the SFR is
latched to maintain the output data value at each pin. When reading, the logic levels of the Port's input pins
are returned regardless of the XBRn settings (i.e., even when the pin is assigned to another signal by the
Crossbar, the Port register can always read its corresponding Port I/O pin). The exception to this is the
execution of the read-modify-write instructions.

Ну и схема порта на стр.127 дает представление о внутренней организации (линии port-input, port-output)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.