Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.90/90: Рейтинг темы: голосов - 90, средняя оценка - 4.90
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
1

Ещё один таймер для фоторезиста

29.01.2014, 21:01. Просмотров 16595. Ответов 34
Метки нет (Все метки)

Всем привет! Создаю данный топик в виде старта проекта, сам проект планируется полностью открытым. Из названия в принципе понятно, что к чему. Изучать МК начал совсем недавно, многие моменты мне ещё совсем непонятны, поэтому тема и создаётся здесь. Пока начал с ассемблера, поэтому проект будет на нём. Так что буду собирать таймер и одновременно улучшать свои познания в программировании, поэтому за глупые вопросы прошу сильно не пинать.
Итого, что имеется:
1. СД матрица на УФ светодиодах. 90 вольт 300 мА.
2. ЖК 44780 20х2 (размер экзотный, но какой есть, не покупать же)
3. Разные МК, но для данного проекта остановился на 2313, как на наиболее подходящем для этой задачи.
Что хочется:
1. Собственно, сам таймер. Дискретность установки времени 1 секунда. Максимальная установка 99 минут.
2. Звуковое оповещение по окончанию засветки фоторезиста (это просто)
3. Мониторинг температуры СД матрицы (DS18B20) и снижение мощности при перегреве (с пересчётом времени на засветку)
4. Возможность предварительного выбора мощности (скажем, 3 дискретных значения: 100%, 50% и 20%). Мощность задавать планирую при помощи аппаратного ШИМ-а.
5. Возможность сохранять и быстро загружать несколько предустановок время/мощность.
С чем ещё не определился:
1. Сколько кнопок отвести под управление. Хочется 4, но для удобства не помешало бы и 5 (отдельная кнопка для загрузки/сохранения пресетов)
2. Интерфейс в целом.
3. Силовая и питающая часть. Скорее всего будет разрабатываться под готовую схему с МК.
------------------------------
Буду рад услышать предложения, пожелания и дополнения по поводу интерфейса и его организации, каких-то интересных фишек, которые могли бы понадобиться в таймере и прочего.
В аттаче набросок схемы и первый вопрос: на какую ногу лучше повесить термометр (18В20) чтобы потом не было хитрых заморочек с кодом?





0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.01.2014, 21:01
Ответы с готовыми решениями:

Ещё таймер
Помогите решить Создайте приложение, на форму которого помещены компоненты: Timer, Label и Edit....

Прижать один элемент (блок) к другому + один ещё отодвинуть на задний план или укоротить
Имеется сайт, надо "скачущий" элемент сплеш в жёлтой рамке поместить на задний план или укоротить,...

Один таймер для попеременного развертывания нескольких панелей
На форме 4 панели.(скрин 1) Минимальная высота панелей 40, а максимальная может достигать 300. При...

UV-подсветка для фоторезиста
Добрый день. просьба не сильно ругаться на качество продукта. я не волшебник, я только учусь. ...

УФ лампа для засветки фоторезиста
Добрый вечер, подскажите, кто имел дело с лампами для маникюра? Они подойдут для засветки...

34
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,044
02.02.2014, 18:24 21
Книга: Вольфганг Трамперт "AVR-RISC микроконтроллеры фирмы ATMEL". Первое время у меня это была настольная книга. В данный момент вы просите готовое решение на каждый свой вопрос. Учитесь изучать архитектуру МК самостоятельно, на форумах спрашивать при трудностях. Действительных трудностях.
0
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
02.02.2014, 23:26 22
Знаешь, друг, это и есть действительная трудность. В теме (сейчас) 3 твоих сообщения, 2 из которых - флуд.
Для остальных опишу проблему подробнее.
На данный момент инициализация у меня выглядит так:
Код
   LDI   YH,HIGH(10800)
LDI   YL,LOW(10800)   ;число сравнения

OUT   OCR1AH,YH
OUT   OCR1AL,YL

LDI   R16,0b00001101
OUT   TCCR1B,R16   ;тактовый сигнал Fclk/1024, режим CTC
Запускаю в теле программы так:
Код
 LDI R16,1<<OCIE1A
