Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Алгоритм кнопочной клавиатуры с динамичной индикацией.


Алгоритм кнопочной клавиатуры с динамичной индикацией.

Сообщений 1 страница 30 из 38

1

Прошу совета, может горожу грабли, вдруг есть способ более быстрый.
Как можно максимально быстро по двум байтам сделать число в 1 байт?
То-есть 1 порт у меня постоянно в прерывании сдвигается "Rotate Portkn , Left", по другому порту у меня срабатывает прерывание по изменению фронта "Rising".
Когда прерывание по фронту срабатывает, я получаю значение порта вывода и значение порта входа - как их быстро объеденить, чтоб к примеру получить число 0-255?
Сработать на две кнопки не может, каждый байт равен 1 биту (1,2,4,8,32,64,128), в голову не лезет наиболее простой способ объединить это всё - (1,2,4,8,32,64,128) + (1,2,4,8,32,64,128) = уникальный 8 битный код.

На всякий случай выложу свой код (Xmega) клавиатуры + 5 светодиодов - используются 7 бит 1 корта и 8 бит другого:

Код:
Portkn Alias Portd                                          'Порт перебора для клавиатуры
Config Portkn = Output
Config Xpin = Portd , Slewrate = Enabled                    'Задерка скорости вывода порта
Pinkn Alias Pinc                                            'Порт входа сработанной кнопки
Config Portc = Input                                        'Порт входа сработанной кнопки на вход

Config Xpin = Pinc , Outpull = Pulldown , Slewrate = Enabled , Sense = Rising       'Вход порта сработанной кнопки подтчягиваем к минусу, ограничиваем скорость и определяем срабатывать по спаду
Portc_int0mask = &B0111_1111                                'Маска прерывания INT0 порта C

Ledkn Alias Portc.7                                         'Выход порта для динамичной индикации на клавиатуре
Config Ledkn = Output
Config Xpin = Portc.7 , Invertio = Enabled , Outpull = Totem , Sense = Inp_disabled       'Инвертируем, двухтактный вход, прерывание отключено

Dim Knl As Byte                                             'Адрес выхода сработанной кнопки
Dim Knh As Byte                                             'Адрес входа сработанной кнопки
Dim Led As Byte                                             'биты светодиодов динамичной индикации
Dim Ledtm As Byte                                           'Перебор битов в динамичной индикации

Portkn = 128
Config Tcf0 = Normal , Prescale = 256                       'Таймер динамичной индикации и опроса кнопок
Tcf0_per = 200                                              'Период сразабывания динамично индикации и опроса кнопок

On Tcf0_ovf Knopkitm                                        'Прерывание по таймеру для динамичной индикации и перебора кнопок
Enable Tcf0_ovf

On Portc_int0 Knopki                                        'Прерывание при сработанной кнопке
Enable Portc_int0

Enable Interrupts


Led=&b1111111_0
Do
If KnL>0 And Knh>0 Then
   Portc_intflags.0 = 1                                     'Сбрасываем прерывание перед включением прерывания по срабатыванию кнопки
   Enable Portc_int0                                        'Включаем прерывание срабатывания нажатой кнопки
End If
Loop


Knopkitm:                                                   'Прерывание по таймеру - вывод индикации и перебор кнопок
 Rotate Portkn , Left                                       'Сдвигаем порт на 1 бит в сторону
 Ledkn = Led.ledtm                                          'Включаем светодиод
 If Ledtm < 7 Then                                          'Перебираем биты в переменной LED для включения нужного светодиода
   Incr Ledtm
   Else
     Ledtm = 0

 End If
Return


Knopki:                                                     'Прерывание если сработала кнопка
Disable Portc_int0                                          'Отключаем прерывание по срабатыванию кнопок (его запустит то, что обработает кнопку)
     Knl = Pinkn                                            'Запоминаем порт
     Knh = Portkn                                           'Запоминаем Запоминаем порт перебора
Portc_intflags.0 = 1                                        'Сбрасываем буфер прерывания от остаточного дребезга
Return

Отредактировано Ev3658 (2018-01-18 14:26:18)

0

2

Ev3658 написал(а):

Прошу совета, может горожу грабли...

"Нам бы схемку, аль чертеж,
Мы б затеяли вертёж..." (с) Л.Филатов

Сколько кнопок-то, не 64, надеюсь ? ;)

0

3

Я вот тоже ничего не понял.

