Сообщение от Pajatel
|
.. Вот допустим к выложенному выше варианту практически притензий нету, но универсальностью он не блещет... Для другого проекта его скорей всего придётся перепахать и получится совсем другой код... Ваш вариант без таймера вообще только для конкретного вашего проекта.. я точно не буду считать шаги процессора чтоб получить задержки... а если кварц допустим поменяю или подпрограммку вклиню где-нить? ..опять всё пересчитывать?
|
Если Вы кнопки от проекта к проекту кнопки сажаете на разные порты то по любому и придется перепахивать , а куда ж от этого денешься , а задержки - на много ли процентов Вы меняете частоту в своих изделиях и как часто ? Если допустим в обработке было 50 мс при кварце в 12 Мгц и захотелось поменять на кварц в 16 или в 20 Мгц то сильно ли изменится надежность срабатывания если не менять ничего в проге обработки кнопок ? Да ничего существенно не изменится - там где без таймера - изменение в 1,5 раза всего общих задержек , можно смело менять кварц и не трогать прогу совсем .А в варианте с таймером - тоже почти ничего можно не трогать .Про добавки прог - ну добавили немного еще прог - а сильно ли времена выдержек изменятся ? Да в общем то не очень , так что слишком уж опасаться нечего .Потом не пойму а зачем Вам всеобщая универсальность такая ? У меня например от проекта к проекту и схема кнопок может меняться , и следовательно сам алгоритм опроса их ,написать какой надо под придуманную схему не проблема , а одно и то же схематическое решение, и под него некий универсальный алгоритм , - совать во все дырки постоянно не получится .
К примеру ,раз просили привести - привожу : реализовал передачу данных на светодиоды одновременно с приемом данных от кнопок , сами кнопки и светодиоды организованы в виде выносного пульта на кабеле , для обмена используется 4 жилы сигнальных и 2 питания , на стороне пульта - регистры HC589 - приемные с кнопок ,и HC595 - выходные для светодиодов пульта ,то есть 6 выводов на все , отдал порт "B" - обычно этот 6 битный , а как преимущество - на эти 4 сигнальных пока сидит 8 кнопок и 4 двухцветных светодиода , ну и еще семисегментный индикатор , но при расширении блока пульта хоть до 20 кнопок а светодиодов до 40 - обмен по все тем же 4 сигнальным проводам идет , и прога - одна и та же - только добавится число шагов считки . Сам процесс обмена оформлен в виде отдельной подпрограммы , вызывается когда надо из основной , и может быть легко перенесен из одного проекта в другой , если уж совсем ничего не менять в тексте то подключаем все это хозяйство к тому же порту что и было в прежних проектах .
IN_OUT: ;ПОДПРОГРАММА ВЫВОДА ИНФЫ НА СВЕТОДИОДЫ И СЕМИСЕГМЕНТНЫЕ ИНДИКАТОРЫ ПУЛЬТА
;УПРАВЛЕНИЯ И ОДНОВРЕМЕННОГО ПРИЕМА ИНФЫ СО ВСЕХ КНОПОК НАЖАТЫХ ИЛИ НЕТ С ЭТОГО ПУЛЬТА
;,ПОСЛЕДОВАТЕЛЬНО ПО ШЛЕЙФУ в 10 жил .А сама дешифрация - отдельно .Все выдержки времени
;для 8 Мгц тактовой AVR-а приведены.
cbi PORTB,3 ;делаем WR в 0 на 280 мкс примерно - забивка текущих положений всех кнопок
ldi RAB18,120
ldi RAB19,1
ldi RAB20,0
rcall TIME
sbi PORTB,3 ;устанавливаем WR в 1 - перегрузили данные кнопок в вых передающий регистр
; и далее забивка битов (светодиодов или любых других выходов)
ldi RAB18,120
ldi RAB19,1
ldi RAB20,0
rcall TIME ;выжидаем время чтобы первый же бит передаваемый из пульта успел успокоиться
; в линии
mov RAB16,F3 ;сдвигаемый и операции с ним можно производить на время вывода битов в выход
clr RAB17 ;счетный циклов
clr F1 ;сначала общий сброс всех битов приемных для кнопок
JJ1: sbic PINB,1 ;пропуск след команды если B1 сброшен
inc F1
; lsl F1 ;бит от 1 кнопки принят от пульта в F1 и он сдвинут для приема следующего бита
;также пока не сдвинули - устанавливаем уровень первого вых бита в B2 PINB ,из F3 с
;младшихших бит начинаем
sbi PORTB,2 ;устанавливаем вых уровень бита из AVR-а (в линии инверсный при этом)
sbrs RAB16,0 ;пропуск след команды если бит 0 в F3 тоже был установлен
cbi PORTB,2
;теперь все есть и готово к сигналу CLK для дальнейшей забивки
;далее даем строб CLK
cbi PORTB,0 ;даем CLK=0
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
sbi PORTB,0 ;даем CLK=1 обратно в 1 исходное
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
inc RAB17
; lsr RAB16 ;подставляем очередной следующий бит на 0 место
cpi RAB17,8
brsh HT1 ;если = 8 или больше то уже не уходим снова вверх а идем далее на формирование
;вых битов так как прием от 8 кнопок всего то уже принятых 8 бит заполнили F1 и можно уже
;работать без приема бит - а только на передачу оставштхся .
;-----далее следующий цикл обмена для следующего приемного бита и передаваемого бита------
lsr RAB16 ;подставляем очередной следующий бит на 0 место
lsl F1
rjmp JJ1
;забивка следующего байта - из F4 (младшими вперед)
HT1:
mov RAB16,F4
clr RAB17
JJ2: ;так как байт положений входов (кнопок) уже принят то нет куска проги по приему от B1
sbi PORTB,2 ;устанавливаем вых уровень бита из AVR-а (в линии инверсный при этом)
sbrs RAB16,0 ;пропуск след команды если бит 0 в F4 тоже был установлен
cbi PORTB,2
;теперь все есть и готово к сигналу CLK для дальнейшей забивки
;далее даем строб CLK
cbi PORTB,0 ;даем CLK=0
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
sbi PORTB,0 ;даем CLK=1 обратно в 1 исходное
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
inc RAB17
; lsr RAB16 ;подставляем очередной следующий бит на 0 место
cpi RAB17,8
brsh HT2 ;если = 8 то уже не уходим снова вверх а идем далее на формирование вых битов
;так как прием от8 кнопок всего то уже принятых 8 бит заполнили F1 и можно уже работать
;без приема бит - а только на передачу оставштхся .
;-----далее следующий цикл обмена для следующего приемного бита и передаваемого бита------
lsr RAB16 ;подставляем очередной следующий бит на 0 место
rjmp JJ2
;забивка следующего байта - из F5 (младшими вперед)
HT2:
mov RAB16,F5
clr RAB17
JJ3: ;так как байт положений входов (кнопок) уже принят то нет куска проги по приему от B1
sbi PORTB,2 ;устанавливаем вых уровень бита из AVR-а (в линии инверсный при этом)
sbrs RAB16,0 ;пропуск след команды если бит 0 в F3 был установлен
cbi PORTB,2
;теперь все есть и готово к сигналу CLK для дальнейшей забивки
;далее даем строб CLK
cbi PORTB,0 ;даем CLK=0
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
sbi PORTB,0 ;даем CLK=1 обратно в 1 исходное
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
inc RAB17
cpi RAB17,8
brsh HT3 ;если = 8 то уже не уходим снова вверх а идем далее на формирование вых битов
;так как прием от8 кнопок всего то уже принятых 8 бит заполнили F1 и можно уже работать
;без приема бит - а только на передачу оставштхся .
;-----далее следующий цикл обмена для следующего приемного бита и передаваемого бита------
lsr RAB16 ;подставляем очередной следующий бит на 0 место
rjmp JJ3
HT3:
;забивка следующего байта - из F6 (младшими вперед)
mov RAB16,F6
clr RAB17
JJ4: ;так как байт положений входов (кнопок) уже принят то нет куска проги по приему от B1
sbi PORTB,2 ;устанавливаем вых уровень бита из AVR-а (в линии инверсный при этом)
sbrs RAB16,0 ;пропуск след команды если бит 0 в F3 был установлен
cbi PORTB,2
;теперь все есть и готово к сигналу CLK для дальнейшей забивки
;далее даем строб CLK
cbi PORTB,0 ;даем CLK=0
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
sbi PORTB,0 ;даем CLK=1 обратно в 1 исходное
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
inc RAB17
cpi RAB17,8
brsh HT4 ;если = 8 то уже не уходим снова вверх а идем далее на формирование вых битов
;так как прием от8 кнопок всего то уже принятых 8 бит заполнили F1 и можно уже работать
;без приема бит - а только на передачу оставштхся .
;-----далее следующий цикл обмена для следующего приемного бита и передаваемого бита------
lsr RAB16 ;подставляем очередной следующий бит на 0 место
rjmp JJ4
HT4:
;забивка следующего байта - из F7 (младшими вперед)
mov RAB16,F7
clr RAB17
JJ5: ;так как байт положений входов (кнопок) уже принят то нет куска проги по приему от B1
sbi PORTB,2 ;устанавливаем вых уровень бита из AVR-а (в линии инверсный при этом)
sbrs RAB16,0 ;пропуск след команды если бит 0 в F3 был установлен
cbi PORTB,2
;теперь все есть и готово к сигналу CLK для дальнейшей забивки
;далее даем строб CLK
cbi PORTB,0 ;даем CLK=0
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
sbi PORTB,0 ;даем CLK=1 обратно в 1 исходное
ldi RAB18,120 ;выдерживаем примерно 200 мкс
ldi RAB19,1
ldi RAB20,0
rcall TIME
inc RAB17
cpi RAB17,8
brsh HT5 ;если = 8 то уже не уходим снова вверх а идем далее на формирование вых битов
;так как прием от8 кнопок всего то уже принятых 8 бит заполнили F1 и можно уже работать
;без приема бит - а только на передачу оставштхся .
;-----далее следующий цикл обмена для следующего приемного бита и передаваемого бита------
lsr RAB16 ;подставляем очередной следующий бит на 0 место
rjmp JJ5
HT5:
;забивка закончена , все биты переданы в линию в пульт в его приемный регистр
cbi PORTB,3 ;теперь делаем WR в 0 на 280 мкс примерно - забивка текущих положений
;всех только что принятых битов из регистра на выходы , в светодиоды
;и индикатор .
ldi RAB18,120
ldi RAB19,1
ldi RAB20,0
rcall TIME
sbi PORTB,3 ;устанавливаем WR в 1 - перегрузили данные кнопок в вых передающий регистр
; и далее забивка битов (светодиодов или любых других выходов)
ldi RAB18,120
ldi RAB19,1
ldi RAB20,0
rcall TIME ;выжидаем время чтобы первый же бит передаваемый из пульта успел успокоиться
; в линии
;----------------НУ ВОТ ТЕПЕРЬ ВРОДЕ КАК ВСЕ БИТЫ ВЫХОДОВ И ПЕРЕДАЛИ -------------------
ret
;-------------------------------------------------------------------------------------
Забыл сказать - TIME просто счетчик этих самых тактов задержки , это одна мелкая простая подпрограмма , просто считает такты не используя ничего - ни прерываний , ни флагов , обычный трехбайтовый программный счетчик ... и все - количество тактов и соответственно выдержку любую можно задавать перед ее вызовом загрузкой ее регистров счета , как в тексте приведенной подпрограммы выше , а можно было и в ней (в TIME мелкой то есть) поставить внутри фиксированное число , раз эти же значения повторяются в приведенной подпрограмме, и тогда уже при изменении кварца или добаки прог или еще чего - удобно менять все времена выдержек только из этого одного места .
P.S. Это как пример только (хоть и выдрал Вам из своего реального проекта) , что разных схем кнопок и их алгоритмов обслуги все же приличное множество , нормально работающих, а какие из них будут реализованы конкретно - зависит от фантазии и возможностей разработчика , лишь бы у него это надежно работало .