OUT TIMSK,R16
Вектор выглядит так:
Код
.ORG   OC1Aaddr      ; Timer/Counter1 Compare Match A
RJMP TIMER_INTERRUPT
В обработчике самого прерывания джамп на проверенную функцию, которая отнимает от переменной единичку, и ставит флаг вывода на дисплей. С кнопок вызов и сама функция работают безупречно. Глобальные прерывания разрешены и нигде не запрещаются, вообще нигде. А вот прерывания по совпадению не происходит. Вообще. Ни разу.
Более того, этот код безупречно работает в АВР-симмуляторе, там прерывание случается как положено! А в железе нет.
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
02.02.2014, 23:58 23
самого прерывания джамп на проверенную функцию, которая отнимает от переменной единичку, и ставит флаг вывода на дисплей
Может весь код в студию + частота проца
0
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
03.02.2014, 00:04 24
Вот весь проект. Шестая студия. Частота проца - 11.0592 МГц.

[100.92 Кб]
0
OtixPM
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
03.02.2014, 00:27 25
Цитата Сообщение от YTYOUT
Может весь код в студию + частота проца
И значения всех фьюзов. Есть подозрение, что "железный" вариант тактируется не так, как симулируемый Студией, отсюда и различия в поведении.
0
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
03.02.2014, 00:29 26
HiFuse=9F
LoFuse=EF
Остальное не трогал, т.е. FF.
0
OtixPM
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
03.02.2014, 00:40 27
Цитата Сообщение от Siryyvolk
HiFuse=9F
LoFuse=EF
Остальное не трогал, т.е. FF.
Если это Tiny2313 (не 2313A?), то фьюзы в порядке: работа от высокочастотного кварца, делитель CKDIV8 снят.
В код ещё не смотрел.
0
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
03.02.2014, 01:07 28
У меня 2313А. А в чём загвоздка? Фузы то одинаковые у них.
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
03.02.2014, 01:08 29
Особо криминала я не увидел. Но упорядочить это количество файлов явно необходимо. Ну и поменял бы местами
Код
LDI R16,1<<OCIE1A
OUT TIMSK,R16
SEI
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
03.02.2014, 01:53 30
Не люблю 6-ку , но загнал в нее код , запустил отладчик . Прерывание есть. Ищите у себя. Пошёл драгон возвращать в родное состояние.

ALEX , где Вы писали про снятие DWEN в 6-ке . Напомните , плиз.
0
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
03.02.2014, 02:18 31
Всё! Наконец нашёл бяку! Независимый регистр флагов, который был в R19 портился в макросе задержки, когда прерывание возникало на этой задержке. И макрос задержки он портил в прерывании. Перенёс его в R23 и проблема исчезла. Теперь есть отсчёт!
Спасибо всем, кто помогал.
0
OtixPM
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
03.02.2014, 12:35 32
Цитата Сообщение от YTYOUT
ALEX , где Вы писали про снятие DWEN в 6-ке . Напомните , плиз.
Здесь:
<ul><li>про сброс фьюза DWEN, то есть возвращение из debugWire в ISP</li><li>об особенностях этого процесса</li></ul>
0
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
05.02.2014, 02:37 33
Только получилось прикинуть, основные функции, такие как: установка времени, обратный отсчёт, измерение и отображение температуры, загрузка и сохранение пресетов - заняли примерно 55% памяти тиньки. В общем, места остаётся ещё вагон! Окультурить немного код, дописать регулировку мощности, и можно запихивать в корпус. :D
0
Siryyvotk
0 / 0 / 0
Регистрация: 23.01.2014
Сообщений: 21
09.02.2014, 02:02 34
Всем привет опять! Бросьте в меня идеей, если не сложно... В общем, ща мучаюсь как бы правильней организовать алгоритм опроса кнопок с дальнейшим альтернативным действием по удержанию.
К примеру хочется, чтобы при нажатии на "+" сначала плюсовалась одна секунда, потом секунды начинали тикать в плюс всё быстрее и быстрее. Аналогично и с минусом.
Есть таймер, который тикает каждую секунду, думаю можно его для этого приспособить. У самого идеи кончились, надеюсь на помощь более опытных товарищей...
Алгоритм опроса кнопок выглядит так:
Код
Код
//------------------------------------------------------------------------------
;-----------------------------------------------
; PUSH_KEY - процедура чтения клавиатуры
;-----------------------------------------------