0

4

Да будет свет  :idea:
Всё-же просто.
при нажатии на кнопку получаю два байта адреса, не могу сообразить как эти два байта адреса максимально быстро впихнуть в один байт:
http://se.uploads.ru/t/hNqfD.jpg

0

5

Ev3658 написал(а):

Всё-же просто.при нажатии на кнопку получаю два байта адреса, не могу сообразить как эти два байта адреса максимально быстро впихнуть в один байт:

Первое, что приходит на ум...
Если нажата в конкретный момент будет только одна кнопка, то можно конвертнуть байты адреса в полубайты одного байта. Сформировать т.н. "условный адрес".
Не гарантирую, что будет "максимально быстро", но как вариант обмуслякать можно... ;)
Правда, потом будут неудобства с этой самой "условностью"...

Другого способа пока не придумал... ;)

А какая необходимость, два байта в памяти не помещаются ? ;)

0

6

Nord написал(а):

...А какая необходимость, два байта в памяти не помещаются ?


Кнопок меньше 100, проще сделать событие по нажатию при сравнении 1 байта, чем сравнивать два байта, вот и хочется чтоб из прерывания вылетел 1 байт, тогда можно и буфер по проще нажатых кнопок сделать  :rolleyes: .

0

7

Развиваю свою идею (согласно приведенной схеме): ;)

Каждый адрес определяем побитно. Не весовые значения битов, а их место в байте.
В этом случае имеем два "полубайта" со значениями от 1 до 8.

В дальнейшем по этим значениям можно однозначно определить, какая из кнопок была нажата.

Пример:
Нажата верхняя ("0") кнопка в последней ("6") колонке.
Получаем: 1000 - адрес строки, 1110 - адрес колонки.
Полученный байт - 10001110.

Нажата кнопка в строке "2" в "4" колонке.
Получаем: 1100 - адрес строки, 1010 - адрес колонки.
Полученный байт - 11001010.

Отредактировано Nord (2018-01-18 16:31:13)

0

8

Ev3658 написал(а):

http://se.uploads.ru/t/hNqfD.jpg

Если бы ты изобрел способ запихать два байта в 1 (без жатия) - ты бы перевернул мир! :D
Вообще все клавы/матрицы сканируются скан кодами. Тут схема очень странная, скорость сканирования от таймера должна быть не меньше 25-50Гц (без учета всяких там плавного свечения, типа шим), чтобы не мерцали диоды (или что там у тебя). Но подозреваю, чтобы получить нормальную скорость обработки клавы, может быстрее понадобится.
Т.к. у тебя используется практически целый байт на выходе после сканирования (минус 1 бит), то ты ничего нового не изобретешь. Хочешь ты этого или нет, а алгоритм таков:

- таймер крутит единицу (бит) по кругу до 8 раз;
- как только срабатывает прерывание, ты должен успеть остановить таймер (если нудна только 1 кнопка) или прочитать информацию с него + заглянуть в порт от которого произошло прерывание (прочитать бит(ы) - это если сканить любое количество нажатых кнопок, которое будит идти вообще потоком. Т.е. как не крути - два байта!!! Такая же технология в клавах ПС.
Прерывание должно срабатывать при наличии еденицы на порте (всегда).
Вообще если честно, прерывание тут с избытком, оно нафиг ненужно. Просто сканируй себе клаву по таймеру и всё.
И не забыть подтянуть входы порта к минусу (пулдаун).

зы: алгоритм может быть и от обратного (инверсия).

0

9

Останавливать таймер не требуется, прерывание сработает быстро и порт не успеет сменить адрес, дело в том, что контроллер не работает на прямую с битом и использует несколько тактов, то-есть считывает байт из порта, меняет бит и записывает его обратно.
Для ускорения этого процесса в Xmega есть виртуальные порты, но пока это тёмный лес.
Вот что будет если два байта перегнать через OR:
B1 OR B2 =

Код:
1 & 1 = 1
2 & 2 = 2
1 & 2 = 3
2 & 1 = 3
4 & 4 = 4
1 & 4 = 5
4 & 1 = 5
2 & 4 = 6
4 & 2 = 6
8 & 8 = 8
1 & 8 = 9
8 & 1 = 9
2 & 8 = 10
8 & 2 = 10
4 & 8 = 12
8 & 4 = 12
16 & 16 = 16
1 & 16 = 17
16 & 1 = 17
2 & 16 = 18
16 & 2 = 18
4 & 16 = 20
16 & 4 = 20
8 & 16 = 24
16 & 8 = 24
32 & 32 = 32
1 & 32 = 33
32 & 1 = 33
2 & 32 = 34
32 & 2 = 34
4 & 32 = 36
32 & 4 = 36
8 & 32 = 40
32 & 8 = 40
16 & 32 = 48
32 & 16 = 48
64 & 64 = 64
1 & 64 = 65
64 & 1 = 65
2 & 64 = 66
64 & 2 = 66
4 & 64 = 68
64 & 4 = 68
8 & 64 = 72
64 & 8 = 72
16 & 64 = 80
64 & 16 = 80
32 & 64 = 96
64 & 32 = 96
128 & 128 = 128
1 & 128 = 129
128 & 1 = 129
2 & 128 = 130
128 & 2 = 130
4 & 128 = 132
128 & 4 = 132
8 & 128 = 136
128 & 8 = 136
16 & 128 = 144
128 & 16 = 144
32 & 128 = 160
128 & 32 = 160
64 & 128 = 192
128 & 64 = 192


PureBasic
Код:
p.a=0
o.a=0
b1.a=0
b2.a=0
l.a=0
f.c
Dim m.a(100)
Dim b11.a(100)
Dim b22.a(100)
For p=1 To 8 
  For o=1 To 8
    f=f+1
    Select p
      Case 1: b1=1
      Case 2: b1=2
      Case 3: b1=4
      Case 4: b1=8
      Case 5: b1=16
      Case 6: b1=32
      Case 7: b1=64
      Case 8: b1=128
    EndSelect
    
    Select o
      Case 1: b2=1
      Case 2: b2=2
      Case 3: b2=4
      Case 4: b2=8
      Case 5: b2=16
      Case 6: b2=32
      Case 7: b2=64
      Case 8: b2=128
    EndSelect
    l=b1 | b2
    m(f)=l
    b11(f)=b1
    b22(f)=b2
    
  Next o
Next p
For p=0 To 255
  For l=1 To 64
    If m(l)=p
      Debug Str(b11(l))+" & "+Str(b22(l))+" = "+Str(m(l))
    EndIf
  Next l
Next p

Чего-то мозг отдыхает, всё никак не включится.

0

10

:tomato:
Вот, получилось, правда как-то странно, но работает, примерно вот так вот:

Код_кнопки = Порт_1 OR Порт_2
If Порт1 < Порт2 Then    Код_кнопки=254-Код_Кнопки

В итоге получается вот так:

Листинг истинности
Код:
1 & 1 = 1
2 & 2 = 2
2 & 1 = 3
4 & 4 = 4
4 & 1 = 5
4 & 2 = 6
8 & 8 = 8
8 & 1 = 9
8 & 2 = 10
8 & 4 = 12
16 & 16 = 16
16 & 1 = 17
16 & 2 = 18
16 & 4 = 20
16 & 8 = 24
32 & 32 = 32
32 & 1 = 33
32 & 2 = 34
32 & 4 = 36
32 & 8 = 40
32 & 16 = 48
64 & 128 = 62
64 & 64 = 64
64 & 1 = 65
64 & 2 = 66
64 & 4 = 68
64 & 8 = 72
64 & 16 = 80
32 & 128 = 94
64 & 32 = 96
16 & 128 = 110
8 & 128 = 118
4 & 128 = 122
2 & 128 = 124
1 & 128 = 125
128 & 128 = 128
128 & 1 = 129
128 & 2 = 130
128 & 4 = 132
128 & 8 = 136
128 & 16 = 144
32 & 64 = 158
128 & 32 = 160
16 & 64 = 174
8 & 64 = 182
4 & 64 = 186
2 & 64 = 188
1 & 64 = 189
128 & 64 = 192
16 & 32 = 206
8 & 32 = 214
4 & 32 = 218
2 & 32 = 220
1 & 32 = 221
8 & 16 = 230
4 & 16 = 234
2 & 16 = 236
1 & 16 = 237
4 & 8 = 242
2 & 8 = 244
1 & 8 = 245
2 & 4 = 248
1 & 4 = 249
1 & 2 = 251
Код:
     Knl = Pinkn                                           
     Knh = Portkn                                          
     Kn = Knl Or Knh
     If Knl < Knh Then Kn = 254 - Kn
RDW написал(а):

Если бы ты изобрел способ запихать два байта в 1 (без жатия) - ты бы перевернул мир!

:rolleyes:

Отредактировано Ev3658 (2018-01-19 09:43:10)

0

11

Напиши алгоритм и назови переменные более ПРАВИЛЬНЫМ Русском языком или английским и я напишу твои обработчики прерываний на чистом ассемблере....   Попытался написать, да в переменных запутался, точнее в названиях.  Терпеть ненавижу "голых" переменных  :D
Например Key_scan_counter и всё понятно а у тебя Portkn хрен знат чо это такое  :O

0

12

Я с орами, ксорами и эндами познакомился ещё на спектруме (z80), когда графику месили, визуально проще запомнить, что и как в итоге работает.
8 х 7 = 56 - это без комбинации кнопок, следовательно тут лучше обойтись тетрадами и просто их сложить. Так же считать номер бита, по факту ведь у тебя счет 1 до 8 бит в обоих портах, вот и строй комбинацию из них.

На компе это выглядит так:

Код:
    Dim C As Byte
    Dim X As Byte
    Dim Y As Byte
    C = 1
    For X = 1 To 8
        For Y = 1 To 8
            Text1.Text = Text1.Text & Format(C, "00") & " - X=" & X & " Y=" & Y & " > " & (X + (Y * 15)) & vbCrLf
            C = C + 1
        Next Y
    Next X


Умножить на 15 - это эмуляция высшей тетрады, ибо VB не знает о ней.
Результат такой:

01 - X=1 Y=1 > 16
02 - X=1 Y=2 > 31
03 - X=1 Y=3 > 46
04 - X=1 Y=4 > 61
05 - X=1 Y=5 > 76
06 - X=1 Y=6 > 91
07 - X=1 Y=7 > 106
08 - X=1 Y=8 > 121
09 - X=2 Y=1 > 17
10 - X=2 Y=2 > 32
11 - X=2 Y=3 > 47
12 - X=2 Y=4 > 62
13 - X=2 Y=5 > 77
14 - X=2 Y=6 > 92
15 - X=2 Y=7 > 107
16 - X=2 Y=8 > 122
17 - X=3 Y=1 > 18
18 - X=3 Y=2 > 33
19 - X=3 Y=3 > 48
20 - X=3 Y=4 > 63
21 - X=3 Y=5 > 78
22 - X=3 Y=6 > 93
23 - X=3 Y=7 > 108
24 - X=3 Y=8 > 123
25 - X=4 Y=1 > 19
26 - X=4 Y=2 > 34
27 - X=4 Y=3 > 49
28 - X=4 Y=4 > 64
29 - X=4 Y=5 > 79
30 - X=4 Y=6 > 94
31 - X=4 Y=7 > 109
32 - X=4 Y=8 > 124
33 - X=5 Y=1 > 20
34 - X=5 Y=2 > 35
35 - X=5 Y=3 > 50
36 - X=5 Y=4 > 65
37 - X=5 Y=5 > 80
38 - X=5 Y=6 > 95
39 - X=5 Y=7 > 110
40 - X=5 Y=8 > 125
41 - X=6 Y=1 > 21
42 - X=6 Y=2 > 36
43 - X=6 Y=3 > 51
44 - X=6 Y=4 > 66
45 - X=6 Y=5 > 81
46 - X=6 Y=6 > 96
47 - X=6 Y=7 > 111
48 - X=6 Y=8 > 126
49 - X=7 Y=1 > 22
50 - X=7 Y=2 > 37
51 - X=7 Y=3 > 52
52 - X=7 Y=4 > 67
53 - X=7 Y=5 > 82
54 - X=7 Y=6 > 97
55 - X=7 Y=7 > 112
56 - X=7 Y=8 > 127
57 - X=8 Y=1 > 23
58 - X=8 Y=2 > 38
59 - X=8 Y=3 > 53
60 - X=8 Y=4 > 68
61 - X=8 Y=5 > 83
62 - X=8 Y=6 > 98
63 - X=8 Y=7 > 113
64 - X=8 Y=8 > 128

В баскоме это будет выглядеть что-то на подобии:

Код:
A = PinKN
B = 0
For F = 1 to 8
    If A.0 = 1 Then
        B = F
        Exit For
    End If
    Rotate A, Right
Next F
Rotate B, Right, 4
A = PortKN
C = 0
For F = 1 to 8
    If A.0 = 1 Then
        C = F
        Exit For
    End If
    Rotate A, Right
Next F
Scancode = C And B

Ну далее можно ещё про оптимизировать.

0

13

RDW написал(а):

Я с орами, ксорами и эндами познакомился ещё на спектруме (z80), когда графику месили

Интересно, какое же у тебя "погоняло" на Z80 было???

0

14

http://se.uploads.ru/t/hNqfD.jpg

-NMi- написал(а):

Напиши алгоритм и назови переменные более ПРАВИЛЬНЫМ Русском языком или английским....

Получается вот так:
Key_scan_counter=PortA AND PortB
If PortA<PortB Then Key_scan_counter=254-Key_scan_counter

RDW написал(а):

Умножить на 15 - это эмуляция высшей тетрады, ибо VB не знает о ней.

Не, не получается, дело в том, что только 1 бит может быть включенный в байте, то-есть 1 байт может быть равен: 1,2,4,8,16,32,64,128, а не 1,2,3,4,5,6,7,8
То-есть если так:
Key_scan_counter=PortB*15
Key_scan_counter=PortA AND +Key_scan_counter
То получается:

Свернутый текст

Где <======= - это метка совпадения

Код:
1 & 1*15 = 15<=======
2 & 1*15 = 15<=======
4 & 1*15 = 15<=======
8 & 1*15 = 15<=======
2 & 2*15 = 30<=======
4 & 2*15 = 30<=======
8 & 2*15 = 30<=======
16 & 2*15 = 30<=======
1 & 2*15 = 31<=======
16 & 1*15 = 31<=======
32 & 1*15 = 47
4 & 4*15 = 60<=======
8 & 4*15 = 60<=======
16 & 4*15 = 60<=======
32 & 4*15 = 60<=======
1 & 4*15 = 61
2 & 4*15 = 62<=======
32 & 2*15 = 62<=======
64 & 1*15 = 79
64 & 2*15 = 94
8 & 8*15 = 120<=======
16 & 8*15 = 120<=======
32 & 8*15 = 120<=======
64 & 8*15 = 120<=======
1 & 8*15 = 121
2 & 8*15 = 122
4 & 8*15 = 124<=======
64 & 4*15 = 124<=======
128 & 128*15 = 128
1 & 128*15 = 129
2 & 128*15 = 130
4 & 128*15 = 132
8 & 128*15 = 136
128 & 1*15 = 143
16 & 128*15 = 144
128 & 2*15 = 158
32 & 128*15 = 160
128 & 4*15 = 188
64 & 64*15 = 192<=======
64 & 128*15 = 192<=======
128 & 64*15 = 192<=======
1 & 64*15 = 193
2 & 64*15 = 194
4 & 64*15 = 196
8 & 64*15 = 200
16 & 64*15 = 208
32 & 32*15 = 224<=======
32 & 64*15 = 224<=======
64 & 32*15 = 224<=======
128 & 32*15 = 224<=======
1 & 32*15 = 225
2 & 32*15 = 226
4 & 32*15 = 228
8 & 32*15 = 232
16 & 16*15 = 240<=======
16 & 32*15 = 240<=======
32 & 16*15 = 240<=======
64 & 16*15 = 240<=======
128 & 16*15 = 240<=======
1 & 16*15 = 241
2 & 16*15 = 242
4 & 16*15 = 244
8 & 16*15 = 248<=======
128 & 8*15 = 248<=======


Отредактировано Ev3658 (2018-01-19 14:50:33)

0

15

Погодь....
Вращаем один БИТ в порту Х непрерывно, так я понял?
По истечении 8 итераций что делаем?

Смотрим в порту Y нажата ли клавиша и определяем её, так чтоли?
Как раскодировать код клавиши? 7 бит а старший бит куда???
Ничо нипонял...  o.O

0

16

-NMi- написал(а):

Погодь....
Вращаем один БИТ в порту Х непрерывно, так я понял?
По истечении 8 итераций что делаем?

Смотрим в порту Y нажата ли клавиша и определяем её, так чтоли?
Как раскодировать код клавиши? 7 бит а старший бит куда???
Ничо нипонял...


Вращаем один бит по кругу бесконечно.
Прерывание INT срабатывает по прерыванию если вдруг появилась единица по входу (нажата кнопка) и тут мы получаем байт вращения и байт входа, чтоб в дальнейшем в программе не писать условия нажатия кнопки по 2м байтам, их как-то надо сложить в один байт.

Выше в коде реализована ещё подсветка на диодах, у меня один бит во входном порту остался свободным, грех было им не воспользоваться.

Вся проблема в том, что нужно максимально короткий алгоритм сложения двух полученных байт при срабатывании кнопки, получить индивидуальный 8 битный индентификатор  :confused:

Двойное нажатие на кнопку не планируется, по этому байт выхода перебора и байт входа сигнала будут равны в случае срабатывания прерывания: 1,2,4,8,16,32,64,128

0

17

Ev3658 написал(а):

Не, не получается, дело в том, что только 1 бит может быть включенный в байте, то-есть 1 байт может быть равен: 1,2,4,8,16,32,64,128, а не 1,2,3,4,5,6,7,8

Я тебе как раз об этом и толкую, с твоим алгоритмом ничего нормально работать не будет, т.к. всегда будет комбинация повторения и следовательно логическими операциями тут не поможешь.
Например вот здесь у тебя уже ошибка:

Код:
Key_scan_counter=PortA AND PortB

У тебя не будет никакого различия, если бит будет выставлен с любой стороны, т.е. бит 0 с стороны кнопок или скана, всегда будет 0. Так же нет различия когда биты будут присутствовать с обеих сторон, всегда будет 1! Казалось бы это и хорошо, но посмотри таблицу истинности AND (как он работает). У тебя там будут значения только 1,2,4,8,16,32,64,128 при наличии нажатия уникальной кнопки (одна из восьми проводов).
Тебе нужно посчитать/перевести как раз 1,2,4,8,16,32,64,128 в 1,2,3,4,5,6,7,8. Я в коде баскома это описал.

-NMi- написал(а):

какое же у тебя "погоняло" на Z80 было

Тогда их не было и не могло быть, ведь погоняло в классическом компьютерном мире присутствовало только при наличии инета (некой общественной составляющей). :)

