Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

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

Ср май 09, 2018 17:51:21

Так работает любое контрольное устройство - независимо от содержания пакета результат контрольного отсчета и прилагаемого ключа-подписи всегда одинаков.
А ежли имелась ошибка - будет и изменение результата.
8)

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

Вт май 15, 2018 11:09:38

Не совсем понял фразы.

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

Пн ноя 11, 2019 08:48:46

Доброго времени суток.
Внутри кода находится строка символов (массив вида db 'Hello',0).
Необходимо поместить первый символ строки в буфер приемопередатчика UART, "обойти" этот массив и продолжить выполнение кода за ним + оставить в DPTR адрес второго символа строки для продолжения передачи всей строки из обработчика UART.
Помещаю в DPTR адрес первого символа строки.
Затем написал 2 варианта обхода, оба рабочие, но 1-й требует лишнюю ячейку ОЗУ, а 2-й чуть длиннее. Может кто увидит более элегантное решение:
Спойлер
Код:
   clr      A                                                     ; очистка для корректного извлечения первого символа
   movc   A,      @A+DPTR               ; получаем первый символ из строки
   inc       DPTR                     ; символ строки уже в АСС, смещаем указатель на следующий символ
;----------
if VARIANT_FIND_STRING_END = 0
   push    ACC                                                               ; cохраним символ строки
   clr     A
   mov     temp,A
Find_String_End:                                                                ; ищем конец строки
   mov     A,   temp                                                 
   inc     temp
   movc   A,      @A+DPTR
   jnz     Find_String_End
   pop     ACC                                                               ; восстановим символ строки
   clr      uart_tx_compl
   mov      SBUF,   A
   mov     A,   temp                                                       ; восстановление для корректного перехода
;----------
elseif VARIANT_FIND_STRING_END = 1
   push   DPH                                                                  ; сохраним DPTR
   push   DPL
   push    ACC                                                               ; cохраним символ строки
Find_String_End:                                                                ; ищем конец строки
   clr      A                                                          ; очистка для корректного извлечения очередного символа
   movc   A,      @A+DPTR               ; получаем очередной символ из строки
   inc      DPTR                     ; смещаем указатель на следующий символ
   jnz      Find_String_End                                         ; если достигнут конец строки
   pop     ACC                                                               ; восстановим символ строки
   clr      uart_tx_compl
   mov      SBUF,   A
   clr      A                                                              ; очистка для корректного перехода
   ; +  2 pop для восстановления DPTR ПОСЛЕ перехода за конец строки
endif
;----------
    jmp      @A+DPTR                                                  ; прыжок ЗА конец строки
db 'Hello',0                                                                         ; тут наша строка
; тут дальнейший код

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

Пн ноя 11, 2019 10:41:39

А если передачу вести самостоятельной подпрограммой?
:roll:
Т.е. основная программа идет сама по себе, а при необходимости пересылки запускаем подпрограмму обслуживания передатчика,
которую привязываем к прервыанию и начальному адресу массива символов...
А подпрограммка UARTа крутится самостоятельно пока не исчерпает содержимое массива...
:roll:

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

Пн ноя 11, 2019 10:51:06

Это я знаю как сделать.
Хочется именно "обходить" строку в коде, дабы иметь возможность ее объявление прямо на месте, в макросе, а не объявлять ее где-то на отшибе.

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

Пн ноя 11, 2019 11:02:26

Так макрос может включать в себя строку и вызов подпрограммы обслуживания передатчика...
Там просто вставляем текущий адрес начала строки равноценно таковому для любой области памяти.
:roll:
Это вызов подпрограммы с передачей параметров через стек или через регистры ОЗУ.
А в макросе остается только добавить переход для обхода участка символов строки.
Примерно
код....
вызов подпрограммы обслуживания передатчика с заданием параметра "начало строки"
переход на метку "конец строки+1"
начало строки:
конец строки+1:
продолжение кода...
:roll:

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

Пн ноя 11, 2019 11:17:53

:roll:

Не понял. Можно увидеть код/псевдокод ?
Под обработчиком UART имею ввиду прерывание UART с соответвующим кодом выборки и отправки строки (в текущей реализации все кроме первого символа, который отправляется из основного кода).

Ап. Благодарю.

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

Пн ноя 11, 2019 11:42:51

МММ...
В принципе есть регистровая пара в которую помещается целевой адрес начала строки перед вызовом программы передачи.
А программа передачи работает с данной регистровой парой как с текущим указателем чего отсылать.
Чего мы в ту регистровую пару поместим - адрес из текущего кода или из отдельной области - значения не имеет - будет выполняться одинаково.
Такой вариант у меня в КОТУИНКО биосе.
Разбирать/вспоминать долго (ибо таки поднаворочено).
Вот кусманчик передатчика:
Спойлер
Код:
;----------
; ********************************************
;
; блок передачи строки символов ASCII
; признак завершения строки - esc символ \0
;
;----------
;
; в подпрограммах обработки прерываний при передаче
; строки символов из ПЗУ
; используется текущий регистровый банк RB
; в следующем варианте интерпритации регистров
;
; R7= не определен
; R6= не определен
; R5= не определен
; R4= не определен
; R3= не определен
; R2= не определен
; R1= не определен
; R0= не определен
;
; также используется DPTR как указатель ячеек размещения данных
;
;----------
;
; поскольку первый символ передается ДО возникновения
; прерывания
; по RI\TI блок обработки выполнен как подпрограмма
; с независимым вызовом и возвратом
;
; инициализирующий вызов в точку prog_txd_init
; вход при прерывании по TXD в точку proс_txd
;
;----------
;
   .cseg
 proc_txd_init:
     clr eof_txd ; сброс флага "передача строки завершена"
     mov ctp_tx,#0 ; указатель смещения символа в строке = 0
 proc_txd:
    push PSW
    push ACC
    push DPH
    push DPL
    mov DPL,strg_ptr ;
    mov DPH,(strg_ptr+1) ;
    mov a,ctp_tx
    movc a,@a+dptr
    jnz stdtx ; в конце строки символов стоит \0 (0х00)
    setb eof_txd ; если обнаружено (0x00)
    sjmp end_stdtx ; завершаем работу с eof_txd=1
 stdtx:
    mov SBUF,a ; иначе очередной байт на передачу
    inc ctp_tx ;
 end_stdtx:
    pop DPL
      pop DPH
      pop ACC
      pop PSW
   ret

и собственно весь тот проект:
https://yadi.sk/d/o-Jf3fADfDtsEQ
там поднакручено из-за особенностей вызова обработчика передатчика - сначала идет вызов как подпрограммы из кода, а затем дальнейшая обработка как прерывания до конца массива символов.
:beer:

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

Вс ноя 17, 2019 14:20:51

Доброго времени суток.
Написал макрос поиска подстроки (из флеша) в строке (из ОЗУ).
Покритикуйте и предложите лучше.
Спойлер
Код:
_search_substring_from_FLASH_in_string_from_RAM    macro   _ram,_str,_size
               mov     R0,      #_ram
               mov     DPTR,   #_str
               mov     string_size,_size
               call    Search_substring_from_FLASH_in_string_from_RAM_routine     ; если после вызова процедуры, string_size > 0, подстрока в строке найдена
               endm

Search_substring_from_FLASH_in_string_from_RAM_routine:
   inc      string_size                                                         ; to return string_size>0 if the string is found
   mov      temp_dph,DPH                                              ; save DPTR
   mov      temp_dpl,DPL
Loop_Search_substring_from_FLASH_in_string_from_RAM_routine:
   clr     A
   movc    A,  @A+DPTR
   jz      End_Search_substring_from_FLASH_in_string_from_RAM_routine
   inc     DPTR
   clr      C
   subb   A,      @R0
   inc     R0
   jz      Skip_Restore_DPTR
   mov      DPH,   temp_dph                                           ; restore DPTR
   mov      DPL,    temp_dpl
   jnb      symbol_ok,Skip_correct_R0_string_size                               ; if previous symbol is good,
   clr     symbol_ok
   dec     R0                                                                  ; go back 1 step
   inc      string_size
   jmp     Skip_correct_R0_string_size
Skip_Restore_DPTR:
   setb    symbol_ok
Skip_correct_R0_string_size:
   djnz    string_size,Loop_Search_substring_from_FLASH_in_string_from_RAM_routine
End_Search_substring_from_FLASH_in_string_from_RAM_routine:
   ret

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

Вс ноя 17, 2019 20:34:56

