Копирование массива данных, из заданного “сектора” EEPROM-памяти данных, в
заданный “сектор” оперпамяти (“чтение-модификация-запись”), с использованием
косвенной адресации. “Затравка” предмета этого разговора “дислоцируется” в статье Подпрограммы EEPROM записи/чтения. А именно, “базис” (в приложении к PIC16F628/628A, но можно “привязаться” и к другим типам ПИКов): PIC16F628/628A 11 ПП потоковой, адресноинкрементной EEPROM-записи (с косвенной адресацией).
41 ПП потокового, адресноинкрементного EEPROM-чтения (с косвенной адресацией).
В этой же статье имеется и программа, посвящённая чтению-модификации-записи:
66 Для N-байтов данных (адресоинкремент, косвенная адресация).
В ней, массив, состоящий из 3-х байтов, копируется, из EEPROM-памяти данных, в
отображаемую область оперпамяти. А именно, в “шапкопрописанные” регистры общего назначения с названиями Reg_1, Reg_2 и Reg_3. Их количество можно нарастить, но во-первых, отображаемая область оперпамяти PIC16F628/628A (в частности) не резиновая и она очень ценна (обычно в ней “прописывают важняковые/ширпотребные” регистры), а во-вторых, если массив данных внушителен, то “замучаешься прописывать” (условно. “Шапка” будет “массивной”). На мой взгляд, целесообразно “состряпать” то, что имеет бОльшие возможности и одновременно, компактность. Особый интерес представляет копирование массива данных в неотображаемую область оперпамяти того банка, который “нравится” (условно). Если уж я ранее “привязался” к 1-му банку, то скопирую в него (из “сектора” EEPROM-памяти) массив, состоящий из 16-ти байтов (можно и больше/меньше, но пусть будет такое количество). Программная реализация этого “техзадания” выглядит так:
Для PIC16F628 / 628A
Вариант копирования массива данных, из заданного “сектора” EEPROM-памяти, в заданный “сектор” оперпамяти. ;*************************************************************************************************** ; Программа, позволяющая последовательно отследить (в симуляторе) процесс отработки процедуры ; “чтение-модификация-запись”, в приложении к копированию содержимого массива данных (таблицы ; данных), из заданного “сектора” EEPROM-памяти, в заданный “сектор” оперпамяти. ;*************************************************************************************************** LIST p=16f628A ; Используется PIC16F628A. #include <p16f628a.inc>; Подключение INC-файла PIC16F628A. errorlevel 2 ; Блокировка вывода сообщений, предупреждений ; (вывод только ошибок). __CONFIG 03F21H ; Защита выключена, WDT выключен, XT-генератор. ;---------------------------------------- ; "Прописка" регистров общего назначения. ;---------------------------------------- cblock 70h ; Назначение адреса первого регистра блока ; (в данном случае, содержимое оперячеек с адресами 70h..7Fh ; отображается во всех банках). Count ; Счётчик проходов. Reg ; Регистр оперсохранения текущих байтов, ; считанных из EEPROM-ячеек. endc ; Конец блока. ;----------------------------------------
; СОЗДАЁМ EEPROM-ТАБЛИЦУ, СОДЕРЖИМОЕ КОТОРОЙ ПОДЛЕЖИТ ДАЛЬНЕЙШЕЙ ОБРАБОТКЕ.
org 2100 ; На стадии "прошивки", записываем, в EEPROM-память de 0,1,2,3,4,5,6,7,8,9 ; (начиная от ячейки с адресом 00h), de 0A,0B,0C,0D,0E,0F ; этот массив данных. ;------------------------------------------------------------- ; Пояснение: в данном случае, таблица является 16-позиционной. ;-------------------------------------------------------------------------------------------------- org 0 ; Выполнение программы начинается c 0-го PC-адреса. ;***********************************************************************************************
; ТАБЛИЦА СОЗДАНА (теперь есть с чем работать). ПОСЛЕДОВАТЕЛЬНО СЧИТЫВАЕМ ЕЁ
; ДАННЫЕ (в регистр Reg), МОДИФИЦИРУЕМ ИХ (инкремент) И ЗАПИСЫВАЕМ РЕЗУЛЬТАТЫ ; МОДИФИКАЦИЙ В ЗАДАННЫЙ “СЕКТОР” ОПЕРПАМЯТИ 1-го БАНКА. ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; Последовательное чтение данных из массива EEPROM-ячеек с адресами 00h..0Fh, модификация считанного ; (инкремент), после чего осуществляется последовательное копирование (запись) модифицированных ; данных в массив оперячеек с адресами A0h..AFh (“лежат” в неотображаемой области 1-го банка). ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; Подготовительные операции. ;------------------------------------ movlw 0A0h ; Задание адреса первой ячейки опермассива movwf FSR ; (в данном случае, это оперячейка с адресом A0h). bsf STATUS,RP0 ; Так как регистры спецназначения EEADR,EECON1,EEDATA "лежат" ; в 1-м банке, то выбор 1-го банка (это для прямой адресации). movlw 0 ; Задание адреса первой ячейки EEPROM-массива. movwf EEADR ; (в данном случае, это EEPROM-ячейка с адресом 00h).
movlw .16 ; Задание количества
movwf Count ; позиций/строк таблицы. ;#################################################################################################### ; Циклическая ПП чтения-модификации-записи. ;#################################################################################################### SNOVA btfsc STATUS,Z ; Отработаны все циклы или не все ? <- ТОЧКА ОСТАНОВКИ №1 goto $ ; Если все, то “мертвяк”. <- ТОЧКА ОСТАНОВКИ №2 ; Если не все, то далее. ;---------------------------------------------------------------------------------------------------- ; Примечание: в данном случае, по причине применения “мертвяка”, отрабатывается один полный цикл ; программы, но если нужно выйти, из этой процедуры, по сценарию “программа исполняется далее”, ; то команду goto $ нужно заменить на команду goto <туда, куда нужно> (выход с 1-м банком). ;---------------------------------------------------------------------------------------------------- ; ЧИТАЕМ ДАННЫЕ ИЗ EEPROM-ПАМЯТИ ; Cчитывание содержимого текущей EEPROM-ячейки в регистр Reg ; (суть: оперсохранение считанных данных, с целью осуществления их дальнейшей модификации). ;------------------------------------------------------------------------------------------ bsf EECON1,RD ; Разрешение чтения. movf EEDATA,W ; EEDATA -> W movwf Reg ; W -> Reg ;-------------------------------------------------------------------------- ; МОДИФИЦИРУЕМ СЧИТАННОЕ ; Модификация (в данном случае, очень простая. Она может быть и посложнее). ;-------------------------------------------------------------------------- incf Reg,F ; Reg + 1 = ... (результат -> Reg) ;------------------------------------------------------------------------------------------- ; ЗАПИСЫВАЕМ РЕЗУЛЬТАТ МОДИФИКАЦИИ В ОПЕРПАМЯТЬ ; Запись ранее считанного (из EEPROM-ячейки) числа, в соответствующую оперячейку 1-го банка. ;------------------------------------------------------------------------------------------- movf Reg,W ; Ранее модифицированное, через W, movwf INDF ; записывается в текущую оперячейку 1-го банка. ;--------------------------------------------------------------------------------- ; Подготовка к следующему циклу чтения-модификации-записи и переход на его начало. ;--------------------------------------------------------------------------------- incf EEADR,F ; Адресноинкрементный выбор следующей EEPROM-ячейки. incf FSR,F ; Адресноинкрементный выбор следующей оперячейки. decf Count,F ; - 1 из счётчика проходов (команда decf воздействует на флаг Z). goto SNOVA ; Переход на начало следующего цикла. ;**************************************************************************************************** end ; Конец программы.
Как видите, программа достаточно компактна.
За счёт того, что EEPROM-таблица создана на стадии “прошивки” (см. концовку “шапки” программы), а не программно (см. программу с номером 11 статьи Подпрограммы EEPROM записи/чтения). Желающие “потренироваться” могут создать EEPROM-таблицу программно (советую. Дело полезное). Компактность достигается также и по причине отсутствия “прыжков”, из неотображаемой области оперпамяти одного банка, в неотображаемую область оперпамяти другого банка (и наоборот). То есть, состояние бита №7 указателя адреса (FSR) корректировать не нужно. Обратите внимание на это: org 2100 ; На стадии "прошивки", записываем, в EEPROM-память de 0,1,2,3,4,5,6,7,8,9 ; (начиная от ячейки с адресом 00h), de 0A,0B,0C,0D,0E,0F ; этот массив данных.
Увеличив значение 2100, можно изменить местоположение EEPROM-таблицы.
Например, если “настукать” 2105, то EEPROM-таблица начнётся не от ячейки с адресом 00h, а от ячейки с адресом 05h. Соответственно, в тексте программы, нужно скорректировать начальный EEPROM-адрес (заменить 0 на 5). Обратите внимание на то, что числа указаны без атрибутов систем счисления. Можно и так (один из возможных вариантов). Это не ошибка. В этом случае, MPLAB “автовоспринимает” их как шестнадцатеричные числа. В тексте программы, шестнадцатеричные числа не должны начинаться с буквы. Это ошибка. Если это так (MPLAB укажет), то слева нужно “прислонить” ноль (например, 0A5, 0FA и т.п.). Также обратите внимание на счётчик проходов. Так как речь идёт о работе в двух “епархиях”, то на первый взгляд, нужно применить 2 счётчика проходов. Можно и так, но зачем, ведь если хорошо подумать, то можно обойтись одним, универсальным (это что-то типа “2 в одном флаконе”), что и имеет место быть. И это удобно/комфортно, так как количество проходов задаётся одной цифрой (для обеих “епархий”), плюс, командноскоростной выигрыш (при прочих, равных условиях).
Копирование массива данных, из заданного “сектора” оперпамяти, в заданный
“сектор” EEPROM-памяти данных (“чтение-модификация-запись”), с использованием косвенной адресации. То есть, изменяем направление “перекачки данных” на противоположное (оперпамять EEPROM):
Для PIC16F628 / 628A
Вариант программной процедуры копирования массива оперданных в заданный “сектор” EEPROM-памяти. ;*************************************************************************************************** ; Программа, позволяющая последовательно отследить (в симуляторе) процесс отработки процедуры ; “чтение-модификация-запись”, в приложении к копированию содержимого массива оперданных (таблицы ; данных), в заданный “сектор” EEPROM-памяти. ;*************************************************************************************************** LIST p=16f628A ; Используется PIC16F628A. #include <p16f628a.inc>; Подключение INC-файла PIC16F628A. errorlevel 2 ; Блокировка вывода сообщений, предупреждений ; (вывод только ошибок). __CONFIG 03F21H ; Защита выключена, WDT выключен, XT-генератор. ;---------------------------------------- ; "Прописка" регистров общего назначения. ;---------------------------------------- cblock 70h ; Назначение адреса первого регистра блока ; (в данном случае, содержимое оперячеек с адресами 70h..7Fh ; отображается во всех банках). Count ; Счётчик проходов. Reg ; Регистр оперсохранения текущих байтов, ; считанных из оперячеек. endc ; Конец блока. ;------------------------------------ org 0 ; Выполнение программы начинается c 0-го PC-адреса. ;***********************************************************************************************
; СОЗДАЁМ ОПЕРТАБЛИЦУ, СОДЕРЖИМОЕ КОТОРОЙ ПОДЛЕЖИТ ДАЛЬНЕЙШЕЙ ОБРАБОТКЕ.
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; Предустановка регистров общего назначения 0-го банка, от ячейки с адресом 20h и до ячейки с адресом ; 2Fh (это 16 оперячеек), числами, которые отличны от 0. ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; Подготовительные операции. ;------------------------------------ movlw 20h ; Потоковая запись чисел начинается от оперячейки movwf FSR ; с адресом 20h (см. соответствующую карту оперпамяти). movlw .16 ; (.16=10h) В счётчик проходов (в “шапке” программы, ему movwf Count ; присвоено название Count) записывается количество оперячеек, ; содержимое которых подлежит предустановке. ;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ; Циклическая ПП предустановки. ;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC SNOVA movf Count,W ; Так как в случае ненулевого результата декремента счётчика ; проходов, в дальнейшем, задействуется не счётчик проходов, ; а аккумулятор, то содержимое счётчика проходов копируется в W ; (команда movf воздействует на флаг Z). btfsc STATUS,Z ; Отработаны все проходы или не все ? ; (Иными словами, предустановка закончена или нет ?) goto VIHOD ; Если все, то выход из <- ТОЧКА ОСТАНОВКИ №1 ; процедуры предустановки. ; Если не все, то далее (текущая предустановка продолжается). ;------------------------------------ ; Рабочее действие. ;------------------------------------ movwf INDF ; В текущую оперячейку записывается значение счётчика проходов. ;------------------------------------ incf FSR,F ; Адресный выбор следующей оперячейки. decf Count,F ; - 1 из счётчика проходов. goto SNOVA ; Переход на начало следующей предустановки.
; ТАБЛИЦА СОЗДАНА (теперь есть с чем работать). ПОСЛЕДОВАТЕЛЬНО СЧИТЫВАЕМ ЕЁ
; ДАННЫЕ (в регистр Reg), МОДИФИЦИРУЕМ ИХ (инкремент) И ЗАПИСЫВАЕМ РЕЗУЛЬТАТЫ ; МОДИФИКАЦИЙ В ЗАДАННЫЙ “СЕКТОР” EEPROM-памяти. ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; Последовательное чтение данных из массива оперячеек с адресами 20h..2Fh, модификация считанного ; (инкремент), после чего осуществляется последовательное копирование (запись) модифицированных ; данных в массив EEPROM-ячеек с адресами 00h..0Fh. ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; Подготовительные операции. ;------------------------------------ VIHOD movlw 20h ; Потоковое чтение ранее записанного начинается movwf FSR ; от оперячейки с адресом 20h. bsf STATUS,RP0 ; Так как регистры спецназначения EEADR,EEDATA,EECON1,EECON2 ; "лежат" в 1-м банке, то выбор 1-го банка. movlw 0 ; Задание адреса первой ячейки EEPROM-массива movwf EEADR ; (в данном случае, это EEPROM-ячейка с адресом 00h).
movlw .16 ; Задание количества
movwf Count ; позиций/строк таблицы.
bcf STATUS,Z ; Так как “влёт” в “нижележащую” проверку осуществляется с
; поднятым флагом Z (команды movlw и movwf не воздействуют на ; флаг Z), что блокирует исполнение “нижележащей” процедуры, ; то флаг Z опускается. ;#################################################################################################### ; Циклическая ПП чтения-модификации-записи. ;#################################################################################################### SNOVA_1 btfsc STATUS,Z ; Отработаны все проходы или не все ? goto $ ; Если все, то “мертвяк”. <- ТОЧКА ОСТАНОВКИ №2 ; Если не все, то далее. ;---------------------------------------------------------------------------------------------------- ; Примечание: в данном случае, по причине применения “мертвяка”, отрабатывается один полный цикл ; программы, но если нужно выйти, из этой процедуры, по сценарию “программа исполняется далее”, ; то команду goto $ нужно заменить на команду goto <туда, куда нужно> (выход с 1-м банком). ;---------------------------------------------------------------------------------------------------- ; ЧИТАЕМ ДАННЫЕ ИЗ ОПЕРПАМЯТИ ; Cчитывание содержимого текущей оперячейки в регистр Reg ; (суть: оперсохранение считанных данных, с целью осуществления их дальнейшей модификации). ;------------------------------------------------------------------------------------------ movf INDF,W ; Содержимое текущей оперячейки копируется в W movwf Reg ; W -> Reg ;-------------------------------------------------------------------------- ; МОДИФИЦИРУЕМ СЧИТАННОЕ ; Модификация (в данном случае, очень простая. Она может быть и посложнее). ;-------------------------------------------------------------------------- incf Reg,F ; Reg + 1 = ... (результат -> Reg) ;------------------------------------------------------ ; ЗАПИСЫВАЕМ РЕЗУЛЬТАТ МОДИФИКАЦИИ В EEPROM ; Запись байта в текущую EEPROM-ячейку. ;------------------------------------------------------ movf Reg,W ; Ранее модифицированное, через W, movwf EEDATA ; записывается в EEDATA. bsf EECON1,WREN ; "Глобальное" разрешение записи.
movlw 55h ; Обязательная
movwf EECON2 ; последовательность movlw 0AAh ; команд. movwf EECON2 ; ----“---- ;------------------------------------ ; Процедура записи. ;------------------------------------ bsf EECON1,WR ; "Запуск в работу" аппаратной процедуры записи. ;------------------------------------------------------------------ ; Пояснение: по окончании записи, бит WR аппаратно сбрасывается в 0 ; (блокировка "запуска в работу" аппаратной процедуры записи). ;------------------------------------------------------------------ btfsc EECON1,WR ; Запись завершена или нет? goto $-1 ; Если не завершена, то проверка производится снова. ; Если завершена, то выход из "плавающей" задержки. ;--------------------------------------------------------------------------------- ; Подготовка к следующему циклу чтения-модификации-записи и переход на его начало. ;--------------------------------------------------------------------------------- incf EEADR,F ; Адресноинкрементный выбор следующей EEPROM-ячейки. incf FSR,F ; Адресноинкрементный выбор следующей оперячейки. decf Count,F ; - 1 из счётчика проходов (команда decf воздействует на флаг Z). goto SNOVA_1 ; Переход на начало следующего цикла. ;**************************************************************************************************** end ; Конец программы.