Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Rtmip писал(а):... Получится элемент И-НЕ :idea: ...
... А вот действительно, за счет чего? Думаю - подтягивающие резисторы нужны. Поэтому, меняйте схему подключения и все "взлетит" :beer: ...
... По поводу программы, если надумаете ее модернизировать, то я бы посоветовал это сделать так: ...


Спасибо, я просто когда макетировал все это, держал в уме принцип выводов MCS-51 - кто сильнее, тот и пересилит (и почему-то возомнил, что в логике сильнее 1 :))) ), а оно не так))

Насчет подтягивающих резисторов, никоим образом не пытаюсь в Вами спорить (глупо спорить с тем, кто тебе помогает :beer: ), просто руководствовался вот этим http://chipnews.gaw.ru/html.cgi/arhiv/00_09/stat_58.htm Там четко указано, что "Выходы порта P0 на самом деле также имеют транзисторы Q1, которые включаются при выводе младшего байта адреса и при выводе данных в командах записи во внешнюю память. Поэтому при работе порта P0 только в качестве шины данных внешние подтягивающие резисторы не нужны." Так как я избавился от вывода значения в порт, и вывожу только по шине, то я думаю, что можно не ставить их. И просто я допустил просчет не этапе проектирования макета, и у меня порт P0 микроконтроллера и разъем для подключения дисплея на самом краю макетки, красиво впаять туда резисторы не получится :( Так что буду пока пробовать без них...

По поводу программы, спасибо, постараюсь все это учесть :write:

П.С. Зработало !!! Еще в даташите на дисплей была ошибочка, команду очистки дисплея надо было ставить в конце инициализации. Ох уж мне эти Сусанины, не могут в мир документ без ошибки выпустить :kill:

Изображение
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Доброго времени суток. Учусь оптимизировать свои наработки. Есть у меня подпрограмма обработки нажатия матричной клавиатуры. В ней я опускаю столбец и побитно проверяю каждую строку (jnb X MetkaX), и уже на МеткеХ присваиваю код нажатой клавиши, и так 12 раз (если 12 кнопок). Хочется все это дело сделать "Быстрее, выше, сильнее". Попытался использовать массив в памяти программ:
Спойлер

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

Key_scan:
mov   DPTR,#Key_Tab1      ; Загрузка адреса кодовой таблицы 1
   mov     keyport,#11101111b   ; Опустим 1 столбец
   mov   A,keyport               ; Считаем порт клавиатуры в А
   cpl     A                       ; Инвертируем состояние порта, чтобы уменьшить таблицу символов
   anl     A,#00001111b      ; Маскируем разряды столбцов
   movc   A,@A+DPTR      ; Достаем символ из таблицы
    jz      Column_2                ; Если ноль - не было нажатия, проверяем следующий столбец
   mov     symbol,A      ; Не ноль, было нажатие
   jmp     Key_End         ; Пропустим остальные для экономии времени

Column_2:
   mov   DPTR,#Key_Tab2      ; Загрузка адреса кодовой таблицы 2
   mov     keyport,#11011111b   ; Поднимем назад 1 столбец, и опустим 2 столбец
   mov   A,keyport               ; Считаем порт клавиатуры в А
   cpl     A                       ; Инвертируем состояние порта, чтобы уменьшить таблицу символов
        anl     A,#00001111b      ; Маскируем разряды столбцов
    movc   A,@A+DPTR               ; Достаем символ из таблицы
   jz      Column_3                ; Если ноль - не было нажатия, проверяем следующий столбец
        mov     symbol,A      ; Не ноль, было нажатие
   jmp   Key_End                 ; Пропустим остальные для экономии времени

Column_3:
   mov   DPTR,#Key_Tab3      ; Загрузка адреса кодовой таблицы 3
   mov     keyport,#10111111b   ; Поднимем назад 2 столбец, и опустим 3 столбец
   mov   A,keyport               ; Считаем порт клавиатуры в А
   cpl     A                       ; Инвертируем состояние порта, чтобы уменьшить таблицу символов
        anl     A,#00001111b      ; Маскируем разряды столбцов
    movc   A,@A+DPTR               ; Достаем символ из таблицы
   jz      No_press                ; Если ноль - не было нажатия
        mov     symbol,A      ; Не ноль, было нажатие

