Форум » Для начинающих. » Проблема ЧМЗ » Ответить

Проблема ЧМЗ

Алексей: У начинающих часто возникают вопросы, связанные с работой с портами контроллера. Проявляется это в непредвиденном изменении состояния одного или нескольких выводов контроллера. Очень часто данная проблема связана с непониманием работы процесса чтение\модификация\запись в приложении к работе с портами... Приведу пример, поясняющий это... В частности товарищ Galrad задал вопрос КЕА и пока не получил ответа В общем то этот пример и есть ответ на его вопрос... В качестве отладчика используется протеус, ссылка на проект в конце поста... Схема проста Увеличить ;**************************************************************************** ; Пример для понимания работы ЧМЗ и связанных с этим фокусов... ;**************************************************************************** [pre2] __config 1F01H #include <p16F627A.inc> errorlevel -302 ;============================================================================ ; Определение названия и положения регистров общего назначения. ;============================================================================ cblock 20h ; начальный адрес области данных endc ;============================================================================ ; START ;============================================================================ org 0x000 ; Вектор сброса ;============================================================================ ; Подготовительные операции ;============================================================================ START bcf STATUS, RP0 bcf STATUS, RP1 clrf PORTA clrf PORTB clrf T1CON clrf T2CON clrf CCP1CON clrf RCSTA movlw 07h movwf CMCON bcf INTCON,GIE bsf STATUS, RP0 clrf TXSTA clrf TRISA clrf TRISB movlw b'00001111' movwf OPTION_REG bcf STATUS, RP0 [/pre2] ;============================================================================ ; С этого момента пошагово выполняем программу, внимательно и с интересом ; наблюдаем за тем, что происходит в симуляторе... Получим результат не тот, ; что ожидаем! И такое происходит не только в протеусе!, но и реальном ; железе!!! ;============================================================================ [pre2]main clrf PORTB ; сброшу порт в нули чтобы bsf STATUS,RP0 ; быть уверенным что в выходных clrf TRISB ; защелках записаны 0 bcf STATUS,RP0 ; BsF PORTB,3 ; Понадобится позже... bsf STATUS,RP0 ; Теперь переключу часть выводов movlw b'01001001' ; на вход movwf TRISB ; bcf STATUS,RP0 ; bsf STATUS,RP0 ; Опять переключу порт на выход clrf TRISB ; убедиться что все пока нормально bcf STATUS,RP0 ; В ВЫХОДНЫХ ЗАЩЕЛКАХ ЧИСЛО .8!!! ; Пока проблем не наблюдается :) bsf STATUS,RP0 ; Опять переключу часть выводов movlw b'01001001' ; на вход. За счет резисторов movwf TRISB ; на этих выводах сформируется bcf STATUS,RP0 ; логический 0 или 1... ;============================================================================ ; А ТЕПЕРЬ, ВНИМАНИЕ, ФОКУС!!! Помните?, в защелках записано число .8!!! ;============================================================================ BsF PORTB,1 ; модифицирую порт бит ориентированной ; командой... По логике должен ; измениться только один 1 бит! И в ; результате должно бы получиться .10 bsf STATUS,RP0 ; Опять переключаю порт на выход clrf TRISB ; И ЧТО Я ВИЖУ В ПОРТУ? Совершенно bcf STATUS,RP0 ; не то, что ожидал... А ожидал .10 ; Даже скинулся 3 бит!!! а он был ; установлен мной ранее!!!!!!!!!! И ; я его не трогал!!! ;============================================================================ ; Что мы теперь видим в регистре PORTB? По идее должны бы видеть число ; .10... Была ведь записана .8 и в дополнение я поднял 1 бит... Что в ; в общем случае дает .10... На самом деле видим совершенно другую ; картину, .67, почему??? Причем 3 бит был поднят! а сейчас нет! ; Все дело в способе работы с регистрами в контроллере. Дело в том, ; что даже бит ориентированные команды не работают с одним единственным ; битом регистра. Сначала производится чтение из регистра, затем модификация ; всего байта, независимо от того, какая команда применяется, и только затем ; запись в регистр всех 8 бит с одним модифицированным. Вроде бы ничего ; такого, и проблем никогда с этим не возникает... Но вот такое творится ; только при работе с регистрами PORTx... И тут дело в том, что чтение ; производится исключительно с "выводов" контроллера, а вот запись производится ; в выходные защелки регистра. Т.е. получается что вместо одного регистра ; PORTx фактически имеем целых два! Один из них это выходные защелки порта, ; которые отключаются от физических выводов при работе на ВХОД. Но тем не ; менее чтение происходит "непосредственно" с выводов порта... Таким образом ; имеем, ЕСЛИ ПОРТ ХОТЯ БЫ ЧАСТИЧНО РАБОТАЕТ НА ВХОД, ЛЮБАЯ! КОМАНДА, ; ИЗМЕНЯЮЩАЯ ЗНАЧЕНИЕ РЕГИСТРА PORTX, БУДЕТ РАБОТАТЬ ТАК: ; 1. Чтение всего порта "непосредственно" с выводов контроллера ; 2. Затем его модификация. Причем не важно как мы работаем с портом! даже ; бит ориентированными командами BSF и BCF... ; 3. Ну и запись... Но запись производится не непосредственно на выводы ; порта :), а естественно в выходные защелки. ; Т.е. получается довольно тернистый путь, читаем с одного места, а пишем в ; другое... Что и может вызвать большие затруднения у начинающих программистов. ; Добавлю еще, что такая ситуация наблюдается до 16 серии включительно... За ; исключением новых контроллеров PIC16F(LF)xxxx. В них и более старших ; семействах уже введен дополнительный регистр LATx. Он и есть те самые ; выходные защелки. Чтение же порта происходит из регитра PORTx... В принципе, ; в ситуациях не связанных с ЧМЗ, без разницы к какому регистру обращаться. ; Т.о. разработчики устранили проблему ЧМЗ, но чтобы понимать и в старшем ; семействе откуда надо читать и куда писАть о проблеме ЧМЗ знать надо... ;============================================================================ goto main end[/pre2] Здесь лежит проект в протеусе, созданный специально для данного примера... Использовать в Обмене и статьях КЕА запрещено

