|
|
|
|
Zandy: Не понял вопроса. Как вычислить нужную константу для получения требуемой задержки - до прерывания по таймеру и длительность паузы между переключением светодиодов в другое состояние? У Вас стоят коэффициенты (.50 и .200) но Вы же их не с потолка взяли?.. Zandy: Вы забыли про сам таймер и его установку в нужное число в каждом прерывании (KTMR0 equ .50) Не забыл, а не знал... И как определить время, через которое сработает таймер? с такими установками, как Вы указали в проге? Zandy: Это просто, только надо ли? Если вариантов - штук 5, то, наверно, не нужна эта кнопка. А если менять частоту с более мелким шагом, когда количество комбинаций будет... например, 20, когда частота переключения может меняться с шагом в 1 Гц, то листать варианты только в одну сторону будет не удобно... Zandy: ...переводить МК в слип, погасив светодиоды? Это сложнее. Проще поставить обычный выключатель. Понятно, что рубильник поставить - значительно проще, но реализовать функцию "рубильника" в самом МК, думаю, интереснее... Хотя, только что пришла идея. Заказчик говорит, что два эффекта должны быть в любом случае - "Горят все светодиоды" и "Не горит ни один". Добавляем в список эффектов эти два варианта и всё... При этом сразу возникают два вопроса: 1) А что, если эффект "Горят все светодиоды" реализовать, как обычный, когда все светодиоды переключаются по очереди, но только с большой частотой, не заметной глазу? Это позволит уменьшить потребляемый ток. Хоть немного... 2) Эффект "Не горит ни один" - то же эффект, только в порты записать постоянно состояние, когда все светодиоды погашены. В этом случае потребление будет только по цепи МК, а так как оно небольшое, то можно считать, что устройство находится в состоянии "Выключено". Zandy: Что за файл? Наверное биты конфигурации. Да, биты конфигурации. Просто, у Вас указано значение: __CONFIG 3F70h ;биты конфигурации А что при этом включено, а что выключено - не понятно. Приходится вычислять самому... |
|
|
DWD: Получается коэффициент "110". Это сколько? Невнимательно даташит читаете. Это 1:128. KTMR0 equ .50 ; Установка таймера TMR0 Koption equ B'00000110' ; Установка OPTION_REG Директива equ используется для присвоения какому-то буквенному набору цифрового значения. Для в/у примера, теперь, при подстановке KTMR0 Ассемблер воспримет его как число 50. Если потом необходимо скорректировать это значение, достаточно будет изменить его только в одной строке (с директивой). Во всех остальных (где использовано KTMR0) оно поменяется автоматически. Чтобы TMR0 отсчитывал нужное значение, необходимо, после каждого переполнения (и выполнения прерывания) записывать в его регистр некоторое начальное число, что видимо, и сделано в программе. По этой причине, кстати, я предпочитаю использовать TMR2, так как в него достаточно записать значение один раз. А как же тогда просчитать время паузы, например? Или через какое время сработает прерывание по таймеру? Это не имеет никакого отношения к байту конфигурации. Я это имел ввиду. Я просто пишу строчку вида: _CONFIG _CP_ON & _DATA_CP_ON & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC , а Ассемблер сам всё считает. Время паузы считаю по количеству комманд, а таймера - по количеству тактов. Естественно потом всё окончательно проверяю в МПлабе по StopWatch, выставив контрольные точки. |
|
|
Обьясняю "на пальцах". Koption equ B'00000110' ........................................... ld OPTION_REG,Koption Эти строки означают, что в регистр OPTION_REG мы записываем число B'110'. При этом предделитель будет иметь Кдел. = 1:128. Рабочая частота равна 1 МГц, т. к. она в 4 раза меньше тактовой. Следовательно, период частоты предделителя будет равен 128 мксек. Строки KTMR0 equ .50 .............................. ld TMR0,KTMR0 означают, что в таймер мы записываем число .50. Причем делается это в начале обработки прерывания, т. е., когда прерывание произошло. А происходит оно по переполнению таймера TMR0, т. е., когда он досчитал до 255. Таким образом мы заставляем таймер считать не с 0, а с числа .50. В результате цикл счета таймера будет 255 - 50 = 205 импульсов. Остается перемножить длительность импульса на их количество 128мкс х 205 = 26, 2 мсек Это и есть период наших прерываний. Строгости ради, чтобы точно получить 20 мсек, нам надо в таймер записывать не .50, а .99. Тогда 128 х (255 - 99) = 20 мсек Дело в том, что период прерываний в данной программе влияет только на антидребезговую обработку кнопок и при том алгоритме, который здесь реализован, вы можете безболезненно уменьшить это время до 10 мсек или еще меньше. Я же говорил, что это дело вкуса. На частоту мигалок, естественно, это никакого влияния не оказывает. Если вам "в лом" делать такие "сложные" расчеты, в процессе симуляции поставьте точку останова на первую команду прерывания. Выводите окошко "Stopwatch". Меряете период прерывания, не забывая нажимать кнопочку "Zero" и пропустив первую остановку, так как в это время входит еще время на выполнение команд инициализации и других, до команды разрешения прерываний (хотя оно крайне мало по сравнением с периодом прерывания). По результатам измерения корректируете цифири и опять меряете. Метод т. н. "научного тыка". Остальные вопросы вроде чисто риторические? Или нет? |
|
|
Zandy: Koption equ B'00000110' ........................................... ld OPTION_REG,Koption Если не ошибаюсь, Id где-то сперва "создаётся". Т.е. какой-то последовательности команд (в нашем случае movlw и movwf) присваивается имя. Где-то я такое читал, но никогда не пользовал, по причине, что искажается подлинная картина количества выполняемых операций. |
|
|
Gregory: Если не ошибаюсь, Id где-то сперва "создаётся". Ну да, это макрос. Используется исключительно для простоты и сокращения записи. Выполняется за время, равное времени выполнения входящих в него команд. Все используемые макросы смотрите в начале текста программы. В данном случае, это: ld MACRO DEST2,CONST2 ; пересылка константы в регистр movlw CONST2 movwf DEST2 endm |
|
|
Gregory и Zandy - спасибо за объяснения. Zandy: Если вам "в лом" делать такие "сложные" расчеты... Как раз наоборот - я ХОЧУ делать эти сложные расчёты, по этому меня интересует каждая мелочь... В доке на 628-й МК получение этих расчётов для TMR0, оказалось, явно не прозрачным... Видимо, одной доки на МК мало. Коэффициент предделителя 1:128 я понял сам, но как его дальше сопоставить со значением 50 - это было проблемой. Спасибо, теперь понятно. Не совсем ясен, правда, смысл всех этих подстановок, но это, видимо, из-за слабого понимания структуры МК. Буду копать дальше... На текущий момент осталось два вопроса - расшифровка бита конфигурации по значению (__CONFIG 3F70h) и расчёт длительности паузы по записиываемым коэффициентам (например, ,200 и .169). Это нужно хотя бы потому, что я собираюсь, всё таки, ставить ещё одну кнопку для изменения частоты не только в "+", но и в "-". Zandy, всю Вашу прогу до конца ещё не понял, но набрался наглости кое-что изменить... Первым и вторым по счёту эффектами стали "Всё включено" и Всё выключено" соответсвенно. Те два эффекта, которые были у Вас первыми двумя, стали последними. Итого - 10 эффектов. А так как циклический счётчик эффектов у Вас ограничен числом 8, то пришлось подправить и его... Получилось... Правда, опасение вызывает факт, что получилось со второго раза... По принципу - если прога заработала сразу, значит она написана неправильно... Тем не менее, прогон в Протеусе показывает, что работает - нажатие на кнопку переключения эффектов переключает их по очереди и зациклено числом 10. Так как я "додумался" сразу создать переменную, определяющую это значение, то дальнейший рост числа эффектов проблемы, надеюсь, не создаст... Кстати, Zandy, получилось со "второй" попытки потому, что первой была - описать переменную в "cblock", а потом присваивать ей значение, используя готовый макрос, но до конца я это не проверил, так как способ мне не понравился... Сначала описываешь переменную, потом присваиваешь ей значение. Потом проверяешь текущее состояние счётчика эффектов, используя операции пересылки в аккумулятор и сравнение с помощью команды "XORWF f,d"... Но есть, ведь, команда "XORLW k" - работа с константой. По этому, я создал не переменную, а константу, описав в одной строке сразу саму переменную и её значение. Потом, просто сравнивал состояние счётчика с константой. В связи с этим вопрос - почему Вы не использовали это? Или я не прав в принципе, и этот вариант, скажем, случайно подошёл только в данном случае, а не вообще? Может, это не существенно, но мне показалось, что таким способом можно было бы избавиться от "двойной" операции - создание переменной и присвоение ей значения. А у Вас в проге много таких переменных, которые "тянут" на константы. |
|
|
DWD: На текущий момент осталось два вопроса - расшифровка бита конфигурации по значению (__CONFIG 3F70h) Выбираете в меню Configure, в нем подменю - Configuration Bits. Щелкаете по нему. Откроется картиночка. В ней увидите и число 3F70h, и все установки конфигурационных битов наглядно. Щелкая мышкой по значениям, можете установить все то, что вам нужно. При этом изменится и число 3F70h. Просто берете и измененное число переписываете в программе вместо того, которое было. Если не нравится так, делайте так, как вам подсказал Gregory Gregory: Я просто пишу строчку вида: _CONFIG _CP_ON & _DATA_CP_ON & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC , а Ассемблер сам всё считает. Синтаксис написания берете из файла P16F628.INC Ну или третий путь. Читаете документацию, раздел 14.1 Там прописаны все эти биты и их значения при разных вариантах конфигурации. DWD: расчёт длительности паузы по записиываемым коэффициентам (например, ,200 и .169). Паузой управляют строки с 423 по 430. Там организован двухбайтовый счетчик паузы. Имеется два цикла: малый (декрементируется с проверкой на 0 счетчик PauseL) и большой (декрементируется с проверкой на 0 счетчик PauseH), когда PauseL обнуляется. Время исполнения цикла равно времени исполнения команд в цикле, умноженное на количество малых циклов и умноженное на количество больших циклов. Не забывайте, что время исполнения некоторых команд (например goto) составляет 2 такта. Конкретный подсчет я делаю так. Сперва грубо прикидываю значения начальных установок счетчика паузы (просчитать с точностью до 1 такта - довольно муторное занятие), а затем в процессе симуляции с помощью стоп - меток и "Stopwatch" уточняю значения. Точный расчет в каждой программе будет разный, т. к. количество команд, входящих в цикл тоже разное. Здесь нет универсальной формулы, а общий подход к расчету я вам уже описал. Гляньте еще вот это http://ikarab.narod.ru/pause.htm Я сам не пользовался, не знаю, но может вам понравится. И вообще, почитайте http://ikarab.narod.ru/Kea_20.html . Там настолько все "разжевано", что дальше некуда. Правда некоторые вещи не используются, например .inc файл. Все регистры спец. назначения прописываются в шапке и т. д. DWD: Сначала описываешь переменную, потом присваиваешь ей значение. Потом проверяешь текущее состояние счётчика эффектов, используя операции пересылки в аккумулятор и сравнение с помощью команды "XORWF f,d"... Но есть, ведь, команда "XORLW k" - работа с константой. По этому, я создал не переменную, а константу, описав в одной строке сразу саму переменную и её значение. Потом, просто сравнивал состояние счётчика с константой. Все правильно. Если в процессе исполнения программы какое-то число не изменяется, то это константа и нет смысла отводить под нее регистр, а затем прописывать туда число. DWD: Может, это не существенно, но мне показалось, что таким способом можно было бы избавиться от "двойной" операции - создание переменной и присвоение ей значения. А у Вас в проге много таких переменных, которые "тянут" на константы. Да нет, у меня таких переменных нету. Смотрите внимательнее. Если я при инициализации (начальная установка) или в процессе выполнения программы, записываю в регистр (переменную) какое-то число, то это не значит, что это число будет там храниться вечно. DWD: Итого - 10 эффектов. А так как циклический счётчик эффектов у Вас ограничен числом 8, то пришлось подправить и его... Получилось... Правда, опасение вызывает факт, что получилось со второго раза... Ну здесь заочно сложно что-либо сказать. Выложите ваш кусок программы - посмотрим, проверим, обсудим.
|
|
|
Zandy: Сперва грубо прикидываю значения начальных установок счетчика паузы Аналогично. |
|
|
Понял, спасибо. Прога у меня дома, завтра принесу и с утра выложу. |
|
|
Zandy: Выбираете в меню Configure, в нем подменю - Configuration Bits. Щелкаете по нему. Откроется картиночка. В ней увидите и число 3F70h, и все установки конфигурационных битов наглядно. В 5-й версии такого нет. Видимо, у Вас 6-я? Там такое есть. Ещё вопрос по биту конфигурации. Почему в Протеусе установлено значение 3F30h, а в листинге проги - 3F70h? Zandy: Выложите ваш кусок программы - посмотрим, проверим, обсудим. Выкладываю (аттач). Изменения: 1) KNOP7 equ .10 ; Количество эффектов. 2) "Перебор вариантов при нажатии на A7". Две Ваши команды "заремлены", и дописаны 4 новых: ; movlw b'00001111' ; затираем лишние биты ; andwf COUNT_KNOP7,F ; кроме трех младших movf COUNT_KNOP7,w ; XORlW KNOP7 ; Если счётчик числа эффектов достиг jnz PER2 ; максимального значения, clrf COUNT_KNOP7 ; то обнуляем его. 3) Перебор вариантов эффектов. Добавлено две строки: goto LIGHT9 goto LIGHT10 Следом подряд идут 2 эффекта - "Всё включено" и "Всё выключено". Получены переделкой Ваших двух эффектов. Те 2 эффекта, которые у Вас были первыми двумя, перенесены на последние - 9-й и 10-й. 4) Гудок. Изменена одна команда: H2 bcf GPORTA,4 ;Было bsf. На выходе не импульсы, а постоянный уровень 0. В результате, на выводе мк RA4 не импульсы, а постоянный уровень нуля. Просто, я расчитываю использовать зуммер от китайского будильника со встроенным генератором, для которого достаточно подать постоянное напряжение, что бы он "запищал". Включу его между выводом питания и портом RA4. О согласовании уровней думаю, так как для зуммера нужно 1,5В... Возможно, хватит включения последовательно с самим зумером стабилитрона на 2,7-3,3В. Пока всё. Дальше хочу думать о пристройке дополнительной кнопки на порт RA5 и изменении программы для получения возможности менять с каким-то шагом частоту эффектов как в сторону увеличения, так и уменьшения. Частота менее 1Гц, вряд ли, понадобится. Не нужна частота и выше 20Гц, так как будет казаться, что светодиоды не мигают, а горят постоянно. По этому, пределы изменения частоты 1-20Гц. При таком малом числе, думаю, можно сделать изменение частоты с шагом в 1 Гц. Как думаете? 67298.zip |
|
|
|
|