На первый взгляд...
Разве что...
Как элемент сравнения помимо вычитания попробовать
cjne или xrl ...
Да и в ОЗУ у 51-й не так уж много места для строк произвольного размера.
Посему можно и прямой адрес задавать (не через косвенную адресацию) но при некоторой потере объема в ПЗУ.
Есть смысл выделения буфера определенного размера в косвенноадресуемой области для 52-х (128+128 байт)
там уже вариант работы через стек... Однако переносимость кода будет иметь ограничения.
В принципе то уже подгонять под конкретную потребность надо.
:roll:
И еще...
Для единичного символа это подойдет (ловим первый встретившийся и далее, если совпадает последовательность).
А вот для строки, содержащей пару одно/двух(и более) символьных повторов...
Вида :
контрстрока
поймать в ней
рок
или более сложный двойной/многократный повтор одинакового фрагмента чуток поменьше контрольного фрагмента...
:dont_know:

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

Вс ноя 17, 2019 22:54:41

...
Для единичного символа это подойдет (ловим первый встретившийся и далее, если совпадает последовательность).
А вот для строки, содержащей пару одно/двух(и более) символьных повторов...
Вида :
контрстрока
поймать в ней
рок
или более сложный двойной/многократный повтор одинакового фрагмента чуток поменьше контрольного фрагмента...
:dont_know:

Скорее так:
контрстрока
поймать в ней
тро
Ну я для этого как раз флаг symbol_ok и ввел. Без него код был попроще, но например последовательность '123' в массиве '1121121123ХХХ' уже не ловилась, ибо первый сивол настоящей последовательности разпозначался как неправильный второй символ преполагаемой последовательности, и пропускался.
Мне ответы на АТ-команды надо парсить, а там частенько такое встречается, что ответы началом похожи.

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

Пн ноя 18, 2019 08:56:21

А почему бы не сходу и "парсить" ?
Без предварительного буферного ввода.
(Ессно буфер - накопитель полезной составляющей будет необходим).
Единственно скорость обмена делать соответствующей.
Я поток данных из *.hex файла получаемого из терминалки ПК в бинарник внешнего ОЗУ перегоняю без особых проблем.
Правда на скорости 9600 (при кварце 11,0592МГц)... Но там дополнительная обработка содержимого добавляется - из-за того и "некоторые излишества".
Собственно в бутлоадере КОТУИНКИ этим mason_2.txt занимается.
Спойлер
Код:
;
;          mason_2.txt
;
; файл обработчика-загрузчика intel.hex файла
; формат inhx8m , intel intelec 8MDS
; текстовой файл ASCII
; генерируемого компиляторами AVR Studio 4.19,
; MPLAB IDE v8.92 и c51asm.exe
;
; базовый обработчик на основе AT89S51
;
; на время исполнения bottle прерывания по
;   RI и TI запрещены
; в программе используется программный опрос
; флага RI
;
;----------
;
;таблица обьявленных имен - пользовательские константы
;
; <simbol> equ <expr>
;
; xon_kod      equ 0x17 ; синхрокод "готов к приему"
; xoff_kod     equ 0x19 ; синхрокод "остановить передачу"
; start_kod    equ 0x3A ; код символа ':'
; vk_kod       equ 0x0D ; код символа "возврат каретки" ('\r')
; ps_kod       equ 0x0A ; код символа "перевод строки" ('\n')
; data_string  equ 0    ; признак строки данных
; endf_string  equ 1    ; признак последней записи в файле
; adr_seg_srt  equ 2    ; запись с адресом сегмента
; adr_lin_str  equ 4    ; запись с линейным адресом
; tm_ertmo     equ 20   ; задержка между приемом соседнимх байт
;                      ; в 0,1 секунду
;
;----------
;
; таблица обьявленных имен - переприсвоение имен
;
; данная часть текста используется для переразметки
; в случае когда область регистров ранее уже была определена
; в главном модуле файла определения имен (dfn_name.txt)
; используется в основном подключеиями-библиотеками
; при обязательности отсутствия перекрытия областей
; данных при исполнении различных модулей программы
;
; <simbol> equ <expr>
;
;
;
;----------
;
; секция регистров общего назначения
; для прямоадресуемых по 0x7F включительно
; /во вложенных файлах данная область добавляется
; в конец области основных определений
; заголовочного файла/
;
; name: .ds <expr>
;
    .DSEG at 0x40 ; /at adres/
;
;----------
;        приемник потока
;
; seg_adr:    .ds 2 ; адрес сегмента
; lin_adr:    .ds 2 ; линейный адрес
; boot_adr:   .ds 2 ; передаточный адрес-дублер первого адреса
;                ; первой записи в принимаемом *.xeh файле
;                ; boot_adr=L, boot_adr+1=H
; map_adr:    .ds 2 ; текущий адрес загрузки в строке
;                ; map_adr=L,map_adr+1=H
; cnt_byts:   .ds 1 ; счетчик байт данных в строке
; cb_total:   .ds 1 ; контрольная сумма
; h_tetras:   .ds 1 ; старшая тетрада преобразователя пары
;                ; символов ASCII в бинарный байт
; tmp_rx:     .ds 1 ; времянка хранения принятого байта
; step_ptr:   .ds 2 ; указатель адреса следующего программного
;                ; субблока обработки приемника бутлоадера
;                ; step_ptr=L,step_ptr+1=H
; strg_ptr:   .ds 2 ; указатель начального адреса строки символов
;                ; передатчика rs232 (бутлоадера) общий ресурс
;                ; strg_ptr=L,strg_ptr+1=H
; ctp_tx:     .ds 1 ; позиционное смещение в строке
;                ; символов передатчика rs232 (бутлоадера)
;                ; общий ресурс
;
;----------
;
; таблица обьявленных имен - секция флагов пользователя
; /во вложенных файлах данная область добавляется
; в конец области основных определений
; заголовочного файла/
;
; name: .dbit <expr>
;
;  .BSEG ; /at adres/
; ap_fill:  .dbit 1 ; статус ожидания начала файла\начального
;                   ; адреса размещения данных
; preof_ldr: .dbit 1 ; предварительное объявление конца файла
; eof_ldr:  .dbit 1 ; отметка "достигнут конец файла"
; eof_txd:  .dbit 1 ; флаг "передача строки символов завершена"
; glob_er:  .dbit 1 ; флаг "обнаружена ошибка"
; в настоящей версии флаги заменены выводом строк - сообщений
; на консоль терминала ПК
; er_ks:    .dbit 1 ; имела место ошибка контрольной суммы в любой из записей
;                  ; (передаточный во внешние модули)
; er_mark:  .dbit 1 ; имела место ошибка приёма
;                  ; "нарушение последовательности управляющих символов"
; er_tmo:   .dbit 1 ; имела место ошибка "тайм-аут разрва потока"
; er_type:  .dbit 1 ; имела место ошибка типа записи
;                  ; в файле (не 0х00 и не 0х01)
;
;----------
;
; в подпрограммах обработки прерываний по приему
; *.xeh файла используется текущий регистровый банк
; в следующем варианте интерпритации регистров
;
; R7=
; R6=
; R5=
; R4=
; R3=
; R2=
; R1=
; R0=
;
; также используется DPTR как указатель ячеек размещения данных
;
; исходно считается, что полная обработка строки из 16 байт должна
; быть завершена задолго до окончания приема следующего байта
; при скорости 9600 на полную обработку не более 0,001041666 S
; что равноценно примерно 800 машинным циклам /гарантированно/.
;
;----------
;
;
; прямой обработчик потока данных
;  допускаются краткие прерывания от
; системного генератора основной сетки частот
;
;
;----------
;
;
      .cseg
 bottle:
     clr ES ; прерывания по УАРТ запрещены
       push PSW
     push ACC
     push DPL
     push DPH
     mov step_ptr,#low kod_onstr ; указатель адреса субблока
     mov step_ptr+1,#high kod_onstr ; загружен
     setb ap_fill ; флаг ожидания начала файла\начального
                ; адреса размещения данных активирован
     clr preof_ldr ; сброс семафора эха для КС, '\r' и '\n'
     clr eof_ldr ; сброс флага отметки "достигнут конец файла"
     clr glob_er ; сброс флага "обнаружена ошибка"
     mov a,SBUF ; фиктивное чтение буфера данных УАРТ
     clr RI ; страховая очистка приемника
     setb REN ; прием разрешен
       ELL_OFF
 bottle_1:
     mov a,P3 ; нажатия S_IN
     jnb ACC.S_SCL,wait_endrx ; экстренный выход по кнопке
     jnb RI,bottle_1
     clr RI
     mov tmp_rx,SBUF
     clr RI ; RI=0
     mov SBUF,tmp_rx ; генерация эхо-ответа
     mov a,#low rebottl
     push ACC
     mov a,#high rebottl
     push ACC
     mov a,step_ptr
     push ACC
     mov a,step_ptr+1 ; адрес указанного в step_ptr
     push ACC ; программного сегмента загружен
     ret
 rebottl:
     jb glob_er,wait_endrx ; выход при обнаружении ошибки
     jb eof_ldr,wait_endrx ; выход при обнаружении завершения загрузки
     sjmp bottle_1
 wait_endrx:
     clr REN ; запрет приемника
     mov wtm1,#tm_ertmo ; загрузить интервал ожидания
              ; разрыва/прекращения потока
     clr wtm1_tic ; режим ожидания конца потока
       setb en_wtm1
 wait_drx:
     jbc wtm1_tic,alles_wt
     mov a,P3 ;
     jb ACC.0,wait_drx ; RXD=P3.0
     mov wtm1,#tm_ertmo
     sjmp wait_drx
 alles_wt:
     clr en_wtm1 ; счетчик wtm1 остановлен
     ELL_OFF
     pop DPH ; возврат из исполнителя программного сегмента
     pop DPL
     pop ACC
     pop PSW
     setb ES ; прерывания по УАРТ разрешены
    ret