0

18

RDW написал(а):

Тогда их не было и не могло быть

Да ты гонишь  :D
Вспомни: De Bill Gilbert, CodeBusters, THD и тд. Как-же, тысячи строк на голом ассемблере....... :writing:

0

19

$regfile = "m128def.dat"
$crystal = 1000000
$hwstack = 40
$swstack = 16
$framesize = 32

Dim Portkn As Byte
Dim Port_keyboard_scan As Byte

$asm
'knopkatim
Timer0_overflov:
                 push r16
                 in r16,sreg
                 push r16
                 lds r16,{Port_keyboard_scan}
                 lsl r16
                 brcc timer0_ovf10
                 ldi r16,01

Timer0_ovf10:
                 Sts {port_keyboard_scan} , R16
                 Out Portb , R16
                 pop r16
                 Out Sreg , R16
                 pop r16
                 reti

$end Asm

0

20

RDW написал(а):

Например вот здесь у тебя уже ошибка:

Код:

Код:
Key_scan_counter=PortA AND PortB

У тебя не будет никакого различия, если бит будет выставлен

Так я же условие добавляю:

Код:
If PortA<PortB Then Key_scan_counter=254-Key_scan_counter

И оно как раз всё исправляет, все коды клавиш разные.
Вот:

Код:
Key_scan_counter=PortA AND PortB
If PortA<PortB Then Key_scan_counter=254-Key_scan_counter
-NMi- написал(а):
Свернутый текст

