;********************************************************************************
; 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-й банк.
;################################################################################
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-й банк.
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; МОДИФИКАЦИЯ (считанное число + 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.
7
Просто есть опасения в том, что, по первости, с непривычки, она, от такой
неожиданности (плюс, изначальная разбалансировка, слабая кормежка, не отработанная
координация движений и т.д.), завалиться может (на бок или еще как-то).
Баба Яга, не смотря на свою относительную лояльность к тому, что творится без нее
(дома редко бывает. Вся в своих авиаделах и иных заботах), тогда вообще тормозов
лишится (расшатанная психика. Старушка-то в годах).
И понять ее можно: прилетела передохнуть, а тут такой конфуз.
Кто хочешь рассверипеет.
Чего доброго, еще и Кащея Бессмертного позовет (ох и крут на расправу …).
Эти неприятности не нужны.
Но это не беда. Спорт - великое дело.
Слабые курьи ножки вполне можно потренировать (зависит от тренерских способностей
Ивана Дурака и ему подобных) и превратить их в выносливые куриные ножищи.
А вот после этого, можно вертеть и так, и сяк (и даже прыгать с места на место.
Только с возвратом).
И Баба Яга будет довольна такой голенастой, спортивной красотищей (она же есть
собственник жилья).
А если, втихаря, еще и динамомашину к этим ножищам пристроить (см. творческое
наследие Аркадия Райкина), то …
Мечтать пока не буду (вернее, буду, но в тайне). Жизнь покажет.
Пояснение: не смотря на достаточно высокую степень идиотизма вышележащих
рассуждений, в них заложено и вполне рациональное зерно.
Только в форме образов.
Нужен будет, например, циклоп, Змей Горыныч, почтальон Печкин, Герасим & Му-Му
и т.д. - нет проблем.
Будут. Лишь бы прошибло.
Кстати, это самый лучший способ недопущения студенческого сна на лекциях
(занудство и монотонность убаюкивают. Эквивалентно колыбельной) и обеспечения
высокой успеваемости, вплоть до процветания всей нации.
В случае игнорирования сказанного, получается стратегический конфуз (ляп).
Например, если привязаться к текущей теме, то можно сказать, что чтение и
модификация происходят, а записи в мозги (ради этого и затеян весь сыр-бор) не
происходит (или происходит, но через пень колоду. Короче, брак).
И за эту явную халтуру, в нашем прелюбопытнейшем царстве-государстве, платят
зарплаты и всяческие медальки дают???!!!
С точки зрения шабашников, это конечно прекрасно (классная кормушка), но у
остального народонаселения возникает короткий, хлесткий и незамысловатый вопрос:
"На фиг (извиняюсь за непарламентское выражение) они нужны"?
Сильные мира сего стыдливо на него не отвечают.
Так что, тайна сия велика есть (похлеще Бермудского треугольника) и можно только
гадать.
Отчасти поэтому, в нашей общей, коммунальной квартире, тараканов полно.
Но это к слову (накипело).
А теперь, на полном серьезе, "пройдусь" по полному циклу одного "оборота избушки".
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-й банк.
После этого, под 5-й байт, сигнал АСК вырабатываться не будет, так как, при наличии
пятерки в регистре Byte, будет осуществлен обход процедуры формирования отклика
ведущего.
При этом, под первые 4 принятых байта, сигнал АСК вырабатываться будет.
Таким образом, "I2C-правила игры", в части касающейся приема ведущим байтов
данных, соблюдены.
Что же касается передачи ведущим байтов данных, то, в соответствии с "I2C-
правилами игры", сигнал АСК должен вырабатываться ведомым под каждый принятый
им байт (что и имеет место быть).
Сигнал NO ACK, "в комплекте" со "Стопом", указывают на то, что текущий цикл
чтения закончен и можно начинать цикл записи.
Если, в конце цикла чтения (после приема последнего байта массива), вместо
сигнала NO ACK будет выработан сигнал АСК, то последующий цикл записи
будет "покоиться на кладбище".
9
Кто не верит, тот может проверить.
Переместите группу команд анализа количества принятых байтов на ее "старое"
место и полюбопытствуйте, произошла ли, после этого, запись или нет.
Теперь следует напомнить, что в регистре 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).
После отработки ПП записи - "мертвяк".
Занавес. "Концерт" закончен.
Если в дальнейшем появится весомый, жизненный повод развить эту тему, то будет "и
углубление, и расширение".
12