Ответов - 68, стр: 1 2 All

Photographer: Эдесь полный проект к этой статье. read modify write.rar

galrad: Спасибо. А можно продолжить тему с разъяснениями, как лучше избегать или устранять возникшие проблемы, связанные с ЧМЗ?

medved: Если же Вы внимательно прочитали первый пост данной темы, то должно стать понятно, что для избежания/устранения проблемы связанной с ЧМЗ перед переключением PORTx на выход следует записать в защелку требуемое значение. Еще раз обращаю внимание, что данная проблема возникает тогда, когда по ходу исполнения программы PORTx имеет переключения вход/выход. Первоначальная настройка контроллера не в счет.


Photographer: Наверно можно выделить дополнительные регистры параллельно портам (в PIC18 есть аппаратно ?). А не корректные команды заменить на корректные макросы, с теми же названиями и префиксом, работающие через дополнительные регистры, .

SanSanich: Лично я не совсем понял пояснения в предыдущих постах. Лучше пример в коде, как надо правильно сделать. Как происходит ошибка увидел, а вот как правильно сделать, в примере ?

Sergey Roslik: Так пример выше, в мплабе крутите его и наблюдаете состояние регистров, куда уже наглядней.

tester: Дополню Алексея: проблема из-за RMW (ЧМЗ) может возникнуть и без переключения направления портов. [pre2] clrf TRISB clrf PORTB ... bsf PORTB, 0 bsf PORTB, 1 [/pre2] При высокой тактовой частоте и сильной нагрузке на порте (или сравнительно большой ее емкостной составляющей) получится так, что RB0 останется в "0". Дело в том, что большинство инструкций по модификации регистров работают по принципу RMW. Когда устанавливается RB0, сначала читается текущее состояние порта (0x00), потом модифицируется нулевой бит (0x01) и затем производится запись обратно. Чем больше нагрузка на RB0, тем медленнее будет переходный процесс по установке лог "1" на выходе. Если сразу же за этой инструкцией вызвать еще одну RMW-инструкцию, то на стадии чтения порта напряжение на выходе RB0 может еще не успеть установиться выше порогового значения, и таким образом порт опять будет прочитан как 0x00. Далее модифицируется бит RB1 (0x02) и делается запись в порт. В результате мы получим совсем не то, что хотели, т.е. 0x02 вместо 0x03. Выходов - два: 1. Простой (по рекомендации микрочипа) - разделять RMW-инструкции над портами ввод/вывода хотя бы одним NOP'ом. 2. Правильный - работать через буферный регистр.

SanSanich: Вот так будет правильно? [pre2] bcf STATUS,RP1 bsf STATUS,RP0 movlw b'11110000' ; 0-3 выход, 4-7 вход movwf TRISB clrf OPTION_REG ; резисторы отключены (бит 7 RBPU тоже в 0) bcf STATUS,RP0 movlw b'11111111' ; можно так? Получим на 0-3 "1", на вход не влияет? movwf PORTB movf PORTB,w ; читаем порт movwf TEMP bsf TEMP,0 ; устанавливаем в 0 бите 1 bсf TEMP,7 ; и в 7 бите 0 bcf STATUS,RP1 bsf STATUS,RP0 movf TEMP,w ; перенапрАвливаем порт 7 на выход, 0 порт на вход movwf TRISB bcf STATUS,RP0 movf TEMP,w ; устанавливаем в порт movwf PORTB ; '0xxx111x' x это 3 состояние, на вход [/pre2]

Алексей: tester пишет: проблема из-за RMW (ЧМЗ) может возникнуть и без переключения направления портов. Не знал SanSanich пишет: Вот так будет правильно? Александр, чет я тебя не пойму... Если работать через буфер, то сначала уж запомни состояние выходов(Т.е. защелок порта), потом переключи порт на вход, сделай что тебе нужно и перед переключением снова на выход перепиши буфер в защелки. и только после этого переключай снова на выход... Ну еще по обстоятельствам смотри, может быть у тебя еще получится так, что состояние порта за это время могло вполне законно измениться... SanSanich пишет: movlw b'11111111' ; можно так? Получим на 0-3 "1", на вход не влияет? movwf PORTB Это я вообще не понимаю для чего? Если ты про примечание testerа, то имеется ввиду что ты должен завести какой либо буферный регистр и все операции по модификации порта ты сначала должен сделать с ним, и только потом одним махом скопировать этот регистр в защелки.Т.е. ты просто исключаешь несколько обращений подряд к PORTx, из за чего могут возникнуть проблемы... При единичном обращении такого не будет...