$regfile = "m128def.dat"
$crystal = 1000000
$hwstack = 40
$swstack = 16
$framesize = 32

Dim Portkn As Byte
Dim Port_keyboard_scan As Byte

$asm
'knopkatim
Timer0_overflov:
                 push r16
                 in r16,sreg
                 push r16
                 lds r16,{Port_keyboard_scan}
                 lsl r16
                 brcc timer0_ovf10
                 ldi r16,01

Timer0_ovf10:
                 Sts {port_keyboard_scan} , R16
                 Out Portb , R16
                 pop r16
                 Out Sreg , R16
                 pop r16
                 reti

$end Asm

Спасибо, попробую, у меня тут ещё перебор для подсветки светодиодов есть, он усложняет всё.

0

21

-NMi- написал(а):

De Bill Gilbert, CodeBusters, THD и тд.

не помню, мы тогда сами игры ломали и пытались писать.

-NMi- написал(а):

Как-же, тысячи строк на голом ассемблере

Ну я в своё время изобрел более качественный алгоритм звукозаписи с однобитного входа, но к сожалению, в СССР это направление довольно быстро начало умирать с появлением х86. Вообще в Россию Спектрум не так уж на долго залетел, да и когда он был, была большущая проблема с магнитафонами, а про всякие там флопи диски и принтеры - молчу.

