Перейти к содержанию
    

Не работает прерывание USB

Решаем задачу:считать данные 4К из внешней микросхемы памяти и передать по USB. Читали в оперативку, перекладывали в фифо USB - работало, но медленно. Решили читать из внешней памяти сразу в фифо в прерывании, т.е. просто перенести код из main в модуль interrupt (с недольшими переделками). И передача пропала. Как будто при компиляции часть программы на Си проигнорировалось. Среда Cygnal IDE (старая, но добросовестно работает с небольшими объёмами (в принципе, нам больше и не надо). Что может быть: недостатки IDE, сам контроллер не любит больших программ в прерывании для USB, или всё же только программу смотреть? Повторю, что код пракически без изменения перенесли !

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

WDT случайно вас не вырубает???

в main() оно может почаще крутилось и сбрасывалось, а когда в прерывание ушли, копирование стало много времени кушать, из-за этого main() не успевает собаку сбросить.

Как вариант не более.

контроллер не любит больших программ в прерывании

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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. Как заставить компилятор и линкер всё собирать в рабочую программу?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так вот, в начале модуля 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")

Ну и напоследок посмотреть ассемблер, к каким адресам обращается в прерывании и в фоне.

Со связкой кейл-силабс работал много, на такие ошибки не нарывался.

 

Изменено пользователем редактор

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал определять переменную как посоветовали, но лучше не стало. Выкрутились так: определили функцию MemFull в модуле usb_isr , всё что было написано в обработке внешнего прерывания в main() перенесли в эту функцию, а в самой этой обработке в main() просто вызвали функцию MemFull. Кривовато, но работает.

Попутно возник ещё вопрос, над чем раньше не задумывался. У меня порт Р1 используется попеременно на вывод команд и на ввод данных . Возникло чувство, что после вывода читаю это же самое число число (на шине стоят буферы, позволяющие разделять ). Нужно ли "перенаправлять" направление работы порта : т.е. перед выводом конфигурировать на Out, а перед приёмом на In?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В этих МК нет явного направления ввод-вывод. Чтобы правильно считывать значения с порта, достаточно записать в него все 1. Реальное чтение идет непосредственно с вывода МК. При этом если в порт-защелку записан 0, то при чтении скорее всего и будет считан 0 (если только внешний сигнал его не вытянет к +VDD :-) ). Ну и обратная ситуация более предпочтительна. Если в порт-защелку записана 1, то внешний сигнал низкого потенциала должен "просадить" выход, и это значение будет считано в МК.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если к порту подключен мало потребляющий компонент , то при конфигурации с открытым стоком (PnMDOUT=0x00) может случиться, что притянуть к нулю не удасться или же будут ошибки при считывании? И другая ситуация: записали Pn=0xFF, на шине появилось 0x00, считали. Что останется в Pn? Если 0x00, то возникает неприятная ситуация, про которую Вы упоминали. Получается, что после каждого чтения надо перезаписывать Pn=0xFF. Или проблема решается конфигурацией (PnMDOUT=0xFF- push-pull)?

При этом возникает ещё вопрос. В даташите сказано, что при PnMDOUT=0x00 и записи Pn=0xFF соответствующие выводы будут high impedance. Однако если порт подключен к шине, где передаются данные между другими устройствами, то не будет ли открытый сток влиять на данные в шине , если входы внешних устройств мало потребляют?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В данном случае нужно установить open drain режим с включенными "weak pull-up". Получится обычный для классических 51 квазидвунаправленный порт.

то при конфигурации с открытым стоком (PnMDOUT=0x00) может случиться, что притянуть к нулю не удасться или же будут ошибки при считывании
Наоборот - встроенная подтяжка на открытом стоке ток единицы ограничивает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если сделать PnMDOUT=0, то вывод можно использовать только как вход уровни формируются внешним источником сигнала, Если же снаружи притянуть вывод к питанию, то он сможет функционировать и как выход.

Получается, что после каждого чтения надо перезаписывать Pn=0xFF

При записи в Pn=0xFF значение остается в регистре-защелке, при чтении считывается непосредственно с вывода. Поэтому после чтения перезаписывать необязательно (значение в защелке не меняется). А вот при использовании команд чтение-модификация-запись может потребоваться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я так понял, что регистр-защёлка порта 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)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...