Key_End:
Проверка введенных символов и прочая ерунда
No_press:            ; Если мы прыгнули сюда джампом, значит ни одна кнопка не была нажата
   mov     keyport,#0FFh      ; Поднимем все столбцы, ну и строки заодно
        reti

Key_Tab1:            ; Клавиатурная таблица 1 столбца
   db      '1','4',0,'7',0,0,0,'*'
   
Key_Tab2:            ; Клавиатурная таблица 2 столбца
   db      '2','5',0,'8',0,0,0,'0'
   
Key_Tab3:            ; Клавиатурная таблица 3 столбца
   db      '3','6',0,'9',0,0,0,'#'

Сразу предупреждаю, приведенный код не отлаженный и скорее всего не рабочий, мне просто нужно понять концепцию.
Вот до чего я дошел. Использую таблицу символов, разделенную на 3 части, чтобы занимать меньше места в памяти программ (если бы я использовал 1 таблицу, мне пришлось бы сделать ее размерностью 256 ячеек). С той же целью инвертирую состояние считанного порта, чтобы в младшей тетраде получить максимум 1000 (8 в дес. системе) и тем самым ограничить длину таблицы 8 значениями.
Но как видите, у меня 3 раза дублируется кусок кода по опросу. И что еще досаднее, в моей совмещенной клавиатурной таблице половина ячеек пропадает впустую (забиты 0). Помогите мне избавится от этих недостатков. Можете даже предложить иную реализацию. Основная идея - избавиться от кучи джампов и меток (все мои программы от этого страдают, хочу научится писать красиво).

П.С. Допридумал оформить повторяющийся кусок кода в макрос:

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

Get_symbol   macro
      mov   A,keyport   ; Считаем порт клавиатуры в А
      cpl   A      ; Инвертируем состояние порта, чтобы уменьшить таблицу символов
      anl   A,#00001111b   ; Маскируем разряды столбцов
      movc   A,@A+DPTR   ; Достаем символ из таблицы
      endm
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение ARV »

рекомендую вам вспомнить про циклы, а не только про макросы.

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

   маска = 0b00010000; первый столбец
   счетчик = 4
цикл:
   mov  R, маска
   инверсия R
   вывод R ; активируем столбец
   ввод строка ; считываем состояние строк
   сравнить строка, #пусто
   jnz выход
   сдвиг_влево маска
   djnz счетчик, цикл
выход:
   ; здесь у нас код нажатой кнопки в ячейке "строка"
как-то так.

P.S. прошу прощения за волапюк - отвык я о ассемблера, тем более 51-го :dont_know:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Получился вот такой код, он полностью рабочий:
Спойлер

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

Key_scan:                               ; Подпрограмма опроса матричной клавиатуры
   clr   TR0                ; Остановим Timer0
   mov   TH0,#3Ch      ; Заново занесем значение в счетный регистр Timer0
   mov   TL0,#0AFh               ; При данном значении прерывание возникает каждые 50 мс
   mov   counter,#3              ; Загружаем количество столбцов
   mov   column,#11101111b   ; Первый столбец
Loop:
   mov   keyport,column      ; Опустим столбец
   mov   A,keyport      ; Считаем порт клавиатуры в А
   cpl   A         ; Инвертируем состояние порта, чтобы на месте нажатой кнопки получить 1
   anl   A,#00001111b      ; Маскируем разряды столбцов (старшие биты АСС)
   jnz   Skip_Repeat      ; Если на выходе не 0, значит что-то нажато, гоу проверять
    mov   A,column      ; В аккумуляторе 0, опять загрузим наш столбец
   rl   A                       ; Переведем на следующий
   mov   column,A      ; И выгрузим новый столбец назад
   djnz   counter,Loop            ; Повторяем столько раз, сколько всего столбцов
   jmp     No_press                ; Не было нажатия
Skip_Repeat:                            ; Таки что-то нажали
   cjne   counter,#3,Out_1        ; Если counter=3, значит опустили 1 столбец
   mov   DPTR,#Key_Tab1      ; Загрузка адреса клавиатурой таблицы 1 столбца
   jmp     Out