;
;----------
;      субблок обработчика
;   кода символа начала строки
;
 kod_onstr:
       mov a,#start_kod
       xrl a,tmp_rx
       jnz rip_00
    mov step_ptr,#low kod_cnth ; указатель адреса следующего
    mov step_ptr+1,#high kod_cnth ; субблока загружен
    ELL_ON ; включить индикатор ELL
   ret ; возврат в точку вызова irq_RI
 rip_00:
      PRETEX str2 ; заготовка печати сообщения о типе ошибки
      setb glob_er ; флаг ошибки активирован
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа старшего полубайта
;     счетчика байт данных сторки
;
 kod_cnth:
       ASCII_HI
      mov step_ptr,#low kod_cntl ; указатель адреса следующего
      mov step_ptr+1,#high kod_cntl ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа младшего полубайта
;     счетчика байт данных сторки
;
 kod_cntl:
      ASCII_LO
      mov cnt_byts,a ; ячейка счетчика загружена
      mov cb_total,a ; начальное значение КС загружено
      mov step_ptr,#low kod_adrhh ; указатель адреса следующего
      mov step_ptr+1,#high kod_adrhh ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа старшего полубайта
; старшего байта указателя адреса размещения
;       байт данных сторки
;
 kod_adrhh:
      ASCII_HI
       mov step_ptr,#low kod_adrhl ; указатель адреса следующего
      mov step_ptr+1,#high kod_adrhl ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа младшего полубайта
; старшего байта указателя адреса размещения
;       байт данных сторки
;
 kod_adrhl:
       ASCII_LO
       mov map_adr+1,a ; старший байт текущего указателя адреса
       add a,cb_total
       mov cb_total,a ; обработка КС
       mov step_ptr,#low kod_adrlh ; указатель адреса следующего
      mov step_ptr+1,#high kod_adrlh ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа старшего полубайта
; младшего байта указателя адреса размещения
;       байт данных сторки
;
 kod_adrlh:
      ASCII_HI
       mov step_ptr,#low kod_adrll ; указатель адреса следующего
      mov step_ptr+1,#high kod_adrll ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа младшего полубайта
; младшего байта указателя адреса размещения
;       байт данных сторки
;
 kod_adrll:
       ASCII_LO
       mov map_adr,a ; старший байт текущего указателя адреса
       add a,cb_total
       mov cb_total,a ; обработка КС
       jnb ap_fill,no_dubl
       clr ap_fill ; сброс ловушки стартового адреса
       mov boot_adr,map_adr
       mov boot_adr+1,map_adr+1 ; грузим стартовый адрес
 no_dubl:
      mov step_ptr,#low kod_typeh ; указатель адреса следующего
     mov step_ptr+1,#high kod_typeh ; субблока загружен
    ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа старшего полубайта
;       кода типа строки
;
 kod_typeh:
        ASCII_HI
       mov step_ptr,#low kod_typel ; указатель адреса следующего
      mov step_ptr+1,#high kod_typel ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа младшего полубайта
;       кода типа строки
;
 kod_typel:
        ASCII_LO
        push ACC
        add a,cb_total
        mov cb_total,a ; обработка КС
        pop ACC
        jnz over_ldd ; если тип не 0, прверка на
                  ; допустимое иное значение
        mov DPL,map_adr
        mov DPH,map_adr+1 ; указатель размещения загружен
       mov step_ptr,#low kod_datah ; указатель адреса следующего
      mov step_ptr+1,#high kod_datah ; субблока загружен
     ret ; возврат в точку вызова irq_RI
 over_ldd:
        xrl a,#1 ; тип 1 - конец файла
        jnz error_type ; или анализ на другие типы (для АВР и др.)
        setb preof_ldr ; активирован флаг preeof_ldr
        mov step_ptr,#low kod_ksh ; указатель адреса следующего
      mov step_ptr+1,#high kod_ksh ; субблока загружен
     ret ; возврат в точку вызова irq_RI
 error_type:
      PRETEX str7 ; заготовка печати сообщения о типе ошибки
      setb glob_er ; флаг ошибки активирован
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа старшего полубайта
;      текущего байта данных
;
 kod_datah:
       ASCII_HI
       mov step_ptr,#low kod_datal ; указатель адреса следующего
      mov step_ptr+1,#high kod_datal ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа младшего полубайта