SanSanich: Вот я и прошу на примере показать, лучше на моём. Если не трудно. До меня так лучше доходит! Защёлки это регистр PORTB? Алексей пишет: то сначала уж запомни состояние выходов(Т.е. защелок порта) [pre2] movf PORTB,w ; читаем порт movwf TEMP [/pre2] Алексей пишет: потом переключи порт на вход, сделай что тебе нужно [pre2] bcf STATUS,RP1 bsf STATUS,RP0 movlw b'01110001' ; перенапрАвливаем порт 7 на выход, 0 порт на вход movwf TRISB ; получаем 0-вход, 1-3-выход, 4-6-вход, 7-выход bcf STATUS,RP0 bsf PORTB,7 nop bcf PORTB, 1 [/pre2] Алексей пишет: и перед переключением снова на выход перепиши буфер в защелки. и только после этого переключай снова на выход... А вот тут я не понял. Покажите тупому на примере!!!

Алексей: SanSanich пишет: Защёлки это регистр PORTB? Нет, это выводы контроллера... Защелки это регистр нечто вроде виртуального... Когда выводы работает на выход эти оба регистра сединены вместе... Когда же выводы переключаешь на вход, они размыкаются и становятся совершенно разными физически... Но чтение идет именно с выводов, а запись происходит в защелку порта, которая отключена от выводов... Теперь, если на входах сигнал не соответствует внутренней защелке, то чтение с выводов и запись защелки изменит состояние защелки и при переключении на выход лог. сигналы поменяются... Для лучшего понимания посмотри устройство портов, сразу будет понятнее... Позже выложу еще на чипмк...

Алексей: Вот как пример из даташита структуры вывода RB0 Увеличить Тут очень четко видно откуда производится чтение и куда запись... регистр PORTx это считай есть физическая ножка контроллера, и есть защелка данных, которая может отключаться от вывода... Соответственно отсюда и все проблемы с ЧМЗ, ведь читаем напрямую с вывода, но запись уже происходит в защелку данных...

SanSanich: Алексей пишет: Но чтение идет именно с выводов Какими командами читать? С какого регистра? Можно на примере, если не трудно.

Алексей: Давай чуть позже, мне сейчас бежать надо? на работу. Насчет чтения... Читает контроллер сам, неважно чем ты обращаешься, даже если выводишь в защелку чего то, он сначала прочитает, модифицирует и запишет... А чтобы тебе считать с порта, то у тебя нет выбора, только регистр PORTx и все...

SanSanich: Ок, по возможности, мне на примере надо

medved: SanSanich пишет: Какими командами читать? Читать стандартными командами. Фишка не в том как читать, а в том откуда читать и куда записывать. Читаешь с ножки МК, а пишешь в защелку. Уровни на ножке и защелке могут отличаться. Вот это и нужно учитывать

Алексей: medved пишет: Уровни на ножке и защелке могут отличаться. Вот это и нужно учитывать Лучше и не скажешь

Photographer: Похоже понять то что не понятно, ещё сложнее SanSanich пишет: А вот тут я не понял. [pre2]; movf PORTB,w ; читаем порт, теперь в TEMP у тебя вместо PORTB ; movwf TEMP ; Но здесь это пока не надо bcf STATUS,RP1 bsf STATUS,RP0 movlw b'01110001' ; перенапрАвливаем порт 7 на выход, 0 порт на вход movwf TRISB ; получаем 0-вход, 1-3-выход, 4-6-вход, 7-выход bcf STATUS,RP0 ; bsf PORTB,7 ; У тебя же TEMP вместо PORTB ; nop ; Вот и работай с ним ; bcf PORTB, 1 ; а не с портом. movf PORTB,w ; читаем порт непосредственно перед изменением movwf TEMP ; теперь в TEMP у тебя вместо PORTB bsf TEMP,7 ; Делаем изменения nop ; Здесь nop нужен нет? пусть будет. bsf TEMP,1 movf TEMP,w ; Вносим изменения в PORTB movwf PORTB ; [/pre2] Вроде так.

tester: Photographer пишет: Вроде так. Не совсем. Смысл буферного регистра в том, чтобы не перетирать его значение прочитанным состоянием портов. Т.е. "movf PORTB, w/movwf TEMP" - лишнее. Фрагмент должен выглядеть так: [pre2] movlw PORTB_INIT movwf Temp ; Инициализируем единожды movwf PORTB bsf status, rp0 movlw TRISB_INIT movwf TRISB bcf status, rp0 ... bsf Temp, 7 ; Все RMW операции - только над буферным регистром bsf Temp, 1 movf Temp, w movwf PORTB ; Запись в порт только присваиванием ... [/pre]

Photographer: tester пишет: Т.е. "movf PORTB, w/movwf TEMP" - лишнее На самом деле. По скольку мы имеем дело только в выходами, то и значения на них изначально будут/должны быть одинаковыми, в смысле предустановленными, а не считанными. Спасибо. Я здесь набросал готовый проект с глюками. Хотел что нибудь законченное сделать, но потом передумал. Не знай как в реале, но Протеус показывает страшный глюк. Смысл устройства и программы понять легко. Надо выключить все сегменты индикатора, а потом кнопками по одному сегменту включить. Пример не лучший, но что есть. Будут лучше - выкладывайте. Предлагаю всем желающим, на одном этом примере потренироваться и исправить ошибку. Не просто добиться правильной работы, а именно исправить с учётом эффекта ЧМЗ. Архив этого проекта здесь.