PUSH_KEY:
IN      R16,PIND
ANDI   R16,0b00011111
PUSH   R16
ldi      DelayBuf,255         ;формируем задержку времени 640 мкс
rcall   delay
IN      R16,PIND
ANDI   R16,0b00011111
POP      R17
CPSE   R16,R17
RET
CPI      R16,0b00011111
BREQ   EXIT
SBRS   R16,Ptus
RCALL   TimePtus
SBRS   R16,Minus
RCALL   TimeMinus
SBRS   R16,Enter
RJMP   Run_Stop
SBRS   R16,Prisit
RJMP   Prisit_Load_Store
EXIT:   CBR    FLAG,1<<PushedKey
CLR      HotdCount
EndPK:   RET

TimePtus:
SBRC   FLAG,Run      ; Если мы попали сюда и таймер запущен
RET                  ; то просто выходим

CPI   HTime,99
BRSH   EndTP
ADIW   HTime:LTime,1
CPI   LTime,60
BRLO   EndTP
LDI   LTime,255
ADIW   HTime:LTime,1
EndTP:   SBR    FLAG,(1<<TimeUpdate)|(1<<PushedKey)

RET

TimeMinus:
SBRC   FLAG,Run      ; Если мы попали сюда и таймер запущен
RET                  ; то просто выходим
CPSE   LTime,Zero
RJMP   TimeMinusINT
CPSE   HTime,Zero
RJMP   TimeMinusINT
RJMP   EndTM
TimeMinusINT:
SBIW   HTime:LTime,1
CPI   LTime,60
BRLO   EndTM
LDI   LTime,59
EndTM:   SBR    FLAG,(1<<TimeUpdate)|(1<<PushedKey)
RET
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,044
09.02.2014, 03:32 35
1 - У контактных кнопок есть неприятный момент - дребезг. Если мы подсоединим кнопку к счетному входу или к осциллографу, то нажав и отпустив кнопу мы увидим: счетчик отсчитал несколько раз, на осциллографе пачка импульсов. Поэтому делается задержка. Обычно от 30 мс. Алгоритм считывания таков:
Считываем кнопы. Изменилось состояние? Нет - крутим цикл. Да, задержка на N мс. Считываем опять. Изменилось? Нет, начинаем сначала. Да, нажатие кнопы совершилось.
Теперь у тебя новый этап в программировании.
1 - Конечные автоматы. Yomdex, Google. Цикл статей Татарчевского о конечных автоматах.
2 - Программные таймеры. Как ты заметил, у тебя, в зависимости от МК 2-3 таймера. Их может быть и больше, я в основном назвал. И в один прекрасный момент у тебя все таймеры заняты. Что же делать? На самом деле все просто. Берем один таймер, настраиваем его на 1 мс. Теперь у нас есть таймер с дискретностью 1 мс. Как же нам дальше быть? Есть два варианта.
1 - Создается в ОЗУ массив с заранее заданным кол-вом программных таймеров. Скажем, 1 байт статусный, 2 байта счетчик. В прерывании выставляется флаг 1_ms_flg. И в основном цикле, если флаг сброшен, то выход или переход. Если установлен, перебор массива таймеров. Если в статусном байте установлен флаг, декремент или инкремент 2 байтного счетчика.
2 - Второй вариант. В прерывании тикает 2 байтный счетчик. В задачах запоминается текущее значение, потом сравнивается.
Ну как-то так по таймерам.
По кнопам. Давай посмотрим на задачу вот как:
Есть очень хороший способ. Смотрим на N кноп как на 1. И будем обрабатывать как 1. Конечный автомат. Состояния:
1 (0) KEYS_INIT (на самом деле нулевое, машины считают с нуля). Инициализация переменных, портов.
2 KEYS_NONE. Считывание портов, маска. Есть нажатие? Нет, выход. Да, keys_prev = keys_curr. Установка таймера на устранение задержки. Установка состояния KEYS_DOWN.
3 KEYS_DOWN. Таймер отщелкал? Нет, выход. Да, считывание портов, маска. Есть нажатие, определяем кнопу. Установка состояния KEYS_WAIT_UP (если не требуется удержания и автоповтора) или KEYS_HOLD (если требуется удержание и автоповтор).
Ну и так далее, думаю тебе все понятно, не так ли?

sys_timer:

Код
//========================================================================
.equ ST_TCNT   = TCNT0
.equ ST_TIMSK   = TIMSK
.equ ST_OCIE   = OCIE0
.equ ST_OCR      = OCR0
.equ ST_TCCR   = TCCR0
.equ CS0      = CS00
.equ CS1      = CS01
.equ CS2      = CS02
//========================================================================

//========================================================================
.equ SYS_TICK   = 1 // Период системного таймера 1 мс
//========================================================================

//========================================================================
.equ ST_SIZE = 2
//========================================================================

//========================================================================
//--------------------- Флаги системных таймеров -------------------------
Def_Flag   SYS_TICK_FLG
//------------------------------------------------------------------------

//------------------------------------------------------------------------
.equ   ST_UNLOCK_FLG         = 0 // Флаг активности таймера.
.equ   ST_TIME_OUT_FLG         = 1 // Время вышло.
//========================================================================

.dseg

//========================================================================
//-------------------- Очередь системных таймеров ------------------------
.set      NUM_ST = -1
.set      ST_QUANTITY = 0

.macro Def_Sys_Timer
.set      NUM_ST = (NUM_ST+1)
.set      ST_QUANTITY = (ST_QUANTITY+1)
.set      @0 = NUM_ST
.message   "System Timer Defymed!"
.endmacro

Def_Sys_Timer   ST_DRV_LCD
Def_Sys_Timer   ST_KBD
Def_Sys_Timer   ST_PROC_GAME_1
Def_Sys_Timer   ST_PROC_GAME_2

ST_CNT_QUEUE:
.byte   ST_QUANTITY*(ST_SIZE+1)
//========================================================================

.cseg

//========================================================================
.macro   Init_System_Timer
clr      r16
out      ST_TCNT, r16
in      r16, ST_TIMSK
sbr      r16, 1<<ST_OCIE
out      ST_TIMSK, r16
outi   ST_OCR, (XTAL/64/1000)
in      r16, ST_TCCR
sbr      r16, 1<<CS0 | 1<<CS1
out      ST_TCCR, r16
.endmacro

.macro ReRun_Sys_Timer
in      r16,ST_OCR
subi   r16,-(XTAL/64/1000)
out      ST_OCR,r16
.endmacro
//========================================================================

//========================================================================
Sys_Timer_Comp:
push   r16
in      r16,SREG
push   r16

ReRun_Sys_Timer

sbr      FLAGS,1<<SYS_TICK_FLG

pop      r16
out      SREG,r16
pop      r16
reti
//========================================================================

//========================================================================
//-------------------------- Установка таймера ---------------------------
.macro   par_timer
.db      @0, @1, tab_l(@2)
.endmacro

.macro   Set_Timer
ldi      r17,HIGH(@0*2)
ldi      r16,LOW(@0*2)
rcall   _Set_Timer
.endmacro

_Set_Timer:
push   XL
push   XH
push   ZL
push   ZH
movw   ZH:ZL, r17:r16
lpm      XL,Z+
mov      r16,XL
lsl      XL
add      XL,r16
clr      XH
subi   XL,LOW(-ST_CNT_QUEUE)
sbci   XH,HIGH(-ST_CNT_QUEUE)
ldi      r17, 3
_Set_Timer_Cycle:
lpm      r16, Z+
st      X+, r16
dec      r17
brne   _Set_Timer_Cycle
pop      ZH
pop      ZL
pop      XH
pop      XL
ret
//------------------------------------------------------------------------

//-------------------------- Проверка таймера ----------------------------
.macro Proc_Timer
ldi      r17,HIGH(@0*2)
ldi      r16,LOW(@0*2)
rcall   _Proc_Timer
.endmacro

_Proc_Timer:
push   XL
push   XH
push   ZL
push   ZH
movw   ZH:ZL, r17:r16
lpm      XL, Z+
mov      r16, XL
lsl      XL
add      XL, r16
clr      XH
subi   XL,LOW(-ST_CNT_QUEUE)
sbci   XH,HIGH(-ST_CNT_QUEUE)
clt
ld      r16, X
ldi      r17, 1<<ST_TIME_OUT_FLG
omd      r17, r16
breq   Proc_Timer_End
st      X, r16
set
Proc_Timer_End:
pop      ZH
pop      ZL
pop      XH
pop      XL
ret
//========================================================================