;      текущего байта данных
;
 kod_datal:
        ASCII_LO
        movx @dptr,a ; байт размещен в ВПД
        inc dptr ; указатель +1
        add a,cb_total
        mov cb_total,a ; обработка КС
        djnz cnt_byts,repit_ld
       mov step_ptr,#low kod_ksh ; указатель адреса следующего
      mov step_ptr+1,#high kod_ksh ; субблока загружен
     ret ; ajmp ret_proc_rx ; следующая КС
 repit_ld:
        mov step_ptr,#low kod_datah ; указатель адреса следующего
       mov step_ptr+1,#high kod_datah ; субблока загружен
     ret ; возврат в точку вызова irq_RI
        ; /продолжаем до исчерпания cnt_byts/
;----------
;      субблок обработчика
;   кода символа старшего полубайта
;      байта контрольной суммы
;
 kod_ksh:
        ASCII_HI
       mov step_ptr,#low kod_ksl ; указатель адреса следующего
      mov step_ptr+1,#high kod_ksl ; субблока загружен
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа младшего полубайта
;      байта контрольной суммы
;
 kod_ksl:
       ASCII_LO
       xch a,cb_total
       cpl a
       inc a
       xrl a,cb_total
       jnz error_ks
       mov step_ptr,#low kod_repk ; указатель адреса следующего
      mov step_ptr+1,#high kod_repk ; субблока загружен
     ret ; возврат в точку вызова irq_RI
 error_ks:
      PRETEX str1 ; заготовка печати сообщения о типе ошибки
      setb glob_er ; флаг ошибки активирован
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа "\r"
;
 kod_repk:
        mov a,#vk_kod
       xrl a,tmp_rx
       jnz rip_01
     mov step_ptr,#low kod_pps ; указатель адреса следующего
    mov step_ptr+1,#high kod_pps ; субблока загружен
   ret ; возврат в точку вызова irq_RI
 rip_01:
      PRETEX str2 ; заготовка печати сообщения о типе ошибки
      setb glob_er ; флаг ошибки активирован
     ret ; возврат в точку вызова irq_RI
;----------
;      субблок обработчика
;   кода символа "\n"
;
 kod_pps:
       mov a,#ps_kod
       xrl a,tmp_rx
       jnz rip_02
       jnb preof_ldr,rep_ldd
       setb eof_ldr ; для правильного эхо-дампа
       PRETEX str3 ; заготовка печати сообщения о завершении загрузки
     ret ; возврат в точку вызова irq_RI
 rep_ldd:
    mov step_ptr,#low kod_onstr ; указатель адреса следующего
    mov step_ptr+1,#high kod_onstr ; субблока загружен
   ret ; возврат в точку вызова irq_RI
 rip_02:
      PRETEX str2 ; заготовка печати сообщения о типе ошибки
      setb glob_er ; флаг ошибки активирован
     ret ; возврат в точку вызова irq_RI
;
;----------
;
; по выходу данные в ОЗУ ВПД\ВПП
; состояние флагов
;    ap_fill=0  статус ожидания начала файла\начального
;                      адреса размещения данных
;    eof_ldr=1\?  статус флага отметка "достигнут конец файла"
;    glob_er=?  статус флага "глобальная ошибка"
;
; стартовый адрес находится в
;  boot_addr+1:boot_addr
;
;----------
;
 asc_bin:
     mov a,tmp_rx ; читаем принятый полубайт
     jnb ACC.6,asc_h0 ; проверяем бит, соответствующий 4
               ; в старшей тетраде
     add a,#0x09 ; добавка для A-F
 asc_h0:
     anl a,#0x0F ; выделяем младшую тетраду старшего символа
   ret
