Так работает любое контрольное устройство - независимо от содержания пакета результат контрольного отсчета и прилагаемого ключа-подписи всегда одинаков. А ежли имелась ошибка - будет и изменение результата.
Доброго времени суток. Внутри кода находится строка символов (массив вида 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 ; тут наша строка ; тут дальнейший код
А если передачу вести самостоятельной подпрограммой?
Т.е. основная программа идет сама по себе, а при необходимости пересылки запускаем подпрограмму обслуживания передатчика, которую привязываем к прервыанию и начальному адресу массива символов... А подпрограммка UARTа крутится самостоятельно пока не исчерпает содержимое массива...
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Это я знаю как сделать. Хочется именно "обходить" строку в коде, дабы иметь возможность ее объявление прямо на месте, в макросе, а не объявлять ее где-то на отшибе.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Так макрос может включать в себя строку и вызов подпрограммы обслуживания передатчика... Там просто вставляем текущий адрес начала строки равноценно таковому для любой области памяти.
Это вызов подпрограммы с передачей параметров через стек или через регистры ОЗУ. А в макросе остается только добавить переход для обхода участка символов строки. Примерно код.... вызов подпрограммы обслуживания передатчика с заданием параметра "начало строки" переход на метку "конец строки+1" начало строки: конец строки+1: продолжение кода...
Не понял. Можно увидеть код/псевдокод ? Под обработчиком UART имею ввиду прерывание UART с соответвующим кодом выборки и отправки строки (в текущей реализации все кроме первого символа, который отправляется из основного кода).
МММ... В принципе есть регистровая пара в которую помещается целевой адрес начала строки перед вызовом программы передачи. А программа передачи работает с данной регистровой парой как с текущим указателем чего отсылать. Чего мы в ту регистровую пару поместим - адрес из текущего кода или из отдельной области - значения не имеет - будет выполняться одинаково. Такой вариант у меня в КОТУИНКО биосе. Разбирать/вспоминать долго (ибо таки поднаворочено). Вот кусманчик передатчика: Спойлер
Код:
;---------- ; ******************************************** ; ; блок передачи строки символов 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 там поднакручено из-за особенностей вызова обработчика передатчика - сначала идет вызов как подпрограммы из кода, а затем дальнейшая обработка как прерывания до конца массива символов.
Доброго времени суток. Написал макрос поиска подстроки (из флеша) в строке (из ОЗУ). Покритикуйте и предложите лучше. Спойлер
Код:
_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
На первый взгляд... Разве что... Как элемент сравнения помимо вычитания попробовать cjne или xrl ... Да и в ОЗУ у 51-й не так уж много места для строк произвольного размера. Посему можно и прямой адрес задавать (не через косвенную адресацию) но при некоторой потере объема в ПЗУ. Есть смысл выделения буфера определенного размера в косвенноадресуемой области для 52-х (128+128 байт) там уже вариант работы через стек... Однако переносимость кода будет иметь ограничения. В принципе то уже подгонять под конкретную потребность надо.
И еще... Для единичного символа это подойдет (ловим первый встретившийся и далее, если совпадает последовательность). А вот для строки, содержащей пару одно/двух(и более) символьных повторов... Вида : контрстрока поймать в ней рок или более сложный двойной/многократный повтор одинакового фрагмента чуток поменьше контрольного фрагмента...
... Для единичного символа это подойдет (ловим первый встретившийся и далее, если совпадает последовательность). А вот для строки, содержащей пару одно/двух(и более) символьных повторов... Вида : контрстрока поймать в ней рок или более сложный двойной/многократный повтор одинакового фрагмента чуток поменьше контрольного фрагмента...
Скорее так: контрстрока поймать в ней тро Ну я для этого как раз флаг symbol_ok и ввел. Без него код был попроще, но например последовательность '123' в массиве '1121121123ХХХ' уже не ловилась, ибо первый сивол настоящей последовательности разпозначался как неправильный второй символ преполагаемой последовательности, и пропускался. Мне ответы на АТ-команды надо парсить, а там частенько такое встречается, что ответы началом похожи.
А почему бы не сходу и "парсить" ? Без предварительного буферного ввода. (Ессно буфер - накопитель полезной составляющей будет необходим). Единственно скорость обмена делать соответствующей. Я поток данных из *.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 ; ; ;---------- ;
Поскольку простая обработка символа не требует таких "наворотов" вроде свертки двух символов в один байт или получения адресной информации для позиционного размещения фрагмента по конкретному адресу ОЗУ/ПЗУ, решение может быть гораздо проще, без излишних добавок.
А почему бы не сходу и "парсить" ? Без предварительного буферного ввода ... решение может быть гораздо проще, без излишних добавок.
Это уже реализовано. Есть 2 режима: парсинг данных из UART на лету, и "просто положи в буфер, как будет время - выгребу". Успешное окончания парсинга в обработчике автоматом включает режим "положи в буфер". А уже из него выгребаю и анализирую "параметры", например уровень сигнала сети. Просто иногда параметров у одного ответа много, и чтобы после получения первого параметра опять не переключатся в режим парсинга в обработчике, проще продолжить прием в буфер, и потом найти там нужную последовательность.
Тогда в принципе особо чего добавить... остается в силе вариант сравнение-переход (cjne, xrl) да еще вариант загрузки DPTR и temp_dph:temp_dpl... Может есть смысл в макросе грузить не в DPTR, а в temp_dph:temp_dpl... а затем использовать внутреннюю перегрузку уже в подпрограмме. Тем более, что предыдущий DPTR все равно предпочтительно в стеке хранить при входе (как АСС и PSW)... А затем восстанавливать при выходе из подпрограммки. Или старт-адрес через стек передавать - но тогда сложнее содержимое стека при разных вариантах выхода отслеживать.
И почти упустил... При относительно небольшом "ассортименте" блоков сравнения можно попробовать movc a,@a+pc вместо movc a,@a+dptr с передачей начального смещения...
и не выходит каменный цветок. В UART шлется 'B', а не 'A'. Адрес регистра AUXR1, отвечающего за выбор DPTR, на карте памяти AT89S52 составляет 0A2h. За переключение отвечает младший (0) бит, который и переключаю (остальные биты не имеют значения, и всегда читаются как 1). Выводил в UART значение AUXR1 (0A2h) до, и после переключения - так оно меняется (либо 0FEh, либо 0FFh), но на выбор DPTR никак не влияет
а где вы используете DPTR? в коде этого нет! вы пишите в регистр DPTR данные, затем из этого регистра данные назад берете - что у вас должно выбраться?! что положили, то и взяли.
альтернатива из двух вариантов DPTR используется в командах типа mov a, @a+dptr - вот тут, в зависимости от выбранного DPTR, будет взяты данные по одному или другому адресу.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
а где вы используете DPTR? в коде этого нет! вы пишите в регистр DPTR данные, затем из этого регистра данные назад берете - что у вас должно выбраться?! что положили, то и взяли.
альтернатива из двух вариантов DPTR используется в командах типа mov a, @a+dptr - вот тут, в зависимости от выбранного DPTR, будет взяты данные по одному или другому адресу.
В приведенном коде этого действительно нет, но это я упрощал условия для проверки кода, который у меня не работает. Предистория. Подцепил я к AT89S52 внешнюю ОЗУ, и решил запилить библиотеку для работы с ней. Одной из функций библиотеки является копировании произвольного количества байт из одной области внешней ОЗУ в другую область внешнего ОЗУ. И вот тут мне понадобился второй DPTR (до этого как-то не приходилось его использовать). "Функция" имеет вид макроса с передачей параметров: Спойлер
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 всегда пишет в первый DPTR, а вот команда inc уже знает, с каким DPTR производить действие, в зависимости от состояния селектора.
Последний раз редактировалось Пока_без_кота Пн июн 29, 2020 10:57:07, всего редактировалось 4 раз(а).
А вот когда загрузку указателей (содержимого) делаем в соответствующие регистры РСФ, там селектор ни при делах.
Почему в макросе не сработало mov dptr,#d16 надо повнимательнее посмотреть... Как вариант - что-то не так с управлением селектором или ограничения по командам. Вечерком чего гляну... Хотя... описание команд дает однозначность: MOV (DPTR)<--#DATA 15-0 DPH<-DPL<- #data 15-8 <- #data 7-0 т.е. можно предположить, что загрузка будет выполнена в DPH:DPL Даташитку на МК только вечером просмотрю...
Прошу прощения за дезинформацию. Все дело оказалось в задержках при работе с памятью. Использую тормозную советскую КР537РУ10, и просто когда переделывал передачу параметров под раздельное присваивание DPH/DPL - вставил отладочный вывод в UART, который и создал задержку, благодаря которой все заработало. Так что первоначальный вариант оказался тоже правильным, просто перед каждой записью в память добавил задержку по 80 мкс, и все взлетело.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 27
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения