Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты данной рассылки

Boriss
Статус: Академик
Рейтинг: 2634
∙ повысить рейтинг »
Абаянцев Юрий Леонидович aka Ayl
Статус: Профессионал
Рейтинг: 2300
∙ повысить рейтинг »
Жерар
Статус: Специалист
Рейтинг: 1844
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / Assembler (Ассемблер)

Номер выпуска:1443
Дата выхода:07.05.2011, 19:30
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:213 / 64
Вопросов / ответов:1 / 1

Вопрос № 183006: Здравствуйте! У меня возникли сложности с таким вопросом: К ОМК 8051 подключены клавиатура 3х4, ЖК-индикатор HD-44780, двигатель постоянного тока. В исходном состоянии на ЖКИ выведено: |_|_|_|_|о|б|/|м| - в пустых отображается скорость работы ...



Вопрос № 183006:

Здравствуйте! У меня возникли сложности с таким вопросом:
К ОМК 8051 подключены клавиатура 3х4, ЖК-индикатор HD-44780, двигатель постоянного тока.
В исходном состоянии на ЖКИ выведено: |_|_|_|_|о|б|/|м| - в пустых отображается скорость работы двигателя в об/м.
Организовать ШИМ модулятор с частотой 8кГц, скважность примерно 1/25. На клавиатуре 10 цифр от 0 до 9.
Пользователь вводит данные - скорость работы двигателя, который отображается на ЖКИ, в соответствии с этими данными происходит изменение скважности в ШИМе и изменяется скорость работы двигателя.
Желательно продемонстрировать работу в САПР Proteus или Pinnacle 52

Отправлен: 30.04.2011, 18:55
Вопрос задал: BVSV (Посетитель)
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, BVSV!
Вот и программа.
Я сделал следующие предположения:
1) Для работы с ЖКИ сигналы RS заведен на A1, а R/W на A0
В результате для адресации регистров и операции используются два младших бита адреса
Для отличия от обычной памяти я предположил использовать старший бит адреса.
2) Кроме цифр остаются еще две клавиши, которые я предлагаю использовать следующим образом:
левая нижняя - для очистки числа, 0 приведет к останову,
правая нижняя - для отработки введенного числа
Причем младшую цифру я игнорирую, т.к. она лишняя.
3) для выхода я использую бит p1.7

Период у нас получается 125 мкс
Скважность меняется от 1/25 до 80/100 = 20/25 или от 5 мкс до 100 мкс (получается, что макс 1000 надо делить на 10)
Реальные цифры Вы увидете только на осциллографе :)
Для включения/выключения напряжения на выходе используются два таймера.
Один включает, второй выключает...

Код:
;регистры ЖКИ
;конкретные адреса задавайте сами.
;важны только два младших бита
;предполагается, что RS заведен на A1, а R/W на A0
IR_WRITE equ 8000h
IR_READ equ 8001h
DR_WRITE equ 8002h
DR_READ equ 8003h

CLEAR equ 01h ;команда очистки экрана
SET_POS_0 equ 80h ;установка позиции 0
SET_POS_4 equ 84h ;установка позиции 4

;строка с цифрами
obM_0 equ 30h ;младший
obM_1 equ 31h
obM_2 equ 32h
obM_3 equ 33h ;старший

DEB_COUNT equ 100 ;число проверок для устранения дребезга клавиатуры

org 0 ;начало
jmp Start ;переход на основную работу

org 0bh ;адрес вектора 0 таймера
setb p1.7 ;включаем на выходе 1
setb tr1 ;запускаем таймер 1
reti

org 1bh ;адрес вектора 1 таймера
clr p1.7 ;выключаем сигнал на выходе
clr tr1 ;останавливаем таймер 1
reti

Start:
mov tmod,#00100010b ;оба таймеpа - 8-битные перегружаемые
mov ie,#8ah ;Разpешить пpеpывания от таймеpов + вообще разрешить
mov th0,255-125 ;константы для периода 125мк, что соответствует частоте 8кГц
mov tl0,255-125

call display_init ;вывод на экран ob/m с 5 позиции
Stop: ;останов
clr p1.7 ;выход в 0, останов
clr tr0 ;останов таймера 0
clr tr1 ;останов таймера 1
Zero:
mov obM_0,'0' ;инициируем строку с цифрами в '0000'
mov obM_1,'0'
mov obM_2,'0'
mov obM_3,'0'
MainLoop:
call display ;вывод строки на монитор

ScanLoop: ;цикл сканирования клави атуры
call scan ;сканируем клавиатуру
cjne a,#0ffh, GetDigit ;если код 0-11, то на анализ кода
jmp ScanLoop ;0ffh - нет кода - на цикл сканирования

GetDigit: ;нажата клавиша
cjne a,#0ch,CmpEnter ;продолжаем сравнение
jmp Zero ;нажата левая нижняя - сброс числа в 0
CmpEnter:
cjne a,#0dh,Digit ;нажата цифра?
call Calculate ;нажата правая нижняя - изменяем скважность
jz Stop ;если ноль, то останавливаем
jmp ScanLoop ;на сканирование клавиатуры
Digit: ;циклически вдвигаем цифру
mov obM_3,obM_2 ;старшая цифра теряется
mov obM_2,obM_1
mov obM_1,obM_0
mov obM_0,a
jmp ScanLoop ;на сканирование

Calculate: ;расчет скважности
;преобразуем строку в число (младший разряд игнорируем)
mov a,obM_3 ;проверим, чтобы число "входило" в один байт
; (допустимо вообще <= 100)
cjne a,#'2',cmp_hi_digit ;проверим старший разряд
cmp_hi_digit:
jc mul_ hi ;если старший разряд < 2, то все в порядке
mov a,#'1' ;иначе меняем на 1
mul_hi: ;формируем число
anl a,# 0fh ;преобразуем символ '0'-'9' в число 0-9
mov b,#100 ;
mul ab ;сотня
mov r2,a ;сохраним
mov a,obM_2
anl a,#0fh
mov b,#10
mul ab ;десятки
add a,r2
mov r2,a
mov a,obM_0
anl a,#0fh ;единицы
add a,r2 ;все число
jz calc_ret ;проверим на 0
cjne a,#101,cmp_max ;проверим на максимальное - 100
cmp_max:
jc set_timers ;<= 100 - все в порядке
mov a,#100 ;ограничиваемся 100 (1000 об/м)
set_timers: ;задаем таймер
cpl a
inc a ;константа для срабатывания таймера 1
mov th1,a
mov tl1,a
setb tr0 ;запускаем таймер 0
calc_ret:
ret

scan: ;сканируем клавиатуру
mov r2,#4 ;четыре линии
mov r3,#11111110b ;маска сканкода для выбора линии p1.0 - p1.3
mov r4,#0 ;база группы кнопок 0, 3, 6, 9
scan_loop: ;цикл сканирования линий
mov p1,r3 ;вывод сканкода
mov a,p1 ;читаем код клавиши из p1.4 - p1.6
swap a ;код в ac c.0 - acc.2
anl a,#07h ;сбросим незначащие биты
cjne a,#07h,debounce ;если есть нажатие, идем на устранение дребезга
jmp next ;нет нажатия - на следующую линию сканирования

debounce: ;устранение дребезга
mov r5,a ;сохраним код
mov r6,#DEB_COUNT ;число циклов проверки дребезга
debounce_loop: ;цикл проверки дребезга
mov a,p1 ;читаем код
swap a
anl a,#07h
cjne a,5,next ;если не равен сохраненному (r5 нулевого банка),
; то на следующее сканирование
djnz r6,debounce_loop ;проверяем DEB_COUNT раз
;клавиша нажата!
wait_off: ;подождем отпускания клавиши
mov a, p1 ;читаем код
swap a
anl a,#07h
cjne a,#07h,wait_off ;ждем отпускания
;сформируем из кода вида 00001101b число r4 + 1
mov r2,#3 ;число бит
mov a,r5 ;сканкод кнопки
conv_loop:
rrc a ;циклически выдвигаем младший бит в C
jnc scan_ret ;0 - число посчитано
inc r4 ;инкремент
djnz r2,conv_loop ;3 раза
scan_ret:
mov a,r4 ;код клавиши 0-11
mov dptr,#table ;таблица перекодировки
movc a,@a+dptr ;код в соответствии с таблицей
ret

next: ;переходим на следующую линию сканирования
inc r4 ;база для следующей линии клавиш (по 3 кнопки в линии)
inc r4
inc r4
mov a,r3 ;маска
rl a ;циклически сдвигаем (перемещаем 0 бит влево)
mov r3,a
djnz r2,scan_loop ;по всем линиям
mov a,#0ffh ;ничего не нажато
ret

;таблица кодов, соответствующих скан-кодам
;размещение, как на телефонной клавиатуре
;1 2 3
;4 5 6
;7 8 9
;c 0 d
;c - сброс
;d - ввод
table: db '1','2','3','4','5','6','7','8','9',0ch,'0',0dh


;п/п для работы с ЖКИ
WAIT_LCD: ;ожидание готовности
mov DPTR,#IR_READ
WAIT_BUSY:
movx a,@DPTR
jb acc.7,WAIT_BUSY ;ждем бит IR.7
ret
WRITE_LCD_DR: ;запись байта на ЖКИ
mov DPTR,#DR_WRITE
movx @DPTR,a
acall WAIT_LCD
ret
WRITE_LCD_IR: ;запись байта в регистр IR
mov DPTR,#IR_WRITE
movx @DPTR,a
acall WAIT_LCD
ret
display: ;п/п вывода строки цифр
mov a,#SET_POS_0 ;позиция 0
acall WRITE_LCD_IR
mov r0,#obM_0 ;адресс массива
mov r1,#4 ;количество
out_num_loop:
mov a,@r0
acall WRITE_LCD_DR
djnz r1,out_num_loop
ret
display_init: ;инициализация ЖКИ
mov a,#CLEAR ;очищаем экран
acall WRITE_LCD_IR
mov a,#SET_POS_4 ;устанавливаем позицию 4
acall WRITE_LCD_IR
mov a,#'o' ;выводим сообщение
acall WRITE_LCD_DR
mov a,#'b'
acall WRITE_LCD_DR
mov a,#'/'
acall WRITE_LCD_DR
mov a,#'m'
acall WRITE_LCD_DR
ret

end

-----
Люби своего ближнего, как самого себя

Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 05.05.2011, 17:24
Номер ответа: 266993
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 266993 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.



    В избранное