0

22

Это только вращение бита в порту и всё!!!
Я чесслово нихрена ничо нипонял, что тебе нужно...
Прадлагаю внести счётчик итераций от 0 до 7.
Предлагаю внести счётчик клавиш от 0 до 6.
Впоследствии умножить итерации на клавиши и будет КОД клавиши размером в ОДИН БАЙТ.
Проще не придумаешь.
Если нужно - напишу обработчики.

0

23

-NMi- написал(а):

Я чесслово нихрена ничо нипонял, что тебе нужно

Он пока сам не понимает, что есть такое слово как "уникальность". Каждый байт должен крутиться в своей области (никакие там условия непрокатят). Ещё непонятно зачем использовать прерывание, которое ему и вносит доп мешанину для отрисовки светодиодов.
В общем сам всё усложнил.

0

24

Ev3658 написал(а):

Как можно максимально быстро по двум байтам сделать число в 1 байт?

Числа в каждом из байтов будут в диапазоне 0-7.
Первый байт нужно сдвинуть на 3 бита влево и произвести побитовое ИЛИ со вторым байтом.

Код:
For b1 = 0 To 7
  For b2 = 0 To 7
    Debug (b1<<3) | b2
  Next b2
Next b1

0

25

Пётр написал(а):

Числа в каждом из байтов будут в диапазоне 0-7.
Первый байт нужно сдвинуть на 3 бита влево и произвести побитовое ИЛИ со вторым байтом.