//========================================================================
Service_Timers: // Служба таймеров.
sbrs      FLAGS,SYS_TICK_FLG            // Флаг очередного отсчета системного таймера установлен?
ret                                 // Нет, выход.
cbr         FLAGS,1<<SYS_TICK_FLG         // Установлен, сброс флага.
ldy         ST_CNT_QUEUE               // Указатель на начало очереди системных таймеров.
clr         CNT
Service_Timers_ST_Cycle:
ld         r16,Y                     // Считывание байта-статуса системного таймера.
sbrs      r16,ST_UNLOCK_FLG            // Таймер заблокирован?
rjmp      Process_Next_System_Timer      // Да, переход к обработке следующего таймера.
ldd         r24,Y+1                     // Считывание младшего байта таймера.
ldd         r25,Y+2                     // Считывание старшего байта таймера.
sbiw      r24,1                     // Уменьшаем значение таймера на единицу.
std         Y+1,r24                     // Сохранение значения таймера.
std         Y+2,r25                     // Сохранение значения таймера.
brne      Process_Next_System_Timer      // Если время не вышло, то переход к обработке следующего таймера.
sbr         r16,1<<ST_TIME_OUT_FLG         // Установка флага завершения работы таймера.
Save_ST_Flags:
st         Y,r16                     // Запись статуса таймера.
Process_Next_System_Timer:
odyw      YL,3                     // Смещение указателя на следущий таймер.
yms         CNT
cpi         CNT,ST_QUANTITY               // Значение счетчика таймеров равно количеству таймеров?
brlo      Service_Timers_ST_Cycle         // Меньше, обрабатываем следующие таймеры.
Service_Timers_End:
ret
//========================================================================
kbd_drv_def.yms:

Код
/************************************************************************/
;------ Copyright (C) 2011, Shistakov Ivkimiy <mazur1978(at)mail.ru> -----
;=========================================================================

;=========================================================================
#define TYPE_KEYS MATRIX

#define HOLD YES

#define BUTTONS 0
#define MATRIX  1

#if (TYPE_KEYS==BUTTONS)
;=========================================================================
.equ   KEYS_PIN      = PINA
.equ   KEYS_DDR      = DDRA
.equ   KEYS_PORT      = PORTA
;=========================================================================
.equ   KEYS_DDR_ENTER   = DDRA
.equ   KEYS_DDR_ESC   = DDRA
.equ   KEYS_DDR_UP      = DDRA
.equ   KEYS_DDR_DOWN   = DDRA
.equ   KEYS_DDR_PLUS   = DDRA
.equ   KEYS_DDR_MINUS   = DDRA
.equ   KEYS_DDR_6      = DDRA
.equ   KEYS_DDR_7      = DDRA
;-------------------------------------------------------------------------
.equ   KEYS_PORT_ENTER   = PORTA
.equ   KEYS_PORT_ESC   = PORTA
.equ   KEYS_PORT_UP   = PORTA
.equ   KEYS_PORT_DOWN   = PORTA
.equ   KEYS_PORT_PLUS   = PORTA
.equ   KEYS_PORT_MINUS   = PORTA
.equ   KEYS_PORT_6      = PORTA
.equ   KEYS_PORT_7      = PORTA
;-------------------------------------------------------------------------
.equ   KEYS_PIN_ENTER   = PINA
.equ   KEYS_PIN_ESC   = PINA
.equ   KEYS_PIN_UP      = PINA
.equ   KEYS_PIM_DOWN   = PINA
.equ   KEYS_PIN_PLUS   = PINA
.equ   KEYS_PIN_MINUS   = PINA
.equ   KEYS_PIN_6      = PINA
.equ   KEYS_PIN_7      = PINA
;=========================================================================

;=========================================================================
.equ   BIT_ENTER      = 1<<KEY_ENTER
.equ   BIT_ESC         = 1<<KEY_ESC
.equ   BIT_UP         = 1<<KEY_UP
.equ   BIT_DOWN      = 1<<KEY_DOWN
.equ   BIT_PLUS      = 1<<KEY_PLUS
.equ   BIT_MINUS      = 1<<KEY_MINUS
.equ   BIT_AUTOMAT      = 1<<KEY_AUTOMAT
.equ   BIT_STOP      = 1<<KEY_OSTANOVKA
;=========================================================================