Photographer: По проекту ко мне был вопрос - почему так запутанно расположены кнопки. Всё просто, они расположены в соответствии с расположением сегментов индикатора. Т.е. верхнему сегменту "а" соответствует верхняя кнопка... и так далее И ещё, объяснять мне как это должно работать не надо. Просто решите эту задачку. Если не понятно, спрашивайте здесь. Кто нибудь ответит. А потом сравним результаты, решения, подходы Анатолий Медведев medved подправил схему. Можно заменить ту что в проекте. Копия read modify write_1.DSN

igor: Photographer пишет: Смысл устройства и программы понять легко. Надо выключить все сегменты индикатора, а потом кнопками по одному сегменту включить. Photographer пишет: Не знай как в реале, но Протеус показывает страшный глюк. Photographer пишет: И ещё, объяснять мне как это должно работать не надо. Просто решите эту задачку. Если не понятно, спрашивайте здесь. Так в чём глюк то заключается? Что решать?

Photographer: Есть пример - глючная програмка. Включи в Протеусе - увидишь. Есть хорошая подсказка от tester-а. Если есть желание - можно потренироваться (всем на одном примере). Я ответ знаю и тоже подготовлю рабочий вариант. Потом можно будет сравнить. SanSanich пишет: Ок, по возможности, мне на примере надо Вроде всё объяснили, но не все поняли. Как не на одной задачке решать эту проблему. Задачка простая, проще некуда. Пример решения и объяснения есть. Её надо решать самому, тому кто не понял. Если я сейчас выложу ответ этой простой задачки, то опять кто то не поймёт. Я уже и так и эдак рассказал. Как ещё рассказывать, уже не представляю. Ясно же, научить нельзя, можно только научиться. Это прописная истина. Ладно, попробую ещё с другого конца подойти. Ты знаешь как ещё по другому объяснить SanSanich-у? А другим? Загляни в школьные учебники. Там после объяснения темы и примеров, даются задачки, без ответов. Вернее ответы есть в методичке учителя. Вот и это и есть такая задачка в конце темы. Если ещё кто нибудь спросит на хрена я выложил эту задачку - я застрелюсь.

igor: igor пишет: Так в чём глюк то заключается? Что решать? Photographer пишет: Есть пример - глючная програмка. Включи в Протеусе - увидишь. Я не хочу догадываться. Или говоришь - где глюк, или я говорю - на хрена ты её выложил?

Алексей: Альберт, почему у тебя выводы порта В не подтянуты в источнику питания У тебя на вывода неопределенный уровень. Что ты хочешь таким образом показать?

galrad: Photographer пишет: Копия read modify write_1.DSN У меня показывает, что страничка инфицирована вирем

medved: galrad пишет: У меня показывает, что страничка инфицирована вирем Попробуйте скачать отсюда

galrad: Спасибо! Здесь нормально!

galrad: Сделал подтяжки на плюс. Сейчас хорошо видно как работает программа с нестабильными скачками сегментов. http://zalil.ru/30831734

galrad: Действительно, проблема устраняется очень просто, если понять мехамизм его возникновения. Поначалу запутался, но когда разобрался, то "все стало на свои места". Думаю, что Альберт прав, подчеркнув на самостоятельном решении задачки, в принципе она очень простая, главное понять. Ну, что же, еще один шаг вперед

Photographer: Я уезжал из города. сейчас отвечу как смогу. Алексей пишет: Альберт, почему у тебя выводы порта В не подтянуты в источнику питания У тебя на вывода неопределенный уровень. Что ты хочешь таким образом показать? Я просто сделал проект с глючной индикацией. К сожалению глюков в нём оказалось больше чем надо Ну вопервых я забыл сделать управление катодом индикатора. Это надо для совместной работы с кнопками. Подтяжку к питанию не надо, выхода МК и так подтянуты к плюсу. Я поставил вместо светодиода транзистор на катод и всё встало на свои места. в смысле схемотехники. Да, кстати, medved сделал ещё один вариант в протеусе с шинами... давайте так, если кто хочет, то может доработать его, поставит транзистор на катод индикатора и включит в свой проект. Так будет интересней вот он И это... вчера брал флешку у жены... так что извините. И где она эти вирусы находит, там же у тёщи интернета даже нет... разве что на работе. Проверьте пожалуйста. Я то просканировал комп и файл онлайн проверил. Но эта зараза неистребима. Модифицируются вечно. ЧМЗ полный короче Итак на счёт проекта... сделать можно как угодно... Если даже я знаю 10 способов, то имею ввиду, что есть ешё десяток способов которые я не знаю. Проект схематически получился не удачный. Заставить включаться сегменты при нажатии кнопок просто. Т.е. кнопкой на выводе делаешь 0, и на том же выводе появляется единица для сегмента индикатора. Это я сделал в своём варианте. Сейчас хочу посмотреть что будет если не использовать временный регистр для порта. Надеюсь, что будут наглядныые нерабочие варианты. Проект может не работать сдуру или наспех. А вот заставить не работать когда всё логично и правильно, оказывается не просто. Может кто то другой проект предложит? Хотелось сделать наглядный пример, как должно быть, но не работает и вариант как надо на самом деле. Тот что работает выложить? или потом сразу оба варианта?.... ладно, вот он. У меня показывает Известных вирусов: 5212594 Дата последнего обновления: 10-04-2011 Размер файла (Kb): 45 Тел вирусов: 0 Файлов: 15 Предупреждений: 0 Архивов: 1 Подозрительных: 0

Photographer: Самое прикольное, что в "оптимизированном" варианте хватает одной команды чтобы считать со входа все кнопки, инвертировать результат, записать на выход и переключится с кнопок на индикатор [pre2]main bsf STATUS,RP0 ; Включим порт movlw b'01111111' ; на вход movwf TRISB ; bcf STATUS,RP0 ; bcf PORTB,7 ; Выключим индикатор. comf PORTB,F ; Читаем, модифицируем, записываем в порт и включаем транзистор :-) bsf STATUS,RP0 ; Теперь переключим входа clrf TRISB ; на выход bcf STATUS,RP0 ; call Pause_10 ; Можно отдохнуть ; или заняться другими делами. goto main[/pre2] Но это сгодится только для этого случая и это плохо.

Photographer: А вот и пример ошибки, для этого случая. Перед тем как инвертировать командой comf, мы командой bcf выключаем индикатор. А попробуйте после comf, обратно включить индикатор подобным образом командой bsf. Тут же данные на защёлках инвертируются обратно [pre2]main bsf STATUS,RP0 ; Включим порт movlw b'01111111' ; на вход movwf TRISB ; bcf STATUS,RP0 ; bcf PORTB,7 ; Выключим индикатор. comf PORTB,F ; Читаем, инвертируем, записываем в порт bsf PORTB,7 ; Включим индикатор. и в защёлках данные инвертировались обратно :-) bsf STATUS,RP0 ; Теперь переключим входа clrf TRISB ; на выход bcf STATUS,RP0 ; call Pause_10 ; Можно отдохнуть ; или заняться другими делами. goto main[/pre2] Я тут подумал, всё таки не стоит использовать использовать для записи в порт регистр с названием Temp. Для каждого порта нужен свой регистр примерно с такими названиями как PORTA_OUT PORTB_OUT PORTC_OUT

MAZ: Уважаемые коллеги. Прошу внимательно прочитать "нижележащее" , как следует это запомнить и руководствоваться этим правилом в дальнейшем. Если нужно, в несколько "бит-приёмов", следующих друг за другом, изменить состояния 2-х или более каналов порта, работающих "на выход" (как в первой проге Павла), то в этом случае целесообразно отказаться от применения бит-ориентированных команд типа bcf/bsf, а сделать это с помощью байт-ориентированных команд. По-первости, я тоже "вляпывался в эту бяку" (её коварство в том, что в симуляторе норма, а "в железе" конфуз). И не один раз, а много. И соответствующая "шизофрения" тоже была. Короче, прислушайтесь к "вышележащему", доброму совету и соответствующих проблем не будет. Вот так,просто и доходчиво. Можно сказать, своими словами, с красивыми отступлениями мастер объяснил ЧМЗ. Это не всякому дано.

Dmitry Dubrovenko: MAZ пишет: Если нужно, в несколько "бит-приёмов", следующих друг за другом, изменить состояния 2-х или более каналов порта, работающих "на выход" (как в первой проге Павла), то в этом случае целесообразно отказаться от применения бит-ориентированных команд типа bcf/bsf, а сделать это с помощью байт-ориентированных команд.Погодите-ка. Насколько понимаю, имеем два варианта "ошибки ЧМЗ" (назовём её так). 1. Ошибка возникает из-за неправильной череды настроек порта на вход-выход (то, что описАл Алексей в начале). 2. Ошибка возникает из-за воздействия внешней нагрузки, которая не даёт мнгновенно измениться выходу защёлки. Получается, что в/у рекомендация распространяется только на второй случай. Если состояние портов будет изменяться мнгновенно, то почему бы не использовать подряд бит-ориентированные команды? На практике же, мнгновенного (или по крайней мере, укладывающегося в МЦ) изменения достичь, наверно, нереально. Однако не припоминаю, что бы у меня два изменения портов следовали друг за другом. Обязательно сперва были какие-то команды, определяющие условие (т.е. "задержка"). Я не прав?

MAZ: Дмитрий прости, но это не мои рекомендации. Алексей, кажется хорошо объяснил, что , читаем с одного места, а пишем в другое. Dmitry Dubrovenko пишет: Однако не припоминаю, что бы у меня два изменения портов следовали друг за другом. Обязательно сперва были какие-то команды, определяющие условие (т.е. "задержка"). Я не прав? Мне кажется ты не правильно ставишь вопрос. Изменение на выводе порта настроенного на вых. можно делать и последовательно, ну nop между ними вставить. Алексей пишет: Но вот такое творится ; только при работе с регистрами PORTx... И тут дело в том, что чтение ; производится исключительно с "выводов" контроллера, а вот запись производится ; в выходные защелки регистра. Т.е. получается что вместо одного регистра ; PORTx фактически имеем целых два! Один из них это выходные защелки порта, ; которые отключаются от физических выводов при работе на ВХОД. Но тем не ; менее чтение происходит "непосредственно" с выводов порта... Таким образом ; имеем, ЕСЛИ ПОРТ ХОТЯ БЫ ЧАСТИЧНО РАБОТАЕТ НА ВХОД, ЛЮБАЯ! КОМАНДА, ; ИЗМЕНЯЮЩАЯ ЗНАЧЕНИЕ РЕГИСТРА PORTX, БУДЕТ РАБОТАТЬ ТАК: ; 1. Чтение всего порта "непосредственно" с выводов контроллера ; 2. Затем его модификация. Причем не важно как мы работаем с портом! даже ; бит ориентированными командами BSF и BCF... ; 3. Ну и запись... Но запись производится не непосредственно на выводы ; порта :), а естественно в выходные защелки.