Не будут (
У меня есть 1 порт по которому бегает 1 бит, то-есть ну никак он не может быть равен 3 или 5, только значения 1,2,4,8,16,32,64,128
Тут же под перебор засвечивается нужный светодиод. Для светодиода отведён 1 байт (Led), бит в котором равен свечению 1 светодиода. (тут ещё нужна оптимизация)

Это работает по таймеру:
Код:
Rotate Portkn , Left                                       'Сдвигаем бит порта на 1 бит в сторону
 Ledkn = Led.ledtm                                          'Включаем светодиод
 If Ledtm < 7 Then                                          'Перебираем биты в переменной LED для включения нужного светодиода
   Incr Ledtm
   Else
     Ledtm = 0
 End If

Чтоб программа жила сама по себе и отрабатывала нажатые кнопки, к примеру для набора текста, тут нужно создать буфер нажатых кнопок.
Запоминать два байта в буфер как-то потому сложно будет обрабатывать, по этому нужен простой алгоритм объединения 2ъ байтов в один.
Пока самый простой через OR и 1 условие, то-есть так:

Код:
Knh = Portkn                                                'Запоминаем  порт перебора
Knl = Pinkn                                            'Запоминаем порт входа
If Kn = 0 Then
        Kn = Knl Or Knh                                     'Складываем значения
        If Knl < Knh Then Kn = 254 - Kn                     'Если порт входа меньше порта перебора, топодходим с другого конца ))))
End If


Теперь есть байт, выше указывал таблицу истинности, вот:

Таблица истинности B = B1 OR B2: IF B1<B2 Then B=254-B
Код:
1 & 1 = 1
2 & 2 = 2
2 & 1 = 3
4 & 4 = 4
4 & 1 = 5
4 & 2 = 6
8 & 8 = 8
8 & 1 = 9
8 & 2 = 10
8 & 4 = 12
16 & 16 = 16
16 & 1 = 17
16 & 2 = 18
16 & 4 = 20
16 & 8 = 24
32 & 32 = 32
32 & 1 = 33
32 & 2 = 34
32 & 4 = 36
32 & 8 = 40
32 & 16 = 48
64 & 128 = 62
64 & 64 = 64
64 & 1 = 65
64 & 2 = 66
64 & 4 = 68
64 & 8 = 72
64 & 16 = 80
32 & 128 = 94
64 & 32 = 96
16 & 128 = 110
8 & 128 = 118
4 & 128 = 122
2 & 128 = 124
1 & 128 = 125
128 & 128 = 128
128 & 1 = 129
128 & 2 = 130
128 & 4 = 132
128 & 8 = 136
128 & 16 = 144
32 & 64 = 158
128 & 32 = 160
16 & 64 = 174
8 & 64 = 182
4 & 64 = 186
2 & 64 = 188
1 & 64 = 189
128 & 64 = 192
16 & 32 = 206
8 & 32 = 214
4 & 32 = 218
2 & 32 = 220
1 & 32 = 221
8 & 16 = 230
4 & 16 = 234
2 & 16 = 236
1 & 16 = 237
4 & 8 = 242
2 & 8 = 244
1 & 8 = 245
2 & 4 = 248
1 & 4 = 249
1 & 2 = 251


0

26

В #7 я уже предлагал использовать номер бита для формирования адреса...  :angry:

ИМХО, к тому и пришли... ;)