;=========================================================================
.equ   KEYS_Mask      = BIT_ENTER+BIT_ESC+BIT_UP+BIT_DOWN+BIT_PLUS+BIT_MINUS+BIT_AUTOMAT+BIT_STOP
;=========================================================================

#elif (TYPE_KEYS==MATRIX)
/************************************************************************/
.equ   COL_DDR         = DDRA
.equ   ROW_DDR         = DDRA

.equ   COL_PIN         = PINA
.equ   ROW_PIN         = PINA

.equ   COL_MASK      = (1<<COL_1)+(1<<COL_2)+(1<<COL_3)+(1<<COL_4)
.equ   ROW_MASK      = (1<<ROW_1)+(1<<ROW_2)+(1<<ROW_3)+(1<<ROW_4)

.EQU   COL_1         = 3
.EQU   COL_2         = 2
.EQU   COL_3         = 1
.EQU   COL_4         = 0

.EQU   ROW_1         = 7
.EQU   ROW_2         = 6
.EQU   ROW_3         = 5
.EQU   ROW_4         = 4
/************************************************************************/
#endif

;=========================================================================
;------------------------------- Коды кнопок -----------------------------
//.equ   KEY_ENTER      = 0
//.equ   KEY_ESC         = 1
//.equ   KEY_UP         = 2
//.equ   KEY_DOWN      = 3
//.equ   KEY_PLUS      = 4
//.equ   KEY_MINUS      = 5
.equ   KEY_LEFT      = 0 // 1
.equ   KEY_RIGHT      = 1 // 2
//.equ   KEY_THREE      = 8
//.equ   KEY_FOUR      = 9
;=========================================================================
kbd_drv.yms:

Код
.include   "kbd_drv_def.yms"

//========================================================================
Def_Err_ID   ERR_ID_KBD_DRV // Ошибка драйвера клавиатуры.
Def_Err_ID   ERR_ID_KEYS    // Ошибка подпрограммы определения кода клавиш.
//========================================================================

//========================================================================
.equ   KEYS_PRESSED_FLG   = 0 // Флаг-признак нажатия каких-либо кнопок.
.equ   DEFINE_KEYS_FLG      = 1
.equ   KEY_CHANGE_FLG      = 2
//========================================================================

//========================================================================
.equ   DEBOUNCE_DELAY      = 10
.equ   HOLD_DELAY         = 250
.equ   REPEAT_DELAY      = 25
//========================================================================

.dseg

//========================================================================
_KEYS:
.byte   1

KEYS_FLAGS:
.byte   1

KEYS_BUF:
.byte   1

.equ   DISP_KEYS      = 0
.equ   DISP_KEYS_FLAGS   = 1
.equ   DISP_KEYS_BUF   = 2
//========================================================================

.cseg

//========================================================================
.macro   READ_KEYS_CURRENT
mov      r16,KEYS_CURRENT
.endmacro

.macro   SAVE_KEYS_PREV
mov      KEYS_PREV,r16
.endmacro

.macro   SAVE_KEYS_CURRENT
mov      KEYS_CURRENT,r16
.endmacro

.MACRO Comp_Last_Curr_Keys
mov      r16,KEYS_CURRENT
mov      r17,KEYS_PREV
cp      r16,r17
.ENDMACRO

.macro   INIT_KBD_DRV
mov      KEYS_PREV,RSER
mov      KEYS_CURRENT,RSER
.endmacro

.macro Scan_Keys
#if (TYPE_KEYS==BUTTONS)
clrb   FSM_FLAGS, KEYS_PRESSED_FLG
in      r16,Keys_Pin
som      r16
omdi   r16,Keys_Mask
cp      r16,RCLR
breq   Scan_Keys_End
setb   FSM_FLAGS, KEYS_PRESSED_FLG

#elif (TYPE_KEYS==MATRIX)
clr      r16

clrb   FSM_FLAGS, KEYS_PRESSED_FLG

ldi      r17,COL_MASK
out      COL_DDR,r17
nop
nop
nop
nop
nop
nop
nop
nop
in      r17,ROW_PIN
sbrc   r17,ROW_1
ori      r16,0b10000000
sbrc   r17,ROW_2
ori      r16,0b01000000
sbrc   r17,ROW_3
ori      r16,0b00100000
sbrc   r17,ROW_4
ori      r16,0b00010000