Out_1:
   cjne   counter,#2,Out_2        ; Если counter=2, значит опустили 2 столбец
   mov   DPTR,#Key_Tab2      ; Загрузка адреса клавиатурой таблицы 2 столбца
   jmp     Out
Out_2:
   cjne   counter,#1,Out      ; Значит опустили 3 столбец
   mov   DPTR,#Key_Tab3      ; Загрузка адреса клавиатурой таблицы 3 столбца
Out:
   jnb   correct_bit,No_Correction       ; Если нажата кнопка из 4 строки (*,0,#), то скорректируем содержимое АСС,
    subb   A,#5                    ; чтобы попасть в нужнаю ячейку клавиатурной таблицы
No_Correction:
   movc   A,@A+DPTR      ; Достаем символ из таблицы
        mov     symbol,A      ; Загружаем его в переменную

   clr     zumer                   ; Озвучим нажатие
   setb   F0         ; Запомним факт нажития кнопки
   call   Del_100ms               ; Потупим для подавления дребезга кнопки
        setb    zumer                   ; Закончим озвучку нажатия
No_press:            ; Если мы прыгнули сюда джампом, значит ни одна кнопка не была нажата
   setb   TR0                ; Запустим Timer0
   reti

Del_100ms:
        mov   R2,#4h
   mov   R1,#0A0h
   mov   R0,#4Ch
    djnz   R0,$
   djnz   R1,$-4
   djnz   R2,$-8
   mov   R0,#49h
   djnz   R0,$
        ret

Key_Tab1:            ; Клавиатурная таблица 1 столбца
   db      0,'1','4','*','7'

Key_Tab2:            ; Клавиатурная таблица 2 столбца
   db      0,'2','5','0','8'

Key_Tab3:            ; Клавиатурная таблица 3 столбца
   db      0,'3','6','#','9'

ARV, спасибо за содействие :))
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Пока_без_кота, приветствую! Спасибо за картинку с дисплеем. :)
Рад, что все заработало у вас! По поводу подтяжки Р0, вы правы, а я перепутал с режимом работы обычного ввода-вывода.
По поводу оптимизации сканирования матричной клавиатуры. Думаю можно еще короче написать.
В подпрограмме не учитываю защиту от дребезга, нажатий сразу двух клавиш и звук. Это вы и сами допишите,
если надо будет. Для примера возьмем "телефонную" клавиатуру:
Спойлер

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

klaviatura:
    mov DPTR, #0    ;
    mov R7,   #4    ;счетчик строк
    mov R6,   #1    ;маска сканирования строк
klav1:
    mov R4,   #4    ;счетчик столбцов
    mov R5,   #1    ;маска на результат сканирования
    mov A,    R6
    rr  A           ;сдвиг вправо единицы из старшего в младший разряд
    mov R6,   A     ;сохранить
    cpl A           ;для вывода сканирующего нуля инверсия
    mov P1,   A     ;вывод сканирующего нуля в порт
klav2:
    mov A,    P1    ;считать результат
    anl A,    R5    ;накладываем маску
    jz     klav3    ;если был 0, то кнопка нажата
    mov A,    R5    ;иначе сдвигаем маску влево для чтения
    rl  A           ;следующего бита
    mov R5,   A
    inc DPTR        ;увеличиваем, указатель таблицы кнопок
    djnz R4, klav2  ;перебор всех столбцов
    djnz R7, klav1  ;перебор всех строк
    mov A,    #16  ; признак не нажатых кнопок, можно просто: setb  F0 , затем проверять флаг
    ret                  ;
klav3:
    mov A,    DPL   ;результат сканирования от 0 до 15
    mov DPTR, #Tab_klav
    movc A, @A+DPTR ;
    ret                  ;
;
Tab_klav:           ;для наглядности построчно
DB  0               ;1
DB  1               ;2
DB  2               ;3
DB  3               ;A
DB  4               ;4
DB  5               ;5
DB  6               ;6
DB  7               ;B
DB  8               ;7
DB  9               ;8
DB  10              ;9
DB  11              ;C
DB  12              ;*
DB  13              ;0
DB  14              ;#
DB  15              ;D
В результате, после сканирования можно получать сразу код символа из таблицы для вывода,
например, на дисплей или в уарт. Конечно, надо будет заполнить таблицу соответствующим образом.
Вместо чисел от 0 до 15 надо вписать нужные коды. Можно вообще, без таблицы, тогда на выходе будем
получать число от 0 до 15 и оно будет соответствовать нажатой клавише. Можно подключить матрицу не 4Х4,
а любую, меньшей размерности, логика работы и результаты не меняются.
Если подумать над программой, то может и можно будет ее еще сократить-оптимизировать.
Схема подключения клавиатуры:
---1-----2-----3-----A---- P1.7
---4-----5-----6-----B---- P1.6
---7-----8-----9-----C---- P1.5
---*-----0-----#-----D--- P1.4
P1.0...P1.1..P1.2..P1.3
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

После просмотра Вашего кода, мои потуги уже не кажуться мне значительной оптимизацией :))
Правда вот 1 нюанс мне кажется лучше в моей реализации: лучше выставлять флаг нажатой кнопки, чем флаг, то ни одна кнопка не нажата. Потому что в общем времени работы МК, гораздо больше времени кнопки не нажимаются, чем нажимаются, а значит мы экономим 1 команду в цикле почти каждого опроса :beer:
Правда все это нивелируется последующей задержкой антидребезга. Но я ведь и ее когда-то надеюсь устранить, заюзав внутри подпрограммы таймер, который все равно остановлен и проставивает :)))
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Здравствуйте! Спасибо за комментарии :beer:
Пока_без_кота писал(а):...лучше выставлять флаг нажатой кнопки, чем флаг, то ни одна кнопка не нажата...
для этого можно переставить одну команду, поставив ее после метки "klav3" :

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

    setb  F0 
Пока_без_кота писал(а):...заюзав внутри подпрограммы таймер, который все равно остановлен и проставивает...
интересно, как вы это будете делать? Надеюсь не будете "зависать" в подпрограмме ожидая сработки таймера?!
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Rtmip писал(а):... Надеюсь не будете "зависать" в подпрограмме ожидая сработки таймера?!

Нет конечно :))) Я еще не все продумал, но я планирую вываливаться в специально отведенную часть главного цикла, в которой будут выполняться критичные ко времени выполнения операции, которые тем не менее не будут требовать мгновенной реакции (такое я вывожу в обработчики прерываний). Оттуда, по истечении времени антидребезга, я буду возвращаться в цикл обработки нажатия, завершать его, и возвращаться уже в основной главный цикл по reti. Как-то так... :dont_know:
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Понятно, но становится интересно, а что это будет, такое, с матричной клавиатурой?
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Охранная сигнализация. Придеться еще освоить I2C (чтобы приделать EEPROM память) и научиться работать с GSM-модулем (слать СМС). Возможно потом прикручу экранчик для удобства, и DS1307 в качестве часов. И финальная стадия, это отделение клавиатурного блока и вынос его на расстояние 15-20 метров от основного блока, который будет где-то заныкан (для безопасности). Как-то так. Сейчас работаю над алгоритмом распознавания пароля))
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Хорошие планы, мне нравится! Вот только расстояние в 15-20 метров сильно смущает :))
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

А чем смущает такое расстояние ? Я читал, что по RS-232 (тот который +-12 В) можно передавать на 10-15 метров. Если не получится, буду пробовать RS-485, но чесно говоря - не хотелось бы, слишком "тяжелая артиллерия" для моих масштабов. Есть еще токовая петля, но это тоже надо спец микросхемы применять, а я хотел что попроще. А MAX232 на каждом углу куча продается.
Насилу дописал алгоритм проверки введенного пароля, думал мозг сломаю, пока все нюансы учту :shock:
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение BOB51 »

Для токовой петли никаких "спец" не требуется, ежли только не притензии к скорости обмена.
8)
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Нет, к максимальным 19200 б\сек токовой петли претензий нет никаких, я сейчас UART юзаю на скорости 9600 б\сек. Просто С МАX232 уже имел дело и проблем там не было (правда расстояния было пару метров всего). Вот и хотелось бы использовать то, что знаешь, и умеешь готовить (хе-хе, это я пока только думаю, что умею).
Покритикуйте кто-то заодно мой алгоритм распознавания пароля. Код рабочий (я всегда все проверяю на макете), функционал устраивает, просто хочу видеть, где можно сделать лучше:
Спойлер

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