;
;----------
; ********************************************
;
; блок передачи строки символов ASCII
; признак завершения строки - esc символ \0
;
;----------
;
; в подпрограммах обработки прерываний при передаче
; строки символов из ПЗУ
; используется текущий регистровый банк RB
; в следующем варианте интерпритации регистров
;
; R7= не определен
; R6= не определен
; R5= не определен
; R4= не определен
; R3= не определен
; R2= не определен
; R1= не определен
; R0= не определен
;
; также используется DPTR как указатель ячеек размещения данных
;
;----------
;
; поскольку первый символ передается ДО возникновения
; прерывания
; по RI\TI блок обработки выполнен как подпрограмма
; с независимым вызовом и возвратом
;
; инициализирующий вызов в точку prog_txd_init
; вход при прерывании по TXD в точку proс_txd
;
;----------
;
   .cseg
 proc_txd_init:
     clr eof_txd ; сброс флага "передача строки завершена"
     mov ctp_tx,#0 ; указатель смещения символа в строке = 0
 proc_txd:
    push PSW
    push ACC
    push DPH
    push DPL
    mov DPL,strg_ptr ;
    mov DPH,(strg_ptr+1) ;
    mov a,ctp_tx
    movc a,@a+dptr
    jnz stdtx ; в конце строки символов стоит \0 (0х00)
    setb eof_txd ; если обнаружено (0x00)
    sjmp end_stdtx ; завершаем работу с eof_txd=1
 stdtx:
    mov SBUF,a ; иначе очередной байт на передачу
    inc ctp_tx ;
 end_stdtx:
    pop DPL
    pop DPH
    pop ACC
    pop PSW
   ret
;
;
;----------
;

Поскольку простая обработка символа не требует таких "наворотов"
вроде свертки двух символов в один байт или получения адресной информации для позиционного размещения фрагмента по конкретному адресу ОЗУ/ПЗУ,
решение может быть гораздо проще, без излишних добавок.
:roll:

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

Пн ноя 18, 2019 09:10:35

А почему бы не сходу и "парсить" ?
Без предварительного буферного ввода ...
решение может быть гораздо проще, без излишних добавок.
:roll:

Это уже реализовано. Есть 2 режима: парсинг данных из UART на лету, и "просто положи в буфер, как будет время - выгребу". Успешное окончания парсинга в обработчике автоматом включает режим "положи в буфер". А уже из него выгребаю и анализирую "параметры", например уровень сигнала сети. Просто иногда параметров у одного ответа много, и чтобы после получения первого параметра опять не переключатся в режим парсинга в обработчике, проще продолжить прием в буфер, и потом найти там нужную последовательность.

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

Пн ноя 18, 2019 10:06:59

Тогда в принципе особо чего добавить...
остается в силе вариант сравнение-переход (cjne, xrl)
да еще вариант загрузки DPTR и temp_dph:temp_dpl...
Может есть смысл в макросе грузить не в DPTR, а в temp_dph:temp_dpl...
а затем использовать внутреннюю перегрузку уже в подпрограмме.
Тем более, что предыдущий DPTR все равно предпочтительно в стеке хранить при входе
(как АСС и PSW)... А затем восстанавливать при выходе из подпрограммки.
Или старт-адрес через стек передавать - но тогда сложнее содержимое стека при разных вариантах выхода отслеживать.
:roll:
И почти упустил...
При относительно небольшом "ассортименте" блоков сравнения можно попробовать
movc a,@a+pc вместо movc a,@a+dptr с передачей начального смещения...
:roll:

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

Пн июн 29, 2020 09:11:31

Доброго времени суток. Понадобилось использовать второй DPTR на AT89S52. Делаю вот так:
Код:
mov 0A2h,   #0   ; select DP0L, DP0H
mov DPL,  #'A'
mov 0A2h,   #1   ; select DP1L, DP1H
mov DPL,   #'B'
mov 0A2h,   #0   ; select DP0L, DP0H
mov SBUF,DPL

и не выходит каменный цветок. В UART шлется 'B', а не 'A'. Адрес регистра AUXR1, отвечающего за выбор DPTR, на карте памяти AT89S52 составляет 0A2h. За переключение отвечает младший (0) бит, который и переключаю (остальные биты не имеют значения, и всегда читаются как 1). Выводил в UART значение AUXR1 (0A2h) до, и после переключения - так оно меняется (либо 0FEh, либо 0FFh), но на выбор DPTR никак не влияет :dont_know:

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

Пн июн 29, 2020 09:35:24

Пока_без_кота писал(а):но на выбор DPTR никак не влияет
а где вы используете DPTR? в коде этого нет!
вы пишите в регистр DPTR данные, затем из этого регистра данные назад берете - что у вас должно выбраться?! что положили, то и взяли.