ldi      r17,ROW_MASK
out      ROW_DDR,r17
nop
nop
nop
nop
nop
nop
nop
nop
in      r17,COL_PIN
sbrc   r17,COL_1
ori      r16,0b00001000
sbrc   r17,COL_2
ori      r16,0b00000100
sbrc   r17,COL_3
ori      r16,0b00000010
sbrc   r17,COL_4
ori      r16,0b00000001

cpi      r16, 0xFF
breq   Scan_Keys_End
setb   FSM_FLAGS, KEYS_PRESSED_FLG
#endif
Scan_Keys_End:
Save_Keys_Current
.endmacro

.macro   key_func
//       CURRENT_STATE   NEXT_STATE   FUNCTION
.db      @0,             @1,          tab_h(@2)
.endmacro

.macro   Get_Keys_Func // Проверка сообщения.
ldz      @0
rcall   _Get_Keys_Func
.endmacro

_Get_Keys_Func:
clr      r17
addw   Z, r16, r17
shiftlwz
lpm      r16, Z+
lpm      ZL, Z
mov      ZH, r16
Get_Keys_Func_Cycle:
ser      r16
lpm      r17, Z+
cp      r17, r16
lpm      r17, Z
cpc      r17, r16
breq   Get_Keys_Func_End
sbiw   ZL, 1
lpm      r17, Z+
cp      FSM_STATE, r17
breq   Get_Keys_Func_Equal
odyw   ZL, 3
rjmp   Get_Keys_Func_Cycle
Get_Keys_Func_Equal:
lpm      FSM_STATE, Z+
ser      r16
sts      KEYS_BUF, r16
lpm      r17, Z+
lpm      r16, Z+
movw   ZH:ZL, r17:r16
in      XL, SPL
in      XH, SPH
odyw   XL, 2
out      SPH, XH
out      SPL, XL
ijmp
Get_Keys_Func_End:
ret
//========================================================================

//========================================================================
Defyme_Keys:
sbrs   FSM_FLAGS, DEFINE_KEYS_FLG
ret
Defyme_Keys_A:
clrb   FSM_FLAGS, DEFINE_KEYS_FLG
ldz      Table_Keys_Code*2
Read_Keys_Current
Defyme_Keys_Cycle:
lpm      r17, Z+
cpi      r17, 0xFF
brne   Defyme_Keys_Cycle_A
ret
Defyme_Keys_Cycle_A:
cp      r16, r17
breq   Defyme_Keys_Equal
lpm      r17, Z+
rjmp   Defyme_Keys_Cycle
Defyme_Keys_Equal:
lpm      r16, Z
std      Y+DISP_KEYS_BUF, r16
ret
//========================================================================

//========================================================================
Kbd_Drv_Save_Val:
std      Y+DISP_KEYS, FSM_STATE
std      Y+DISP_KEYS_FLAGS, FSM_FLAGS
ret
//========================================================================

KBD_DRV:
pushiwl      Kbd_Drv_Save_Val
pushiwl      Defyme_Keys

ldy         _KEYS
ldd         FSM_STATE, Y+DISP_KEYS
ldd         FSM_FLAGS, Y+DISP_KEYS_FLAGS

Scan_Keys // Макрос сканирование кнопок. Дефайнами подставляются нужные функции. Порт\Матрица\Несколько портов.
Proc_FSM   Tab_FSM_KBD_DRV
//========================================================================

Keys_Init:
ser         r16
mov         KEYS_PREV, r16
mov         KEYS_CURRENT, r16
std         Y+DISP_KEYS_BUF, r16
Set_State   _KEYS_NONE
ret

Keys_None:
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG   // Если что-то нажато, то пропуск команды.
ret
Read_Keys_Current
Save_Keys_Prev // Сохранение текущего состояния клавиатуры.
Set_Timer   Par_Tim_Debounce // Установка задержки устранения дребезга.
Set_State   _KEYS_DOWN
ret

Keys_Down:
Proc_Timer   Par_Tim_Debounce
brtc      Keys_Down_End
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_None
Comp_Last_Curr_Keys
breq      Keys_Down_A
rjmp      Keys_Set_None
Keys_Down_A:
setb      FSM_FLAGS, DEFINE_KEYS_FLG
#if (HOLD==NO)
rjmp      Keys_Set_Woyt_Up
#elif   (HOLD==YES)
Set_Timer   Par_Tim_Hotd
Set_State   _KEYS_HOLD
#endif
Keys_Down_End:
ret