Dmitry Dubrovenko: MAZ пишет: Изменение на выводе порта настроенного на вых. можно делать и последовательно, ну nop между ними вставить.Так и я про то же. Только дополнил, что из личного опыта, перед изменением состояния выхода, у меня сперва следует ряд команд, где выясняется, необходимо ли это изменение. Поэтому, между двумя изменениями порта "автоматически" получается "ноп". Это всё про второй "случай". Честно говоря, раньше я о нём как-то не задумывался. Про первый же (про который Алексей говорил), я давно знаю, и для себя взял за правило менять направление порта бит-ориентированными командами (по мере возможности, разумеется).

SanSanich: Dmitry Dubrovenko пишет: для себя взял за правило менять направление порта бит-ориентированными командами (по мере возможности, разумеется). Бит или байт-ориентированными?

medved: На известном форуме "мастер" предпринял попытку объяснить проблему ЧМЗ: "Частотная составляющая", и особенно в случаях работы на максимальной Fosc, конечно же важна. Её признак - избавление от "бяки" после осуществления "врезки" NOPов, но у меня были такие случаи, что "врезки" даже десятков NOPов не помогали. Значит, это функциональный "глюк". Стало интересно и решил разобраться. Вот что получилось. Исполнение команды bcf/bsf происходит следующим, специфическим образом. После осуществления декодирования команды (Q1), происходит копирование, во внутренний буфер состояний выводов порта (Q2). Во внутреннем буфере устанавливается то состояние выбранного бита, которое задано командой bcf/bsf (Q3). Далее, содержимое внутреннего буфера копируется (Q4) в регистр порта. Обратите внимание на то, что происходит чтение (Q2) состояний выводов порта. Если все каналы порта настроены "на выход", то и проблем нет, так как выходы всех защёлок электрически подключены к соответствующим выводам порта. Проблем нет также и в случае наличия одного канала порта, работающего на вход. А вот если часть из них (от 2-х и более) настроена на работу "на вход" (высокоимпендансное состояние, выходы соответствующих защёлок электрически от них отключены), то могут быть проблемы, и весьма существенные. Например, состояние выводов порта (допустим, С), ранее настроенного на работу "на выход", такое: 111х хххх, где х - то, что нужно оставить без изменения. Архинужно сменить 111х хххх на 000х хххх. Допустим, что перед применением команды bcf/bsf, по каким-то уважительным причинам, левые 3 канала порта С настроены "на вход" (например, ПИКу нужно опросить флаг занятости ЖК-модуля и/или свершить другие подвиги, требующие такой настройки). То есть, входы этих ПИК-каналов переведены в высокоимпендансное состояние (Rвх - много мегоом). Если к ним подключены входы управления неким внешним устройством также имеющие высокое Rвх., то более чем вероятно, что на выводах RC7,6,5 установятся единичные логические уровни. Посмотрим, что получится. 1. bcf PortC,7 Во внутренний буфер запишется 111х хххх. В регистр PortС запишется 011х хххх. Если на этом и закончить (то есть, нужно сбросить только один-разьединственный бит №7), то всё в норме, но по условию задачи, этого мало. "Потоково" сбрасываем дальше. 2. bcf PortC,6 Во внутренний буфер запишется 111х хххх. Выполнение: 101х хххх. В регистр PortB запишется 101х хххх. 3. bcf PortC,6 Во внутренний буфер запишется 111х хххх. Выполнение: 110х хххх. В регистр PortС запишется 110х хххх. Вывод: было нужно 000х хххх, а получилось 110х хххх, что чревато нехорошими последствиями. Предположим, что 3 старших канала порта С управляют режимами работы ЖК-модуля, и архинужно сделать так, чтобы после осуществления перевода этих каналов на работу "на выход", в соответствующих защёлках было установлено состояние 000х хххх, а в наличии имеется 110х хххх. Вопрос: что это такое? Ответ: функциональный сбой в работе ЖК-модуля, который в упор не запланирован конструктором. Это что-то типа "глюка". В этом случае, никакие разделительные NOPы не помогут. Хоть сто штук (условно). Эту беду, с помощью дополнительных команд, победить можно, но зачем, ведь эту "страсть" можно заменить всего-лишь тремя байт-ориентированными командами, после чего описанного выше безобразия просто не будет. Ещё раз дружески советую: в случаях возникновения подобного рода конфузов, нужно просто перейти с бит-ориентированных команд, на байт-ориентированные, и все дела ("дёшево и сердито"). Проверено жизнью, и не один раз (эквивалент "штампа ОТК"). Что по этому тексту думают профессионалы и начинающие?

medved: В регистр PortС запишется 011х хххх. Если на этом и закончить (то есть, нужно сбросить только один-разьединственный бит №7), то всё в норме, но по условию задачи, этого мало. "Потоково" сбрасываем дальше. 2. bcf PortC,6 Во внутренний буфер запишется 111х хххх. Для меня лично (по данному тексту) осталось загадкой почему во внутренний буфер запишется 111х хххх, ведь в регистр уже записано 011х хххх. И если после первого BCF все будет в норме, то во время второго BCF в регистре почему-то вылазит "бяка". Прямо полтергейст какой-то.

igor: "Частотная составляющая", и особенно в случаях работы на максимальной Fosc, конечно же важна. Её признак - избавление от "бяки" после осуществления "врезки" NOPов, но у меня были такие случаи, что "врезки" даже десятков NOPов не помогали. Что подразумевает автор под словом "бяка"? Не пояснил. Бяка и всё. Об остальном догадайтесь. Для чего автор врезает NOPы. Не пояснил. Врезал и всё. Об остальном догадайтесь.

