Вы находитесь на странице: 1из 5

Копирование массива данных, из заданного “сектора” 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 ; Конец программы.