0

27

Дык а там по другому никак. Делаем счётчик на 8 итераций и с ним же вращаем бит.
Кнопки сами по себе пронумерованы битами.
Определяем выставленный бит, например 5-й и присваиваем ему уже байт=05.
Далее умножаем на счётчик, например 4. 4Х5=20 - код клавиши.
Всё!

0

28

-NMi- написал(а):

....Определяем выставленный бит, например 5-й и присваиваем ему уже байт=05.
Далее умножаем на счётчик, например 4. 4Х5=20 - код клавиши.
Всё!


Чтоб определить бит №5 в байте - уже алгоритм сложный.

Пока самый простой:
Knopka=Byte1 AND Byte2   
IF Byte1 < Byte2 Then Knopka=254 - Knopka

В итоге код кнопки никогда не повторится во всех вариантах этих байтов матрицы: 1,2,4,8,16,32,64,128
Вот варианты по этому алгоритму:

Свернутый текст

1 & 1 = 1
2 & 2 = 2
2 & 1 = 3
4 & 4 = 4
4 & 1 = 5
4 & 2 = 6
8 & 8 = 8
8 & 1 = 9
8 & 2 = 10
8 & 4 = 12
16 & 16 = 16
16 & 1 = 17
16 & 2 = 18
16 & 4 = 20
16 & 8 = 24
32 & 32 = 32
32 & 1 = 33
32 & 2 = 34
32 & 4 = 36
32 & 8 = 40
32 & 16 = 48
64 & 128 = 62
64 & 64 = 64
64 & 1 = 65
64 & 2 = 66
64 & 4 = 68
64 & 8 = 72
64 & 16 = 80
32 & 128 = 94
64 & 32 = 96
16 & 128 = 110
8 & 128 = 118
4 & 128 = 122
2 & 128 = 124
1 & 128 = 125
128 & 128 = 128
128 & 1 = 129
128 & 2 = 130
128 & 4 = 132
128 & 8 = 136
128 & 16 = 144
32 & 64 = 158
128 & 32 = 160
16 & 64 = 174
8 & 64 = 182
4 & 64 = 186
2 & 64 = 188
1 & 64 = 189
128 & 64 = 192
16 & 32 = 206
8 & 32 = 214
4 & 32 = 218
2 & 32 = 220
1 & 32 = 221
8 & 16 = 230
4 & 16 = 234
2 & 16 = 236
1 & 16 = 237
4 & 8 = 242
2 & 8 = 244
1 & 8 = 245
2 & 4 = 248
1 & 4 = 249
1 & 2 = 251

Отредактировано Ev3658 (2018-01-26 16:25:27)

0

29

Ev3658 написал(а):

Чтоб определить бит №5 в байте - уже алгоритм сложный.

Немного длиннее и, если время критично, то писать в Ass... ;)

Крутануть два цикла, один внутри другого.
Переменные циклов - идентификаторы номера бита.
В теле цикла проверяем состояние бита, по условию запоминаем этот номер.

В результате получаем два номера.
номер1
номер2
Далее:
номер1 = 255 - номер1                        - сдвигаем на 4 разряда вверх
                                                             можно Rotate, как удобнее
номер1 + номер2 = <результат>

Получаем 1 байт, "половинки" которого однозначно указывают адрес кнопки.

Отредактировано Nord (2018-01-26 18:44:10)

0

30

Ну, если бы тетрадами делал, то бы смело можно было строить клаву матрицей 15 х 15 = 225 кнопок.

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Алгоритм кнопочной клавиатуры с динамичной индикацией.