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

8/3.

Использование модуля MSSP м/контроллера PIC16F873A (режим ведущего)


для исполнения процедуры типа "чтение-модификация-запись"
(ведомый - м/схема памяти 24C64).

Теперь можно "сваять" что-то "комплексное".


То есть, нужно и прочитать, и записать, а заодно и "замодифицироваться", так как
жизнь есть жизнь, и от нее никуда не денешься.
"В переводе на русский", это означает то, что реально существует множество
устройств, внутри "ПИКожелезяк" которых осуществляется то, что называется
"процедурой чтения – модификации – записи".
Из названия понятен порядок действий.
Сначала нужно произвести чтение.
Читать буду содержимое первых 5-ти ячеек EEPROM памяти 24С64 (адреса 00h … 04h)
Естественно, что изначально, это содержимое нужно записать в упомянутые выше
ячейки (с помощью IcProg, PonyProg и т.п.).
Потом нужно произвести модификацию.
Я не стану особо мудрить (в данном случае, это неуместно. Важен принцип), а просто
прибавлю по единице к числовым значениям всех считанных байтов.
После этого, будет осуществлена запись получившегося "безобразия" в ячейки
EEPROM памяти 24С64 с адресами 08h … 0Ch.
А можно записать и "по верху" считанного (нет проблем), но ведь жизнь нужно как-то
разнообразить?
После всего этого - "стоп-машина" (запланированный "глюк").
Получилась вот такая "учебно – тренировочная" программа:

;********************************************************************************
; WR_RD.asm Использование модуля MSSP м/контроллера PIC16F873A
(режим ведущего) для исполнения процедуры типа
; "чтение-модификация-запись" (ведомый - м/схема 24C64)
; (учебная программа)
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах"
; (http://ikarab.narod.ru) karabea@Lipetsk.ru
;================================================================================
; Автор: И.Н.Шевченко (RW1ZK), г.Заозерск Мурманская обл.
; (PIC18F252, 24C16).
; Е.А.Корабельников: перевод c PIC18F252 на PIC16F873A, с 24С16 на 24С64
; и объяснение работы.
;================================================================================
; Из первых 5-ти ячеек 24С64 (адреса 00h...04h) считывается 5 байтов (чтение).
; К числовому значению каждого считанного байта прибавляется единица
; (модификация).
; Результат записывается в 5 ячеек 24С64 с адресами 08h...0Ch (запись).
; Линии SCL и SDA "подтянуты" к +5V через резисторы 4,7 Ком.
; Кварц 4 Мгц.
;================================================================================
; Функции выводов порта С:
; RC3 - линия SCL - вывод №6 24C64,
; RC4 - линия SDA - вывод №5 24C64,
; остальные выводы порта С не используются.
; Выводы портов А и В не используются.
;-----------------------------------------
; Объем программы: 103 команды.
;********************************************************************************
LIST p=16F873A ; Используется PIC16F873A.
__CONFIG 3F71h ; Включено: XT-генератор, PWRT, сброс BOR.
; Выключено: защита, WDT, LVP, DEBUG.
;================================================================================
; Регистры специального назначения.
;================================================================================
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.

1
IndF equ 00h ; Доступ к памяти через FSR.
FSR equ 04h ; Регистр косвенной адресации.
SSPStat equ 14h ; Регистр статуса модуля MSSP (банк 1).
SSPCon equ 14h ; Регистр управления модуля MSSP.
SSPCon2 equ 11h ; Регистр управления модуля MSSP (банк 1).
SSPAdd equ 13h ; Регистр управления скоростью обмена
; (банк 1).
SSPBuf equ 13h ; Регистр приемо-передающего буфера.
PIR1 equ 0Ch ; Регистр флагов прерываний
; от периферийных модулей.
;================================================================================
; Регистры общего назачения.
;================================================================================
Temp equ 20h ; Регистр временного хранения
; считанных байтов.
Byte equ 21h ; Счетчик байтов (он же - указатель адреса).
Temp1 equ 22h ; "Целевые"
Temp2 equ 23h ; регистры
Temp3 equ 24h ; оперативной
Temp4 equ 25h ; памяти.
Temp5 equ 26h ; ---"---
;================================================================================
; Присвоение битам названий.
;================================================================================
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
RP1 equ 6 ; Бит выбора банка.
SSPIF equ 3 ; Флаг прерывания от модуля MSSP.
SEN equ 0 ; Бит включения "Старта".
PEN equ 2 ; Бит включения "Стопа".
ACKSTAT equ 6 ; Бит подтверждения от ведомого.
SMP equ 7 ; Бит управления длительностью фронта.
RCEN equ 3 ; Бит разрешения/запрета приема.
ACKEN equ 4 ; Бит подтверждения ведущим приема байта.
;================================================================================
org 0 ; Начать выполнение программы
; с 0-го адреса PC.
;********************************************************************************

;********************************************************************************
; НАЧАЛО ПРОГРАММЫ.
;********************************************************************************
; Инициализация модуля MSSP (работа по I2C, режим ведущего, скорость 100 Кгц).
;================================================================================
; Все не задействованные модули отключены по умолчанию.
; Выводы всех портов, по умолчанию, работают на вход. По этой причине, не нужно
; подтверждать обязательную, в данном случае, настройку выводов RC3 (SCL) и
; RC4 (SDA) на работу "на вход".
; Все регистры SSP... , по умолчанию, сброшены в ноль. Прерывания запрещены.
; Обязательный, в данном случае, нулевой уровень отклика (сигнала АСК) на прием
; ПИКом байта, считанного из 24С64 (ACKDT=0), установлен по умолчанию.
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw 9 ; Установка стандартной скорости обмена:
movwf SSPAdd ; Fosc/{4*(SSPAdd+1)}=4Мгц/40=100 Кгц.
bsf SSPStat,SMP ; Управление длительностью фронта выключено,
; т.к. выбрана стандартная скорость
; (100 Кгц.).
bcf Status,RP0 ; Переход в 0-й банк.

clrf Byte ; Сброс счетчика байтов.


movlw b'00101000' ; Включение модуля MSSP (SSPEN=1),
movwf SSPCon ; в режиме I2C-ведущего (SSPM3..SSPM0=1000).

;################################################################################
2
; ЧТЕНИЕ БАЙТОВ ИЗ ЯЧЕЕК 24С64 С АДРЕСАМИ 00h ... 04h.
;################################################################################
; Формирование условия "START".
;================================================================================
call START ; Начало формирования условия "START".
;--->Возврат по стеку из ПП START
;================================================================================
; Передача режимного байта.
;================================================================================
movlw b'10100000' ; Передача режимного байта: 1010 - код
call WR_I2C ; функциональности, 000 - адрес м/схемы,
; 0 - режим записи.
;--->Возврат по стеку из ПП WR_I2C
;================================================================================
; Передача байтов адреса той ячейки 24C64, из которой будет считан 1-й байт
; массива. В данном случае, считывание начнется с 1-й ячейки (адрес 00h).
;================================================================================
movlw 0 ; Передача старшего
call WR_I2C ; байта адреса.
;--->Возврат по стеку из ПП WR_I2C
movlw 0 ; Передача младшего
call WR_I2C ; байта адреса.
;--->Возврат по стеку из ПП WR_I2C
;================================================================================
; Формирование условия "STOP".
;================================================================================
call STOP ; Начало формирования условия "STOP".
;--->Возврат по стеку из ПП STOP
;================================================================================
; Формирование условия "START".
;================================================================================
call START ; Начало формирования условия "START".
;--->Возврат по стеку из ПП START
;================================================================================
; Передача режимного байта.
;================================================================================
movlw b'10100001' ; Передача режимного байта: 1010 - код
call WR_I2C ; функциональности, 000 - адрес м/схемы,
; 1 - режим чтения.
;--->Возврат по стеку из ПП WR_I2C
;================================================================================
; ПП приема байта и формирования отклика ведущего на принятый байт.
;================================================================================
; Прием байта.
;-------------------------------------
RD_I2C bsf Status,RP0 ; Переход в 1-й банк.
bsf SSPCon2,RCEN ; Разрешение приема текущего байта
; от 24С64 (начало приема).
bcf Status,RP0 ; Переход в 0-й банк.

bcf PIR1,SSPIF ; Сброс флага перерываний от модуля MSSP.

btfss PIR1,SSPIF ; Прием текущего байта завершен или нет?


goto $-1 ; Если нет, то ожидание.
; Если завершен, то принятый байт аппаратно
; копируется в SSPBuf и программа
; исполняется далее.
movf SSPBuf,W ; Копирование принятого байта
movwf Temp ; из SSPBuf в Temp.
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Принятый байт "лежит" в регистре Temp.
; Номер принятого байта задается числом, "лежащим" в регистре Byte.
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Анализ количества принятых байтов.
;----------------------------------------------------
movlw 5 ; Задание количества принятых байтов.
3
subwf Byte,W ; Byte - 5 = ...
btfsc Status,Z ; Считаны все 5 байтов или не все?
goto FINAL ; Если все, то ACK не формируется (NO ACK)
; и чтение заканчивается.
; Если не все, то программа
; исполняется далее.
;----------------------------------------------------
; Формирование отклика ведущего.
;----------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
bsf SSPCon2,ACKEN ; Формирование подтверждения (АСК)
; принятого байта.
bcf Status,RP0 ; Переход в 0-й банк.

bcf PIR1,SSPIF ; Сброс флага перерываний от модуля MSSP.

btfss PIR1,SSPIF ; 9-й импульс закончился или нет?


goto $-1 ; Если нет, то ожидание.
; Если закончился, то программа
; исполняется далее.

;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; МОДИФИКАЦИЯ (считанное число + 1).
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
incf Temp,F ; Temp + 1 = ...
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; "Целевое" распределение текущих байтов по регистрам Temp1 ... Temp5.
;================================================================================
movf Byte,W ; Подготовка к вычисляемому переходу.
;------------------------------------------------------
; Распределение байтов с помощью вычисляемого перехода.
;------------------------------------------------------
addwf PC,F ; Приращение PC на величину W.
goto METKA_1 ; 1-й сценарий.
goto METKA_2 ; 2-й сценарий.
goto METKA_3 ; 3-й сценарий.
goto METKA_4 ; 4-й сценарий.
;------------------------------------
movf Temp,W ; 5-й сценарий.
movwf Temp5 ; Temp --> Temp5.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_1 movf Temp,W ;
movwf Temp1 ; Temp --> Temp1.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_2 movf Temp,W ;
movwf Temp2 ; Temp --> Temp2.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_3 movf Temp,W ;
movwf Temp3 ; Temp --> Temp3.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_4 movf Temp,W ;
movwf Temp4 ; Temp --> Temp4.
; "Все пути ведут в Рим".
;----------------------------------------------------
; Подготовка к обработке следующего байта.
;----------------------------------------------------
PLUS1 incf Byte,F ; Byte + 1 = номер/адрес текущего байта.
goto RD_I2C ; Переход на начало обработки
; следующего байта.
;================================================================================
; Формирование условия "STOP".
;================================================================================
4
FINAL call STOP ; Начало формирования условия "STOP".
;--->Возврат по стеку из ПП STOP
;################################################################################

; Сюда можно "врезать продукт" разнообразнейшего творчества


; (зависит от интеллектуальной изворотливости и "дерзалки"/"хотелки").

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; ЗАПИСЬ РЕЗУЛЬТАТА МОДИФИКАЦИИ В ЯЧЕЙКИ 24С64 С АДРЕСАМИ 08h ... 0Сh.
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; Формирование условия "START".
;================================================================================
call START ; Начало формирования условия "START".
;--->Возврат по стеку из ПП START
;================================================================================
; Передача режимного байта.
;================================================================================
movlw b'10100000' ; Передача режимного байта: 1010 - код
call WR_I2C ; функциональности, 000 - адрес м/схемы,
; 0 - режим записи.
;--->Возврат по стеку из ПП WR_I2C
;================================================================================
; Передача байтов адреса той ячейки 24C64, в которую будет записан 1-й байт
; массива. В данном случае, запись начнется с ячейки с адресом 08h.
;================================================================================
movlw 0 ; Передача старшего
call WR_I2C ; байта адреса.
;--->Возврат по стеку из ПП WR_I2C
movlw 8 ; Передача младшего
call WR_I2C ; байта адреса.
;--->Возврат по стеку из ПП WR_I2C
;================================================================================
; Запись массива байтов в 24С64.
;================================================================================
; Стандартная процедура косвенной адресации.
;-------------------------------------------
movlw 5 ; Задание количества
movwf Byte ; записываемых байтов.
movlw Temp1 ; Сначала передается байт, "лежащий" в
movwf FSR ; Temp_1, а за ним, в порядке увеличения
SNOVA movf IndF,W ; числового значения адреса, и все остальные.
call WR_I2C ; Запись в 24C64 текущего байта данных.
;--->Возврат по стеку из ПП WR_I2C
incf FSR,F ; FSR + 1 = ...
decfsz Byte,F ; Записаны все байты данных или не все ?
goto SNOVA ; Если не все, то переход на запись
; следующего байта.
; Если все, то программа исполняется далее.
;================================================================================
; Формирование условия "STOP".
;================================================================================
call STOP ; Начало формирования условия "STOP".
;--->Возврат по стеку из ПП STOP
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; "Закончен бал, погасли свечи".
;------------------------------------
goto $ ; "Вечное, мертвое кольцо" (вместо него
; может быть продолжение программы).

;********************************************************************************
; Подпрограммы, которые вызываются командой call.
;********************************************************************************
; ПП передачи байта и анализа отклика ведомого.
;================================================================================
POVTOR bcf Status,RP0 ; Переход в 0-й банк.
5
WR_I2C movwf SSPBuf ; Загрузка буфера байтом любой
; функциональности
; (начало передачи текущего байта).
bcf PIR1,SSPIF ; Сброс флага перерываний от модуля MSSP.

btfss PIR1,SSPIF ; Передача текущего байта завершена или нет?


goto $-1 ; Если нет, то ожидание.
; Если завершено, то программа
; исполняется далее.
;------------------------------------
; Анализ отклика ведомого.
;------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
btfsc SSPCon2,ACKSTAT; Подтверждение от ведомого (ACK)
; принято или нет?
goto POVTOR ; Если нет, то повтор передачи
; текущего байта.
bcf Status,RP0 ; Если есть, то переход в 0-й банк,
return ; после чего - возврат по стеку.
;================================================================================
; ПП формирования условия "START".
;================================================================================
START bcf PIR1,SSPIF ; Сброс флага перерываний от модуля MSSP.

bsf Status,RP0 ; Переход в 1-й банк.


bsf SSPCon2,SEN ; Начало формирования условия "START".
bcf Status,RP0 ; Переход в 0-й банк.

btfss PIR1,SSPIF ; Формирование условия "START" завершено


; или нет?
goto $-1 ; Если нет, то ожидание.
; Если завершено, то программа
; исполняется далее.
return ; Возврат по стеку.
;================================================================================
; ПП формирования условия "STOP".
;================================================================================
STOP bcf PIR1,SSPIF ; Сброс флага перерываний от модуля MSSP.

bsf Status,RP0 ; Переход в 1-й банк.


bsf SSPCon2,PEN ; Начало формирования условия "STOP".
bcf Status,RP0 ; Переход в 0-й банк.

btfss PIR1,SSPIF ; Формирование условия "STOP" завершено


; или нет?
goto $-1 ; Если нет, то ожидание.
; Если завершено, то программа
; исполняется далее.
return ; Возврат по стеку.
;********************************************************************************
end ; Конец программы.

Принципиальная схема устройства под эту программу находится в подразделе 8/1.


Программа "собрана" по принципу "крупнопанельного домостроения".
Но в отличие от "хрущевок", с качеством "домостроения" все в полном порядке.
В данном, неказистом случае, получилась "избушка" (место проживания трех поросят,
Бабы Яги и прочих), а не "дворец", но ничто не мешает построить и "дворец", ведь
"крупнопанелек"-то (кстати, качественных. Буржуи озаботились) можно использовать
какое угодно количество, плюс, можно "перетасовать их как колоду карт" (прикиньте
количество комбинаций).
Лишь бы "архитектор/дизайнер лаптем щи не хлебал" (не подкачал).
Но прежде чем строить "дворец", нужно "руку набить на избушке", а иначе откуда
взяться знаниям и опыту?
Вот такая получается банальная банальность (очень уставшая истина).
6
Вывод: "дворцы дворцами, а избушки нужно уважать".
Так же, как и родителей.
Голос из-за кулис: " Ты еще про Адама с Евой вспомни. Хватит языком трепать.
Ближе к избушке (тьфу ты, - к делу). Железяку давай без всяких родителей и соплей".
Сейчас дам.
Специально, из-за принципа, выдам духовитый русский дух (кавычки - в сторону. Что
естественно, то не безобразно).

Нужно отметить, что у вышеупомянутой избушки нет какого-то выдающегося


фундамента.
Его заменяют курьи ножки (чувствуете, куда ветер дует? Если чувствуете, то с Вашим
детством было все в порядке).
Проще говоря, рассматриваемая программа является, в некотором роде,
универсальной.
Всем русским (и не только) людям доподлинно известно, что избушка, имеющая такую
интересную и интригующую конструкцию, может повернуться к лесу хоть передом, хоть
задом, хоть под углом в 45 (и т.д.) градусов (сальто – мортале, правда делать не
может, но научить можно).
В первую очередь, это зависит от убедительности и грамотности командования.
В части касающейся этого командования, на мой русский взгляд, эталоном является
всем известный, но не смотря на это, очень таинственный и исключительно
колоритный Иванушка Дурачек.
Любят у нас умных людей хаять (это от недалекого ума). Какой же он дурак?
Во-первых, сам себе на уме, а во-вторых, технарь чистейшей воды (от Бога), хоть и
академий не заканчивал.
Только замаскированный, так как придуривается.
И с этим ничего не поделаешь - последствия менталитета, в виде специфической
защитной реакции (условный рефлекс) на агрессивность внешней среды, которая не
менее, а даже и более придурковата, чем вышеупомянутый Иван Дурак (с волками
жить - по волчьи выть).
Поэтому и юмористов/клоунов/и т.п. у нас чуть ли не больше, чем во всем остальном
мире (никто не говорит, что это плохо, но немного странновато).
Изначально, имеет место быть случай типа "по умолчанию" (окна à на север).
Проще говоря, избушка на курьих ножках находится в режиме ожидания Ивана Дурака.
(SCL = SDA = 1).
Вопрос: "Где отыскать Ивана Дурака, и когда он примется за свое дурацкое, куриное
дело"?
Ответ: на мой взгляд, по некоторым параметрам, я смогу его, хоть и частично, но
все-таки заменить (безумно горжусь).
За дело берусь сразу же.
Задача: нужно плавненько (чтобы сооружение не завалилось. Ножки-то - курьи. Посуду
перебъешь - Баба Яга отплатит пакостью) развернуть избушку на 180 градусов, и
причем так, чтобы к концу этого разворота, байты данных, лежащие в ячейках
EEPROM памяти 24С64 с адресами 00h … 04h, были скопированы в регистры
оперативной памяти Temp1 … Temp5, а впоследствии и модифицированы путем
прибавления единиц к числовым значениям этих байтов.
То есть, на данном этапе, речь идет о чтении и модификации.
После того, как это дело будет сделано, нужно так же плавненько довернуть избушку
еще на 180 градусов, и причем так, чтобы к концу этого доворота, модифицированные
байты регистров Temp1 … Temp5 записались в ячейки EEPROM памяти 24С64 с
адресами 08h … 0Ch.
То есть, на этом этапе, речь идет о записи.
Таким образом, за один полный оборот избушки на курьих ножках вокруг своей оси,
последовательно отрабатываются процедуры чтения, модификации и записи, что, в
данном, немудреном случае, и есть один полный цикл программы.
Исходя из гуманных соображений избушколюбия, я не стал ее (избушку) заставлять
крутиться как пропеллер у самолета (крутанул только один раз).

7
Просто есть опасения в том, что, по первости, с непривычки, она, от такой
неожиданности (плюс, изначальная разбалансировка, слабая кормежка, не отработанная
координация движений и т.д.), завалиться может (на бок или еще как-то).
Баба Яга, не смотря на свою относительную лояльность к тому, что творится без нее
(дома редко бывает. Вся в своих авиаделах и иных заботах), тогда вообще тормозов
лишится (расшатанная психика. Старушка-то в годах).
И понять ее можно: прилетела передохнуть, а тут такой конфуз.
Кто хочешь рассверипеет.
Чего доброго, еще и Кащея Бессмертного позовет (ох и крут на расправу …).
Эти неприятности не нужны.
Но это не беда. Спорт - великое дело.
Слабые курьи ножки вполне можно потренировать (зависит от тренерских способностей
Ивана Дурака и ему подобных) и превратить их в выносливые куриные ножищи.
А вот после этого, можно вертеть и так, и сяк (и даже прыгать с места на место.
Только с возвратом).
И Баба Яга будет довольна такой голенастой, спортивной красотищей (она же есть
собственник жилья).
А если, втихаря, еще и динамомашину к этим ножищам пристроить (см. творческое
наследие Аркадия Райкина), то …
Мечтать пока не буду (вернее, буду, но в тайне). Жизнь покажет.
Пояснение: не смотря на достаточно высокую степень идиотизма вышележащих
рассуждений, в них заложено и вполне рациональное зерно.
Только в форме образов.
Нужен будет, например, циклоп, Змей Горыныч, почтальон Печкин, Герасим & Му-Му
и т.д. - нет проблем.
Будут. Лишь бы прошибло.
Кстати, это самый лучший способ недопущения студенческого сна на лекциях
(занудство и монотонность убаюкивают. Эквивалентно колыбельной) и обеспечения
высокой успеваемости, вплоть до процветания всей нации.
В случае игнорирования сказанного, получается стратегический конфуз (ляп).
Например, если привязаться к текущей теме, то можно сказать, что чтение и
модификация происходят, а записи в мозги (ради этого и затеян весь сыр-бор) не
происходит (или происходит, но через пень колоду. Короче, брак).
И за эту явную халтуру, в нашем прелюбопытнейшем царстве-государстве, платят
зарплаты и всяческие медальки дают???!!!
С точки зрения шабашников, это конечно прекрасно (классная кормушка), но у
остального народонаселения возникает короткий, хлесткий и незамысловатый вопрос:
"На фиг (извиняюсь за непарламентское выражение) они нужны"?
Сильные мира сего стыдливо на него не отвечают.
Так что, тайна сия велика есть (похлеще Бермудского треугольника) и можно только
гадать.
Отчасти поэтому, в нашей общей, коммунальной квартире, тараканов полно.
Но это к слову (накипело).
А теперь, на полном серьезе, "пройдусь" по полному циклу одного "оборота избушки".

Начиная с инициализации модуля MSSP и до окончания копирования, в регистр Temp,


считанного, из 24С64, байта, все то же самое, как и в предыдущем подразделе.
А вот дальше нужно кое-что пояснить.
В программе предыдущего подраздела, отклик ведущего на прием им байта (сигнал
АСК) формировался под каждый, принятый ведущим, байт.
В том числе и под последний, 5-й байт.
И это было вполне приемлемо, так как не было "дальнейшего развития событий".
То есть, имел место быть "мертвяк" (goto $), на котором все и заканчивалось.
В рассматриваемом же случае, имеется "дальнейшее развитие событий", и поэтому
"этот номер не пройдет"?
Вопрос: "Почему"?
Ответ: потому, что, в соответствии с "I2C-правилами игры", в конце цикла чтения,
должен иметь место быть так называемый сигнал NO ACK.

8
Проще говоря, после окончания приема ведущим последнего байта массива, ведущий
не должен вырабатывать сигнал АСК (формировать отклик).
Это и есть сигнал NO ACK.
Вопрос: "А если принимается только один байт? Как быть с сигналом АСК?"
Ответ: а никак. Просто не формировать.
Это соответствует формированию сигнала NO ACK.
В рассматриваемом случае, принимается 5 байтов.
Значит, под первые 4 байта, ведущий должен сформировать сигналы АСК, а под
последний, 5-й байт, он этого делать не должен.
Как это "дельце провернуть"?
А очень просто: нужно всего-навсего переместить группу команд анализа количества
принятых байтов немного выше.
Это Вы и видите:
........................
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Анализ количества принятых байтов.
;----------------------------------------------------
movlw 5 ; Задание количества принятых байтов.
subwf Byte,W ; Byte - 5 = ...
btfsc Status,Z ; Считаны все 5 байтов или не все?
goto FINAL ; Если все, то ACK не формируется (NO ACK)
; и чтение заканчивается.
; Если не все, то программа
; исполняется далее.
;----------------------------------------------------
; Формирование отклика ведущего.
;----------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
bsf SSPCon2,ACKEN ; Формирование подтверждения (АСК)
; принятого байта.
bcf Status,RP0 ; Переход в 0-й банк.

bcf PIR1,SSPIF ; Сброс флага перерываний от модуля MSSP.

btfss PIR1,SSPIF ; 9-й импульс закончился или нет?


goto $-1 ; Если нет, то ожидание.
; Если закончился, то программа
; исполняется далее.
Ранее, группа команд анализа количества принятых байтов находилась
здесь. Она перенесена выше.
........................
FINAL call STOP ; Начало формирования условия "STOP".
;--->Возврат по стеку из ПП STOP
;################################################################################

После этого, под 5-й байт, сигнал АСК вырабатываться не будет, так как, при наличии
пятерки в регистре Byte, будет осуществлен обход процедуры формирования отклика
ведущего.
При этом, под первые 4 принятых байта, сигнал АСК вырабатываться будет.
Таким образом, "I2C-правила игры", в части касающейся приема ведущим байтов
данных, соблюдены.
Что же касается передачи ведущим байтов данных, то, в соответствии с "I2C-
правилами игры", сигнал АСК должен вырабатываться ведомым под каждый принятый
им байт (что и имеет место быть).
Сигнал NO ACK, "в комплекте" со "Стопом", указывают на то, что текущий цикл
чтения закончен и можно начинать цикл записи.
Если, в конце цикла чтения (после приема последнего байта массива), вместо
сигнала NO ACK будет выработан сигнал АСК, то последующий цикл записи
будет "покоиться на кладбище".

9
Кто не верит, тот может проверить.
Переместите группу команд анализа количества принятых байтов на ее "старое"
место и полюбопытствуйте, произошла ли, после этого, запись или нет.

Итак, текущий байт принят и "лежит" в регистре Temp.


Далее происходит модификация (изменение) его содержимого:
........................
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; МОДИФИКАЦИЯ (считанное число + 1).
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
incf Temp,F ; Temp + 1 = ...
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
........................
В данном случае, она проста как мычание коровы, что, тем не менее, позволяет
"постичь глубинную суть".
Но вместо этой команды можно "врезать" целую процедуру, вплоть до "процедурищи"
(не путать с "дурой", находящейся на последней стадии моральной деградации) любой
сложности.

Теперь следует напомнить, что в регистре Temp "лежит" текущий байт, который
"рождается" на каждом из 5-ти "витков" внутреннего цикла ПП приема.
Поэтому, в целях сохранения "добытого тяжким и непосильным трудом", нужно
переписать его содержимое в один из регистров Temp1 … Temp5.
В какой именно?
Это зависит от порядкового номера "добытого" байта.
Этим делом "заведует" регистр Byte.
........................
;================================================================================
; "Целевое" распределение текущих байтов по регистрам Temp1 ... Temp5.
;================================================================================
movf Byte,W ; Подготовка к вычисляемому переходу.
;------------------------------------------------------
; Распределение байтов с помощью вычисляемого перехода.
;------------------------------------------------------
addwf PC,F ; Приращение PC на величину W.
goto METKA_1 ; 1-й сценарий.
goto METKA_2 ; 2-й сценарий.
goto METKA_3 ; 3-й сценарий.
goto METKA_4 ; 4-й сценарий.
;------------------------------------
movf Temp,W ; 5-й сценарий.
movwf Temp5 ; Temp --> Temp5.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_1 movf Temp,W ;
movwf Temp1 ; Temp --> Temp1.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_2 movf Temp,W ;
movwf Temp2 ; Temp --> Temp2.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_3 movf Temp,W ;
movwf Temp3 ; Temp --> Temp3.
goto PLUS1 ; "Все пути ведут в Рим".
;------------------------------------
METKA_4 movf Temp,W ;
movwf Temp4 ; Temp --> Temp4.
; "Все пути ведут в Рим".
;----------------------------------------------------
; Подготовка к обработке следующего байта.
;----------------------------------------------------
10
PLUS1 incf Byte,F ; Byte + 1 = номер/адрес текущего байта.
goto RD_I2C ; Переход на начало обработки
; следующего байта.
;================================================================================
; Формирование условия "STOP".
;================================================================================
........................
Организован 5-сценарный вычисляемый переход.
В зависимости от числового значения байта регистра Byte (от 00h до 04h), происходит
отработка одного из 5-ти аналогичных друг другу сценариев.
Разница только в выборе того или иного регистра Temp…
После отработки любого из этих сценариев, происходит приращение содержимого
регистра Byte и переход на "добывание" следующего байта данных.
На 5-м "витке" внутреннего цикла, все 5 считанных байтов "залягут" именно в те
регистры Temp…, в которых они и должны "залечь" (произошло распределение
принятых байтов).
Дело сделано.
Теперь нужно "штатно" закончить процедуру чтения, и так же "штатно" начать
процедуру записи.
То есть, нужно "состряпать Стоп/Старт".
Примечание: в "промежуток" между "Стопом" и "Стартом" можно "врезать" какую-нибудь
"нужность" (любой сложности), но в данном случае, эта "нужность" не нужна.
Начинается ПП записи.
Она просто "бессовестно передрана" из подраздела 8/1.
Поэтому добавить нечего, за исключением того, что осуществлена смена адреса (в
младший байт адреса записано число 8).
После отработки ПП записи - "мертвяк".
Занавес. "Концерт" закончен.

По-моему, ничего суперсложного, во всем этом "крупнопанельном домостроении", нет, а


польза - явная (все-таки Хрущев был далеко не глуп).
Нужно только знать/соблюдать "I2C-правила игры" и уметь работать с модулем MSSP.
Плюс, грамотная стратегия и наличие хотя бы одной извилины.
Если учесть, что "крупнопанели" качественные, то вообще получается "красота/ляпота".
Аж душа радуется.
Буржуи буржуями, а дело свое они разумеют.
Хотя, кто знает?
Например, сидит в Селиконовой долине член сообщества Иванов Дураков и делает
умные дела, а эти ушлые ребята тут как тут.
С ложкой (а может быть даже с половником).
Кто будет утверждать, что это бред?

Итак, в части касающейся модуля MSSP, "база" сформирована.


То, что осталось "за забором", относится либо к режиму ведомого, либо к делам,
связанным с "разруливанием непонимаек" в случае возникновения конфликтов, которые
возможны при работе с большим количеством ведущих/ведомых (интерфейс SPI в
расчет не беру).
Я ориентировался на наиболее востребованное.
То есть, имеется ведомый, работающий по интерфейсу I2C, а ПИК им "рулит".
В этом случае, нужно только учесть конкретную специфику ведомого ("конструкцию"
режимного байта, количество и "конструкцию" байтов адреса) и "адаптировать"
программу под нее.
Но в любом случае, "I2C-правила игры" остаются неизменными, и об этом всегда
нужно помнить.
Теперь несколько слов по поводу "аппаратных дел".
В модуле MSSP есть эффект буферизации.
По своей сути, он такой же, как и в модуле USART.
"Все что шевелится" внутри модуля MSSP, синхронизируется.
11
Это позволяет, в широком диапазоне скоростей, автоматически (аппаратно) обеспечить
необходимые, для нормальной работы, фазовые соотношения сигналов на линиях SCL
и SDA.
Числовое значение содержимого регистра SSPAdd определяет скорость обмена.
Скорость обмена определяется продолжительностью "прохождения" одного бита.
Этот интервал времени формирует генератор скорости обмена (BRG).
Он представляет собой 7-разрядный вычитающий счетчик с предустановкой.
Предустанавливаются младшие 7 битов регистра SSPAdd (вот Вам и "вышележащая"
зависимость).
Эта предустановка может осуществляться как программно (например, при программном
"запуске в работу" аппаратных процедур), так и аппаратно (в ходе отработки
аппаратных процедур).
Сразу же после каждой предустановки, начинается счет в сторону нуля.
При достижении нуля, генератор скорости обмена останавливается и ждет следующей
предустановки (программной или аппаратной).
Так как числовое значение предустановки одно и то же (то, которое задано), то будут
отмеряться одинаковые интервалы времени фиксированной продолжительности.
Из "кучи" таких интервалов формируется и цикл передачи, и цикл приема.
Какие именно уровни будут сформированы во время "прохождения" этих интервалов -
зависит от аппаратного алгоритма работы модуля MSSP, заданного разработчиками.
По большому счету, пользователю этим чудом техники вовсе не обязательно знать
этот алгоритм, ведь его не изменишь.
Пользователю нужно только знать, в какой момент и каким "рубильником программно
клацнуть".
Это тоже алгоритм, но относительно простой.
Остальное сделает "железяка".
Другое дело, когда такого помощника нет и приходится, в полном объеме, составлять
программный алгоритм работы по интерфейсу I2C (аппаратных "поблажек" - ноль).
Эта работа и была проделана в 1-м разделе.
Теперь Вы можете сравнить одно с другим.
Совершенно понятно, что модуль MSSP вне конкуренции.
Означает ли это то, что в 1-м разделе имеет место быть "занятие ерундой"?
Не в коем разе, так как от этого зависит качество и класс работы.
Плюс, олимпийское спокойствие и уверенность в своих силах (здоровая психика), что,
согласитесь со мной, важно.
Человеку прошедшему "горнило" 1-го раздела, модуль MSSP покажется "легкой
прогулкой по бульвару".
Конечно я утрирую. Легких прогулок в нашем деле нет (какие бульвары? Джунгли
кругом и крокодилы попадаются), но смысл, я надеюсь, понятен.

Если в дальнейшем появится весомый, жизненный повод развить эту тему, то будет "и
углубление, и расширение".

Выражаю свою признательность Шевченко Ивану за помощь в написании этого


раздела.

"Практикум по конструированию устройств на PIC контроллерах"      http://ikarab.narod.ru       E-mail: karabea@lipetsk.ru

12