Алексей: Да уж, не хотел бы я по такому объяснению разбираться с ЧМЗ... Сочувствую...

Bigor: А мне кажется, что цитаты "мастера" приведенные Анатолием (medved) не столько объясняют проблему ЧМЗ, сколько запутывают её. Это пример того, как не следует объяснять ЧМЗ. Вполне вразумительно эта проблема разъяснена в данной теме в постах Алексея и В. Тимофеева (tester-а).

Bigor: Уважаемые коллеги! Многие посты этой темы, и не только этой, на прямую подсказывают "мастеру" что отвечать на вопросы задаваемые на его форуме. Он, с некоторой задержкой, переводит на свой "суконно-пламенный" язык ответы с этого форума (правда, не всегда удачно) и публикует их от своего имени на форуме имени себя. Вот такая "загагулина" получается. Хоть бы спасибо сказал.

igor: Bigor пишет: переводит на свой "суконно-пламенный" язык ответы с этого форума (правда, не всегда удачно) и публикует их от своего имени на форуме имени себя. Да и пускай пользуется. Так оно и было всегда. Только хочется пожелать автору, чтобы в этих перевода было поменьше воды и ошибок. И откуда они только берутся эти ошибки. И я придерживаюсь мнения, что "мастеру" не надо писать так уж заумно. Попроще, подоходчивей. Оно и самому понятней будет и птенцам. Но это моё мнение. Если фиксированная задержка в 3 м.ц. (3 NOPа) не помогает, то это не то, о чём идёт речь в этом сообщении, а то, чему посвящено моё предыдущее сообщение Откуда такая уверенность? Почему именно три NOPа, а не два или пять? Непонятно. Вопрос: "В одной из разбираемых мной программ обнаружил неизвестные мне ранее команды: BNZ, BC, BZ. М ожет кто разъяснит их значение?" А почему бы и нет. Не буду умничать, просто открою книжку Предко " Справочник по PIC микроконтроллерам". Там написано :.......чтобы повысить функциональную гибкость системы команд микроконтроллеров младшего и среднего подсемейств, фирмой microchip введены специальные команды (макрокоманды). [pre2] BNZ label равнозначна btfss STATUS,Z ;если результат не равен нулю goto Label ; то переход BC Label равнозначна btfsc STATUS,C ;переход при переносе goto Label BZ Label равнозначна btfsc STATUS,Z ;если результат равен нулю goto Label ; то переход[/pre2]

Алексей: "В одной из разбираемых мной программ обнаружил неизвестные мне ранее команды: BNZ, BC, BZ. М ожет кто разъяснит их значение?" Мне так непонятна, такая жгучая ненависть мастера ко всем даже макрокомандам ... ведь без них никак не обойтись... В смысле без [pre2]btfsc STATUS,Z ;если результат равен нулю goto Label ; то переход [/pre2] А раз так, откуда такая ненависть к макроопределениям?

tester: Вот от производителя (см. главу 9.10): PIC Mid-Range MCU Family Reference Manual И для ленивых на русском. Еще добавлю: кто-то тут написал, что проблема касается только бит-ориентированных команд. Это не так. Проблема актуальна для всех команд, работающих по принципу RMW (read-modify-write), т.е. для все команд, изменяющих значение содержимого регистра, кроме команд MOVWF и CLRF.

Алексей: tester пишет: кто-то тут написал, что проблема касается только бит-ориентированных команд Наверно это был я

medved: Алексей пишет: Наверно это был я Нет, Алексей, не ты. Нечего себе чужие заслуги присваивать "мастер" пишет: Ещё раз дружески советую: в случаях возникновения подобного рода конфузов, нужно просто перейти с бит-ориентированных команд, на байт-ориентированные, и все дела ("дёшево и сердито"). Проверено жизнью, и не один раз (эквивалент "штампа ОТК"). Правильно должно быть так tester пишет: Выходов - два: 1. Простой (по рекомендации микрочипа) - разделять RMW-инструкции над портами ввод/вывода хотя бы одним NOP'ом. 2. Правильный - работать через буферный регистр. Как он сейчас будет выкручиваться? Опять Далласа приплетет? PS Кстати здесь тоже у него тоже закралась неточность. Правильно будет "Директива Даллеса (Аллен Уэлш Даллес). Врагов надо знать в лицо, а тем более как пишутся их фамилии

Доктор: Sergey Roslik пишет: в мплабе крутите его и наблюдаете состояние регистров, куда уже наглядней. да не крутится....

Доктор: medved пишет: Читаешь с ножки МК, а пишешь в защелку. Поучите,Гуру.Вроде и по- руски - - а ничего не ронятно.

Доктор: Доктор пишет: ронятно. палец попал не туда - -а все ровно не понял,medved? Подскажи,если не трудно.

igor: Что конкретно не понятно?

Bigor: Доктор, любой порт, как двуликий Янус, его выводы могут работать как на вход так и на выход. При считывнии со входа Вы (точнее МК) снимаете информацию прямо с вывода, а при использовании для выведении инфы она записывается в защелку. При этом возможны проблемы, которые рассмотрены в этой теме.