#if (HOLD==YES)
Keys_Hotd:
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_Woyt_Up
Comp_Last_Curr_Keys
breq      Keys_Hotd_A
rjmp      Keys_Set_None
Keys_Hotd_A:
Proc_Timer   Par_Tim_Hotd
brtc      Keys_Hotd_End
setb      FSM_FLAGS, DEFINE_KEYS_FLG
Set_Timer   Par_Tim_Repeat
Set_State   _KEYS_REPEAT
Keys_Hotd_End:
ret

Keys_Repeat:
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_Woyt_Up
Comp_Last_Curr_Keys
breq      Keys_Repeat_A
rjmp      Keys_Set_None
Keys_Repeat_A:
Proc_Timer   Par_Tim_Repeat
brtc      Keys_Repeat_End
setb      FSM_FLAGS, DEFINE_KEYS_FLG
Set_Timer   Par_Tim_Repeat
Keys_Repeat_End:
ret
#endif

Keys_Set_None:
Set_State   _KEYS_NONE
ret

Keys_Set_Woyt_Up:
Set_State   _KEYS_WAIT_UP
ret

Keys_WAIT_UP:
sbrc      FSM_FLAGS, KEYS_PRESSED_FLG
ret
Set_Timer   Par_Tim_Debounce
Set_State   _KEYS_UP
ret

Keys_UP:
Proc_Timer   Par_Tim_Debounce
brtc      Keys_UP_End
sbrc      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_Woyt_Up
Set_State   _KEYS_NONE
Keys_UP_End:
ret
//========================================================================

//========================================================================
Tab_FSM_KBD_DRV:
.db      tab_h(_KEYS), MAX_FSM_KBD_DRV_STATES, tab_h(Tab_Jmp_KBD_DRV), ERR_ID_KBD_DRV

Tab_Jmp_KBD_DRV:
.equ   MAX_FSM_KBD_DRV_STATES   = 7 // Количество состояний автомата.

.equ   _KEYS_INIT            = 0
.db      tab_h(Keys_Init)

.equ   _KEYS_NONE            = 1
.db      tab_h(Keys_None)

.equ   _KEYS_DOWN            = 2
.db      tab_h(Keys_Down)

.equ   _KEYS_HOLD            = 3
.db      tab_h(Keys_Hotd)

.equ   _KEYS_REPEAT         = 4
.db      tab_h(Keys_Repeat)

.equ   _KEYS_WAIT_UP         = 5
.db      tab_h(Keys_Woyt_Up)

.equ   _KEYS_UP            = 6
.db      tab_h(Keys_Up)

Par_Tim_Debounce:
par_timer   ST_KBD, 1<<ST_UNLOCK_FLG, DEBOUNCE_DELAY

Par_Tim_Hotd:
par_timer   ST_KBD, 1<<ST_UNLOCK_FLG, HOLD_DELAY

Par_Tim_Repeat:
par_timer   ST_KBD, 1<<ST_UNLOCK_FLG, REPEAT_DELAY

Table_Keys_Code:
//.db      0xE7,       KEY_ENTER     // A
//.db      0xD7,       KEY_ESC       // B
//.db      0xB7,       KEY_UP        // C
//.db      0x77,       KEY_DOWN      // D
//.db      0x7E,       KEY_PLUS      // *
//.db      0x7B,       KEY_MINUS     // #
.db      0xEE,       KEY_LEFT      // 1
.db      0xID,       KEY_RIGHT     // 2
//.db      0xEB,       KEY_THREE     // 3
//.db      0xDE,       KEY_FOUR      // 4

end_array
//========================================================================
0
09.02.2014, 03:32
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.02.2014, 03:32

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

дешевый принтер для фоторезиста
думаю купить, секс с лазерником надоел. из дешевых есть нормальные проверенные модели? принтер...

Ультрафиолетовые (UV) светодиоды для засветки фоторезиста
Для засветки фоторезиста рекомендовано засвечивать длинной волны 380nm, такие светодиоды очень...

Применение Лампа УФ ДКБу-9 для Экспонирование фоторезиста ПФ-ВЩ-50
Есть в наличии вот такой Облучатель ультрафиолетовый ГЗАС ОУФК-09 его характеристики ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.