альтернатива из двух вариантов DPTR используется в командах типа mov a, @a+dptr - вот тут, в зависимости от выбранного DPTR, будет взяты данные по одному или другому адресу.

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

Пн июн 29, 2020 10:17:04

а где вы используете DPTR? в коде этого нет!
вы пишите в регистр DPTR данные, затем из этого регистра данные назад берете - что у вас должно выбраться?! что положили, то и взяли.

альтернатива из двух вариантов DPTR используется в командах типа mov a, @a+dptr - вот тут, в зависимости от выбранного DPTR, будет взяты данные по одному или другому адресу.

В приведенном коде этого действительно нет, но это я упрощал условия для проверки кода, который у меня не работает.
Предистория.
Подцепил я к AT89S52 внешнюю ОЗУ, и решил запилить библиотеку для работы с ней. Одной из функций библиотеки является копировании произвольного количества байт из одной области внешней ОЗУ в другую область внешнего ОЗУ. И вот тут мне понадобился второй DPTR (до этого как-то не приходилось его использовать).
"Функция" имеет вид макроса с передачей параметров:
Спойлер
Код:
_copy_XRAM_2_XRAM   macro   _source,_dest,_size
               orl      0A2h,   #00000001b                           ; select DP1L, DP1H
               mov      DPTR,   #_dest
               anl      0A2h,   #11111110b                           ; return DP0L, DP0H
               mov      DPTR,   #_source
               mov      xram_copy_size,_size
               call   Copy_XRAM_2_XRAM_routine
               endm

Copy_XRAM_2_XRAM_routine:
   movx   A,      @DPTR
   inc      DPTR
   orl      0A2h,   #00000001b                                       ; select DP1L, DP1H
   movx   @DPTR,   A
   inc      DPTR
   anl      0A2h,   #11111110b                                       ; return DP0L, DP0H
   djnz   xram_copy_size,Copy_XRAM_2_XRAM_routine
   ret

Согласно моей первоначальной логике, селектор DPTR должен был влиять на то, куда именно (в какую пару DPL/DPH) я буду писать значение при записи указателя в DPTR.

П.С. Благодарю. Переделал присвоение параметров-указателей следующий образом, и все заработало:
Код:
mov     DPL,#low(_source)
mov     DPH,#high(_source)
mov     DP1L,#low(_dest)
mov     DP1H,#high(_dest)

Получается, что команда mov всегда пишет в первый DPTR, а вот команда inc уже знает, с каким DPTR производить действие, в зависимости от состояния селектора.
Последний раз редактировалось Пока_без_кота Пн июн 29, 2020 10:57:07, всего редактировалось 4 раз(а).

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

Пн июн 29, 2020 10:51:46

Пока_без_кота писал(а):а вот команда inc уже знает, с каким DPTR производить действие, в зависимости от состояния селектора.
даже не так: все команды, работающие с DPTR (не частями, а целиком с 16-битным), учитывают заданный селектором регистр.

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

Пн июн 29, 2020 11:00:55

Селектор отвечает за то, с каким из DPTR будет проводиться действие команды, мнемоника которой включает в себя "DPTR".
Код:
movc a,@a+dptr
jmp @a+dptr
movx a,@dptr
movx @dptr,a
mov dptr,#d16  пока поставлю  ?
inc dptr

А вот когда загрузку указателей (содержимого) делаем в соответствующие регистры РСФ, там селектор ни при делах.
8)

Почему в макросе не сработало
mov dptr,#d16
надо повнимательнее посмотреть...
Как вариант - что-то не так с управлением селектором или ограничения по командам.
Вечерком чего гляну...
Хотя...
описание команд дает однозначность:
MOV
(DPTR)<--#DATA 15-0
DPH<-DPL<- #data 15-8 <- #data 7-0
т.е. можно предположить, что загрузка будет выполнена в DPH:DPL
Даташитку на МК только вечером просмотрю...
:roll:

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

Пн июн 29, 2020 12:54:53

Прошу прощения за дезинформацию. Все дело оказалось в задержках при работе с памятью. Использую тормозную советскую КР537РУ10, и просто когда переделывал передачу параметров под раздельное присваивание DPH/DPL - вставил отладочный вывод в UART, который и создал задержку, благодаря которой все заработало. Так что первоначальный вариант оказался тоже правильным, просто перед каждой записью в память добавил задержку по 80 мкс, и все взлетело.
Ответить