Доктор: Bigor пишет: Уважаемые коллеги! Многие посты этой темы, и не только этой, на прямую подсказывают "мастеру" что отвечать на вопросы задаваемые на его форуме. Он, с некоторой задержкой, переводит на свой "суконно-пламенный" язык Уважаемы форумчане,ттоли я не туда попал,толи не понимаю ничего.А так и есть,я еще молодой,.Кто это - мастер? Я этот форум в поиску нашел,хотел подучиться малость,но но как -то трудно уже с первых постов.Medved -я понимаю,что тема интересная,но вот если бы попроще...

Bigor: Доктор пишет: Кто это - мастер? Это наши внутренние разборки. Вкратце - очень амбициозный человек.

SanSanich: Доктор Собственно, вопрос так и не был задан. Что у Вас не получается?

Bigor: Доктор, учиться надо по литературе. Желательно по фирменным апнотам и некоторым книгам. Одна из них принадлежит перу tester-а. Ее можно скачать здесь И еще информация на русском http://www.microchip.ru/lit/?mid=1x0. Изучайте и задавайте вопросы. Успехов.

Доктор: Ну слава тебе,Господи,хоть кто-то посоветовал дело.На других форумах так сразу лесом посылали...

Доктор: SanSanich пишет: Собственно, вопрос так и не был задан Еслиб бы я их умел задавать...

SanSanich: Доктор пишет: Еслиб бы я их умел задавать... Это наводит на некоторые мысли Если Вы чисто позабавиться, Вам не сюда. Я бы посоветовал Вам заполнить свой профиль, хотябы возраст, чтоб участникам было легче ориентироваться в способе и методе оказания Вам помощи.

medved: Специально для Доктора попробую еще раз с самого начала. МК имеет выходные защелки, которые автоматически отключаются от ножки при переключении на вход. Для примера возьмем PORTB. Переключением управляет регистр TRISB Допустим следующие исходные данные: в TRISB "лежит" значение 0010 0000, т.е. RB5 настроен на вход, остальные на выход. в PORTB - 0000 1111 Далее считываем данные с PORTB (на самом деле читаем с ножек), а на ножках 0010 1111. Ведь пятый вывод порта у нас настроен на вход и там может быть любое значение. Производим какие-то действия со считанными данными, например очистим нулевой бит и запишем опять в регистр 0010 1110. И все бы ничего, но стоит нам переключить пятый вывод на выход начнутся непонятки. Ведь в регистре пятым битом был 0 и мы никаких действий с ним вроде бы не делали, а значит там и должен быть 0. На самом деле там уже 1. Понятно?

Алексей: Доктор пишет: хотел подучиться малость А можно ваш уровень подготовки? Может зря пока полезли в самые дебри?

Доктор: Алексей пишет: Может зря пока полезли в самые дебри Алексей,спасибо за пост.Беда в том,что я пока не знаю,где тут дебри,а где нет.Моя основа - три книжки А.В.Фрунзе.Кроме скальпеля,умею держать паяльник.medved,спасибо,только скажите мне,где это начало?Что я должен прочесть и знать?Я это сделаю. И не о каких забавах речь не идет.ВЕСЕЛЯЩИЙСЯ ДОКТОР это ХУЖЕ ЦУНАМИ.Профиль я сейчас оформлю.С уважением ко всем,Доктор.

medved: Доктор пишет: где это начало? По-моему Вам действительно это еще рановато. Доктор пишет: Что я должен прочесть и знать? Почитайте Справочник по среднему семейству микроконтроллеров PICmicro

Bigor: Доктор, начало определяется имеющимся начальным уровнем. В МК приходят разные люди. Опытные электронщики (без знаний в программировании) и программисты разного уровня (без знания электроники) и различные промежуточные любители и специалисты. Определите для себя кто Вы и исходя из этого планируйте свою работу над собой и что прочесть. В какой мере Вы знаете английский? Это в нашем деле очень важно. разработка программ (проектов) для пиков производится в среде MPLAB последнюю версию скачайте и потихоньку разбирайтесь. Скачать можно по ссылке: http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en019469&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002#

Вячеслав: Bigor пишет: потихоньку разбирайтесь. Лучше не скажешь. МК - это почти вторая профессия. Дисциплинирует, подтягивает интеллект. Доктор, года полтора Ваши "шестерни" должны скрипеть. Разбирайте чужие проекты. Пытайтесь создать свои. Заставить заработать холодную железяку - это как вылечить уже "холодного" пациента. Успехов.

Photographer: Вячеслав пишет: Заставить заработать холодную железяку - это как вылечить уже "холодного" пациента. Ужас как двусмысленно. Доктор пишет: Беда в том,что я пока не знаю,где тут дебри,а где нет.Моя основа - три книжки А.В.Фрунзе.Кроме скальпеля,умею держать паяльник.medved,спасибо,только скажите мне,где это начало?Что я должен прочесть и знать?Я это сделаю. И не о каких забавах речь не идет. Отвечу по своему, решайте сами как поступить. Давно зрела идея, вот и повод подвернулся. По моему ничего за ранее читать и изучать не надо, особенно в вашей ситуации. В любом случае Вам программирование надо не для галочки, а под какие то конкретные цели. Возможно у Вас есть уже какие то идеи и проекты. А если нет, то не страшно. Можно для начала и помигать светодиодом. А там и ещё чего захочется. Предлагаю прямо сейчас открыть личную тему и начать реализовывать в реальное устройство свою идею. А там и ясно будет чем помочь и что не получается. В этом разделе "Для начинающих" я создал свою такую личную тему. Можете взять её за образец. Просто выкладывайте там свою идею, исходники и начинайте работать, спрашивать. Уверен, что при таком раскладе дело у Вас пойдёт быстрее.



полная версия страницы