инициализация клавиатуры 4на4 _асемблер

Здесь принимаются все самые невообразимые вопросы... Главное - не стесняйтесь. Поверьте, у нас поначалу вопросы были еще глупее :)
Ответить
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

Да так я и хотел,чтоб сканировать всю клаву,одержать код нажатой кнопки и передать по uart только ее код
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Тогда примерно так... Только кварц нужно взять поудобнее (например 11.059200 MHz), иначе будут ошибки передачи.

Код: Выделить всё

$mod51

	MOV	SP,#30h	
	CALL	UART_init 	;конфигурация UART
main:			;основной цикл
	CALL	Read_Key	;сканирование клавиатуры
	JMP	main
;----------------------------------------------------------------------------
; Procedures
;----------------------------------------------------------------------------
Read_Key:
	mov A,#07Fh	;загружаем ноль для первого столбца
scan_klava:
	mov P1,A	;выводим ноль
	RR A		;двигаем
	mov R1,A	;сохраняем текущий "ноль"
	mov A,p1	;читаем порт
	CPL A	;инвертируем
	MOV R0,A	;сохраняем значение порта
	ANL A,#0Fh	;выделяем строки
	JNZ KEY_OUT	;проверяем кнопки. переход, если нажата хоть одна в столбце
	mov A,R1	;загружаем "ноль"
	jb ACC.3,scan_klava ;если "ноль" не 4-й, повторяем для следующего столбца
	ret		;выход
KEY_OUT:
	MOV A,R0	;загружаем код кнопки в А (старшие биты - столбец, младшие - строка)
	CALL UART_Write	;вывод
	CALL Delay	;*антидребезг*
	CALL Delay	;одной мало, ковырять не стал, просто добавил еще задержку
	RET

Delay: ; Підпрограма затримки
mov r3,#0ffh
d_m2: mov r2,#0ffh
d_m1:
djnz r2,d_m1
djnz r3,d_m2
ret

UART_init:
mov SCON,#01010000b ; конфігурація послідовного порта
mov PCON,#00h ; конфігурація потужності
mov TMOD,#20h ; режим роботи таймера
mov TH1, #253 ; для швидкості 9600 бод !!!!F=11.059200 MHz!!!
mov A, SBUF ; онулюєм буфер
setb TR1 ; запуск таймера
ret

;----------------------------------------------------------------------------
Uart_Read:
jnb RI, $ ; очікуєм закінчення передачі щоб почати читання
mov A, SBUF ; пересилання байта в SBUF
clr RI ; очищення біта RI
ret

;----------------------------------------------------------------------------
Uart_Write:
mov SBUF, A ; зчитування байта в ACC
jnb TI, $ ; очікування на прийом
clr TI ; очистка TІ

ret
;-------------- Кінець програми ---------------
end
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

Спасибо Engineer_Keen .... все работает ))... Это как раз то, что мне было нужно.
Но есть одна неточность: я перепробовал все клавиши и получил через UART такой результат, как на прикрепленном рисунке. А должно бы быть такое: 1,2,3,4,5,6,7,8,9, A, B, C, D, E, F. Как такое получить?
и шо значит SP в строке: MOV SP, # 30h - загрузить константу 30h в SP, просто это не описано. А вообще очень большое спасибо, я целую неделю уже мучился над курсаком, а написал лишь то, что нашел в книге, которую мне советовали выше, и то немного не то что надо было.
Вложения
5555555555.jpg
(141.48 КБ) 360 скачиваний
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

ascentman писал(а):Но есть одна неточность: я перепробовал все клавиши и получил через UART такой результат, как на прикрепленном рисунке. А должно бы быть такое: 1,2,3,4,5,6,7,8,9, A, B, C, D, E, F. Как такое получить?
Во-первых, то что у вас на рисунке - не совсем верно, должно быть (слева-направо,сверху-вниз): 11,21,31...43,44, видимо с частотой кварца косяк. Я об этом гворил.
Во-вторых, чтобы получить последовательность 1,2...E,F - нужны дополнительные преобразования. Алгоритм примерно таков:

Код: Выделить всё

1 Взять младшие биты
2 Вычислить степень 2-ки (0001->1, 0010->2, 0100->3, 1000->4)
3 Умножить на 16
4 Взять старшие биты
5 см. п2
6 Сложить с п.3
7 PROFIT!!!111
В ассемблер переводить влом...
ascentman писал(а):и шо значит SP в строке: MOV SP, # 30h
Ай-яй, даташит все-таки не читали на контроллер. SP - указатель стека, я же говорил что его нужно инициализировать!
Реклама
Эиком - электронные компоненты и радиодетали
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

та-та .... я просто забыл на мк изменить частоту: там 12 стояло .... поставил 11.059200 и начало выводить такие же числа, как и вы написали))
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

Engineer_Keen писал(а):

Код: Выделить всё

1 Взять младшие биты
2 Вычислить степень 2-ки (0001->1, 0010->2, 0100->3, 1000->4)
3 Умножить на 16
4 Взять старшие биты
5 см. п2
6 Сложить с п.3
7 PROFIT!!!111
пытался сделать алгоритм, но не до конца понимаю:
mov A,R0
anl A,#00001111b ; п.1
Вычислить степень 2-ки? ; п.2
mov B,#FFh ; 3
mul AB
xch B,A
anl A,#11110000b ;4
Вычислить степень 2-ки?
orl A,B

call UART_write
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

ascentman писал(а): mov A,R0
anl A,#00001111b ; п.1
Верно
ascentman писал(а): Вычислить степень 2-ки? ; п.2
Нужно преобразовать полученный код 0001-0010-0100-1000 в номер строки 0-1-2-3
Если сдвинуть код вправо, получится 0000-0001-0010-0100, 3 первых кода уже подходят, 4й нужно заменить на число 3
ascentman писал(а): mov B,#FFh ; 3
mul AB
Никогда не используйте операции DIV и MUL, если в качестве второго оператора степень двойки. Эти операции быстрее делаются сдвигами вправо-влево. Кстати с 16 я погорячился, умножать надо на 4, ведь у нас всего 4 столбца/строки.
ascentman писал(а): anl A,#11110000b ;4
Вычислить степень 2-ки?
если поменять старшие и младшие биты (SWAP A), то можно использовать ту же процедуру для преобразования кода в номер
ascentman писал(а): orl A,B
call UART_write
Если нумерация должна быть с единицы, то ее нужно добавить (ADD A,#1), так как нумерация строк/столбцов начинается с 0, и код первой кнопки будет 0*4+0=0
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

Шо то мне не получаетсЯ так сделать: либо виводит ff 0f и тд либо ничего :cry: намагался еще сделать подругому:виводить в ансі коде, используя movc a,@а+pc но тож ничего хорошого не одержал((...need help
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

Поскольку не нужно отслеживать комбинацию нажатых одновременно клавиш, можно сделать проще. Перед выводом делайте переопределение: если к выводу идет 11, то выводите 0, если к выводу идет 21, то выводите 1 и т.д.
Docendo discimus
Контактная информация:
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

А Как ето переоприделить? В акамуляторе при виводе 11 есть 00010001. Переопределить XOR I jnb і потом загрузить mov a новое значение 1?
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

1. В аккуме 11?
2. Если нет, уходим на 5.
3. заносим в аккум 0
4. уходим на вывод по кому.
5. В аккуме 21?
и т.д.
Docendo discimus
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Код: Выделить всё

	MOV	A,R0	;загружаем код кнопки в А
	SWAP	A	;берем страшие биты (код строки)
	ANL	A,#0Fh	;выделаем их маской
	RRC	A	;сдвигаем вправо (тогда код 0001 соответствует номеру 0, 0010 - 1,0100 - 2, а 1000 - 3)
	CJNE	A,#4,X1	;проверяем что код не равен 1000 (остальные 3 значения после RRC подходят и так)
	MOV	A,#3	;если код равен 0100, загружаем номер "3"
X1:	MOV	B,A	;временно сохраняем в B 2х битное значение номера строки
	CLR	C	;очистка флага переноса
	MOV	A,R0	;загружаем код кнопки в А
	ANL	A,#0Fh	;берем младшие биты (код столбца)
	RRC	A	;делаем аналогичные операции
	CJNE	A,#4,X2	;...
	MOV	A,#3	;...
X2:	CLR	C	;...
	RL	A	;умножаем на 4
	RL	A	;никаких MUL или DIV, когда в качестве делителя/множителя - степень 2!!!
	ORL	A,B	;складываем номер столбца с номером строки
	ADD	A,#1	;прибавляем 1, если нумерация должна быть с 1
	CALL UART_Write	;вывод
А проверять каждый из 16 кодов и преобразовывать длинно получается, и время выполнения кода сильно зависит от входного параметра, хотя можно и так. Еще короче сделать - с использованием таблицы, правда тоже время выполнения будет от кода кнопки зависеть.
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

В 4ой строке отображается неверно(
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

А можно сделать вивод в ансі коде?а не в 16....препод захотел чтоб в масиве задать ansii код и по индексу обращаться?
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Не знаю... У меня все точно отображается...
ascentman писал(а):А можно сделать вивод в ансі коде?а не в 16....препод захотел чтоб в масиве задать ansii код и по индексу обращаться?
Можно все! Нужно всего-то 3 строчки добавить, из которых одна - список кодов.
Вложения
scan1.PNG
(21.33 КБ) 329 скачиваний
Последний раз редактировалось Engineer_Keen Ср июн 01, 2011 15:20:07, всего редактировалось 1 раз.
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 27
Зарегистрирован: Вс май 29, 2011 16:04:41

Сообщение ascentman »

Вав роботает ..... Еще раз спасибо)
Ответить

Вернуться в «Теория»