;============== Проверка пароля ====================
Pass_Check:            ; Проверка пароля
   cjne   A,#'#',Skip      ; Проверим, или это # (символ ввода пароля)
   mov   A,   pass_counter    ; Это #, проверим, сколько правильных символов подряд до этого было введено
   cjne   A,#3,Error      ; Если не 3, то это не наш пароль
   mov   A,   symbol_counter   ; Проверим, сколько всего символов было введено до #
   cjne   A,#3,Error      ; Если не 3, то это не наш пароль
   jmp   Yes_pass      ; 3, так что это наш пароль
Skip:                                   ; Пока еще не #, будем проверять дальше
   inc   symbol_counter          ; +1 введенный символ   
   mov   DPTR,   #Pass_Tab   ; Загрузка адреса кодовой таблицы
   mov   A,   pass_counter   ; Загрузка порядкового номера цифры пароля
   movc   A,   @A+DPTR      ; Запись очередной цифры пароля в А
   cjne   A,symbol,Error_2   ; Сравним введенный символ с символом пароля
   inc   pass_counter            ; Символ принят, в следующий раз возьмем для сравнения следующую цифру пароля
   jmp   No_End   
Yes_pass:
   setb   password_ok             ; Пароль принят !!!
   mov   error_counter,#4        ; Восстановим счетчик попыток ввода пароля
        inc   pass_counter            ; Чтобы пикнуть 3 раза
PiPiPi:                                 ; Озвучим принятый пароль тройным пиканьем
   call   Del_125ms
   cpl   zumer
   djnz   pass_counter,PiPiPi
Error:               ; До # было введено больше/меньше символов, чем должно быть в пароле, либо просто количество введенных подряд правильных символов не совпадает
   mov   symbol_counter,#0   ; Обнулим счетчик введенных символов, ввод пароля начнется сначала
Error_2:                           ; Введен неправильный символ, счетчик правильно введенных символов необходимо обнулить
   mov   pass_counter,#0         ; Обнулим счетчик правильно введенных символов, ввод пароля начнется сначала
   jb   password_ok,No_End      ; Если введен пароль, нечего уже проверять
   mov   A,symbol
        cjne   A,#'#',No_End
   clr   zumer                   ; Если введен неправильный пароль, то надо сделать длинный ПИИИИИИК
        call   Del_1s
   djnz   error_counter,No_End    ; Проверим сколько неправильных попыток уже было сделано
   clr   sirena_copy_1      ; Достаточно, гавкнем сиреной !!!
No_End:                                 ; Была нажата правильная кнопка, но не последняя
        call   Del_125ms      ; Потупим для подавления дребезга кнопки
          setb   zumer                   ; Закончим озвучку нажатия
;============== Конец проверки пароля ====================

Pass_Tab:            ; Таблица паролей
   db   '1','2','3'      ; Пароль, после всегда символ #
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Jack_A »

Вот эта простая токовая петля работала у меня без замечаний.
Изображение
Вложения
TP1.JPG
(11.59 КБ) 824 скачивания
Изображение
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение ARV »

Пока_без_кота писал(а):Нет, к максимальным 19200 б\сек токовой петли претензий нет никаких, я сейчас UART юзаю на скорости 9600 б\сек. Просто С МАX232 уже имел дело и проблем там не было (правда расстояния было пару метров всего). Вот и хотелось бы использовать то, что знаешь, и умеешь готовить (хе-хе, это я пока только думаю, что умею).
Покритикуйте кто-то заодно мой алгоритм распознавания пароля. Код рабочий (я всегда все проверяю на макете), функционал устраивает, просто хочу видеть, где можно сделать лучше:
Спойлер

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

;============== Проверка пароля ====================
Pass_Check:            ; Проверка пароля
   cjne   A,#'#',Skip      ; Проверим, или это # (символ ввода пароля)
   mov   A,   pass_counter    ; Это #, проверим, сколько правильных символов подряд до этого было введено
   cjne   A,#3,Error      ; Если не 3, то это не наш пароль
   mov   A,   symbol_counter   ; Проверим, сколько всего символов было введено до #
   cjne   A,#3,Error      ; Если не 3, то это не наш пароль
   jmp   Yes_pass      ; 3, так что это наш пароль
Skip:                                   ; Пока еще не #, будем проверять дальше
   inc   symbol_counter          ; +1 введенный символ   
   mov   DPTR,   #Pass_Tab   ; Загрузка адреса кодовой таблицы
   mov   A,   pass_counter   ; Загрузка порядкового номера цифры пароля
   movc   A,   @A+DPTR      ; Запись очередной цифры пароля в А
   cjne   A,symbol,Error_2   ; Сравним введенный символ с символом пароля
   inc   pass_counter            ; Символ принят, в следующий раз возьмем для сравнения следующую цифру пароля
   jmp   No_End   
Yes_pass:
   setb   password_ok             ; Пароль принят !!!
   mov   error_counter,#4        ; Восстановим счетчик попыток ввода пароля
        inc   pass_counter            ; Чтобы пикнуть 3 раза
PiPiPi:                                 ; Озвучим принятый пароль тройным пиканьем
   call   Del_125ms
   cpl   zumer
   djnz   pass_counter,PiPiPi
Error:               ; До # было введено больше/меньше символов, чем должно быть в пароле, либо просто количество введенных подряд правильных символов не совпадает
   mov   symbol_counter,#0   ; Обнулим счетчик введенных символов, ввод пароля начнется сначала
Error_2:                           ; Введен неправильный символ, счетчик правильно введенных символов необходимо обнулить
   mov   pass_counter,#0         ; Обнулим счетчик правильно введенных символов, ввод пароля начнется сначала
   jb   password_ok,No_End      ; Если введен пароль, нечего уже проверять
   mov   A,symbol
        cjne   A,#'#',No_End
   clr   zumer                   ; Если введен неправильный пароль, то надо сделать длинный ПИИИИИИК
        call   Del_1s
   djnz   error_counter,No_End    ; Проверим сколько неправильных попыток уже было сделано
   clr   sirena_copy_1      ; Достаточно, гавкнем сиреной !!!
No_End:                                 ; Была нажата правильная кнопка, но не последняя
        call   Del_125ms      ; Потупим для подавления дребезга кнопки
          setb   zumer                   ; Закончим озвучку нажатия
;============== Конец проверки пароля ====================

Pass_Tab:            ; Таблица паролей
   db   '1','2','3'      ; Пароль, после всегда символ #

показалось сложновато и слегка запутанно.
я бы просто по мере ввода сравнивал каждый символ с паролем. если хотя бы один символ не совпал - устанавливал бы флаг, что не совпал пароль, и после того просто игнорировал бы ввод. когда введен символ конца пароля (у вас вроде #) - просто смотрел бы на флаг. если флаг стоит - ошибка, не стоит - все Ок.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение BOB51 »

Может есть смысл в плоскости KEELOQ поглядеть на реализацию обмена?
:roll:
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Всех с новым годом!
Пока_без_кота, мне тоже показалась ваша программа неоднозначна и более того, мне показалось,
что там могут быть логические ошибки, но это трудно сказать, не видя, точек входа и выхода из подпрограммы.
Поэтому прислушайтесь к совету ARV, но может я и ошибаюсь, и все там нормально :dont_know:
По поводу клавиатуры на расстоянии 20 метров: а как вы будете ее подключать физически? Ведь у нее
как минимум 8 проводов будет? Не очень понял этот момент.
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Rtmip писал(а): По поводу клавиатуры на расстоянии 20 метров: а как вы будете ее подключать физически? Ведь у нее
как минимум 8 проводов будет? Не очень понял этот момент.

И Вас с наступившим. И всех завсегдатаев этой темы))
Клавиатура впоследствии будет выполнена на отдельном контроллере (часть программы из основного блока просто уйдет в нее), который будет подключатся к основному блоку с помощью последовательной шины. Какой именно, пока точно утверждать не берусь, пока ориентируюсь на RS-232, а в случае неудачи на токовую петлю (схема с рисунка Jack_A вроде несложная).

Уважаемый ARV, спасибо за наводку. На досуге еще обмозгую этот вопрос и возможно отпишу сюда результат.
Подскажите еще по такому вопросу. Для формирования Таблицы пароля я хочу использовать макрос IRPC (это тот, который выводит строку посимвольно), который выглядит вот так:
Спойлер

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

irpc   Pass,   '123'
   db   Pass
endm

и должен транслироваться вот в это:

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

db   '1'
db   '2'
db   '3'

Вместо этого он транслируется вот в это:

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

db   1
db   2
db   3

При использовании макроса IRP все транслируется корректно:

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

irp   Pass,   '1','2','3'
   db   Pass
endm

как положено транслируется в:

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

db   '1'
db   '2'
db   '3'
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Доброго времени суток. Прошу подсказать, как правильнее реализовать отправку строки по UART. Вызывать процедуру отправки, в которой при каждом новом извлечении символа из памяти программ записывать его в SBUF, и тем самым вызывать прерывание, в котором он будет отправлятся. Или устанавливать вручную флаг TI, который вызовет прерывание, внутри которого и будет находится процедура отправки, и она будет крутится в цикле внутри прерывания, пока не отправит всю строку. Вот код 1 варианта:
Спойлер

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

; Где-то внутри главного цикла
   mov   DPTR,#AT_CMGS         ; Загружаем адрес 1 символа команды
   call    Send_comm
;=======
Send_comm:                                              ; Подпрограмма отправки
   clr   A                                       ; Очистим АСС
   movc   A,   @A+DPTR                         ; Поместим очередной символ команды в АСС
   jz   Out               ; Если конец команды, выходим
   mov   SBUF,   A                               ; Скопируем его в буфер передатчика
   call    Del_100ms                               ; Без этой задержки шлет мусор !!!
   inc   DPTR                                    ; Возьмем следующий символ
   jmp   Send_comm                                 ; Зациклимся на передачу всей строки
Out:
   ret
;=======
Serial_int:                  ; Обработчик прерываний посл. порта
   clr   EA               ; Запретим все прерывания
   jb   RI,   Receive            ; Если есть флаг RI, значит это прием
   jnb     TI,$                          ; Нет флага ТІ (окончания посылки) - топчемся на месте
   clr   TI               ; Был флаг ТІ, байт ушел, сбросим флаг ТІ
   jmp     Serial_end
Receive:                  ; Это прием
   mov   A,   SBUF            ; Это прием, примем байт
   clr   RI               ; Сбросим флаг RI
Serial_end:
   setb   EA               ; Разрешим все прерывания
   reti

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

Вот 2 вариант:
Спойлер

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

; Где-то внутри главного цикла
   mov   DPTR,#AT_CMGS         ; Загружаем адрес 1 символа команды
   setb   TI            ; Вызовем отправку команды
;=======
Serial_int:                  ; Обработчик прерываний посл. порта
   clr   EA               ; Запретим все прерывания
   jb   RI,   Receive            ; Если есть флаг RI, значит это прием
        clr   TI                                      ; Сбросим флаг ТІ, которым вызвали прерывание
Repeat:
   clr   A                                       ; Очистим АСС
   movc   A,   @A+DPTR                         ; Поместим очередной символ команды в АСС
   jz   Serial_end            ; Если конец команды, выходим
   mov   SBUF,   A                               ; Скопируем его в буфер передатчика
   jnb     TI,$                          ; Нет флага ТІ (окончания посылки) - топчемся на месте
   clr   TI               ; Был флаг ТІ, байт ушел, сбросим флаг ТІ
   inc   DPTR                                    ; Возьмем следующий символ
   jmp   Repeat                                  ; Зациклимся на передачу всей строки
Receive:                  ; Это прием
   mov   A,   SBUF            ; Это прием, примем байт
   clr   RI               ; Сбросим флаг RI
Serial_end:
   setb   EA               ; Разрешим все прерывания
   reti

Этот вариант работает нормально без введения всяких задержек. Но я везде читал, что надо как можно быстрее валить из прерывания, а я там кручусь в цикле, и меня это немного смущает.
Так как правильнее ?
Ответить

Вернуться в «Разные вопросы по МК»