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

3/2.

Организация чтения массива байтов по адресному запросу и чтения массива


байтов от текущего адреса. Комплексное чтение. Общий итог по чтению.

При "въезде" в эту тему, используется то же проверочное устройство, принципиальная схема


которого опубликована в предыдущем подразделе. Никаких его переделок не
требуется.
А вот теперь пришла пора разобраться с тем, что называется сигналом АСК,
вырабатываемым "мастером" (вырабатывается только при непосредственном
считывании байтов данных из 24С64А) и ответить на вопрос: "Зачем он вообще
нужен"?
По аналогии с сигналом АСК, вырабатываемым "помощником", логично предположить,
что сигналом АСК, вырабатываемым "мастером", будет являться все тот же нулевой
уровень на линии SDA, но вырабатываемый не "помощником", а "мастером".
В соответствии с этим предположением, нулевой уровень, вырабатываемый
"мастером" на линии SDA, в интервале времени между окончанием чтения одного
байта данных и стоп-условием (см. программу Read_1.asm или рис. 3 предыдущего
подраздела), является сигналом АСК.
Но есть одно "но".
Куда, при чтении одного байта данных, подевался импульс 9-го такта?
Забегая вперед, скажу, что это именно то, что в технической документации
"зашифровано" как NO ACK.
NO ACK означает то, что, по окончании считывания, из ячеек EEPROM памяти 24Схх,
байта/байтов данных, "мастер" должен выставить на линии SDA нулевой уровень
сигнала АСК, но импульса 9-го такта под него сформировано быть не должно.
Почему такие строгости?
А если сформировать (то есть, застробировать нулевой уровень на линии SDA)?
После экспериментальной проверки, выясняется то, что, если завершить процедуру
чтения "полноценным" АСК (то есть, на линии SDA, "мастер" сначала выставляет
нулевой уровень, а затем вырабатывает под него импульс 9-го такта), то последующее
чтение от текущего адреса (если в этом есть необходимость) становится не
возможным ("жесточайший глюк" с "мертвым зависанием").
В принципе, если в программе не используется чтение от текущего адреса, то можно
формировать импульс 9-го такта под все сигналы АСК, выдаваемые в линию SDA
"мастером", но зачем "испытывать судьбу" экономя всего на 4-х командах?
При помощи этих команд как раз и организуется проверка типа "это последний
считываемый байт или нет"?
Если это не последний считываемый байт, то импульс 9-го такта, под сигнал АСК,
вырабатывается ("полноценный" сигнал АСК без NO), а если последний, то не
вырабатывается (NO ACK).
С учетом сказанного, должно быть понятно, что "полноценный" сигнал АСК должен
формироваться во всех "промежутках" между, считываемыми из EEPROM памяти
24Схх, байтами данных, а после считывания последнего байта, для обеспечения
возможности последующего чтения от текущего адреса, "мастер" должен
сформировать сигнал NO ACK.
Итак, что получается?
В основном, получается "красота", за исключением понятийного "бардальеро", на
которое я ранее уже ругался: после считывания любого байта данных, сигнал АСК,
вырабатываемый "мастером", по факту, есть (на линии SDA), и, как бы, одновременно,
его нет (в случае NO ACK).
Лично я, считаю, что составители технической документации, в этом случае, вольно
или не вольно, создали совершенно не нужные и вредные, понятийные сложности
("кочки на ровном месте").
Хотя бы "расшифровали" как следует, но этого нет и, поневоле, приходится прибегать к
помощи "лома практики".
В части касающейся процедуры чтения (без учета подготовки к чтению), я бы,
упрощенно, "расшифровал" сигнал АСК, как "нулевой уровень на линии SDA c
импульсом 9-го такта", а сигнал NO ACK, как "нулевой уровень на линии SDA без
импульса 9-го такта".
Пусть, может быть, и длинновато, но зато более-менее понятно.
1
А то ведь, по факту, получается что-то типа "вражеской агентуры", которую, "с потом и
кровью", нужно "выявлять" и "сажать на нары".
Это и есть суровое и трудное, "даташитное счастье", постичь которое может только
человек с задатками шпиона - разведчика, работающего на вражеской территории (все
остальные - "под колпаком у Мюллера").
Итак, в "промежутках" между считываемыми байтами данных, импульс 9-го такта
стробирует нулевой уровень, ранее установленный на линии SDA, что и есть
разрешение автоинкремента счетчика адреса 24Схх.
После этого, в триггеры внутреннего, сдвигового регистра, с входов его предустановки,
будет переписан следующий байт данных, и начиная с тактового импульса №1, этот
байт, побитно, будет выводиться в линию SDA. И т.д.
Все. Баста!
И не нужно "бабушку лохматить" (это я Задорного вспомнил) по поводу какой-то
"крутой миссии" сигнала АСК, вырабатываемого "мастером".
Все очень просто: "мастер", в конце полного цикла ПП приема байта, "тупо" ("в
автомате") выдает "комплект", состоящий из нулевого уровня на линии SDA и
стробирующего его импульса на линии SCL (или без него, если байт последний).
Слухи о том, что этот сигнал АСК является "контролером" безошибочности считывания
байта, как говорится, сильно преувеличены.
Почему?
А потому, что нет соответствующего критерия.
При таком "раскладе", его и не может быть, так как критерием является всего-лишь
полная отработка программной процедуры считывания одного байта данных, которая
"привязана" к "делам, творящимся внутри 24С64А" только посредством простейшего
анализа состояния линии SDA, с последующей перезаписью в бит С состояния линии
SDA (в том числе и ошибочного, если это имеет место быть), и не более того.
Сигнал АСК, вырабатываемый "мастером", нужен только для того, чтобы, после
окончания считывания текущего байта данных, подготовить "помощника" к выводу на
линию SDA следующего байта данных.
Ну и "по совместительству", формируется "временной зазор" между соседними,
считываемыми байтами данных.
Если, при чтении, и возникнет ошибка, связанная с тем, что числовое значение
считанного байта не соответствует требуемому, то эта ошибка не будет влиять на
числовые значения байтов, считываемых позднее, то есть, ошибка локализуется
внутри одного байта.
Дешево и сердито (и “бабушка не взлохмачена”).
В этом случае, разработчики "выезжают" на технологии, в комплексе с продуманной
схемотехникой, и нужно признать, что это им удалось, так как считывание, в
абсолютном большинстве случаев, происходит без ошибок.
Может возникнуть вопрос о конкретных функциях стробов импульса 9-го такта,
формируемого под сигнал АСК.
Ответ: да какая разница? Процессы в 24С64А могут запускаться и передним стробом,
и задним, и обеими. На суть это не влияет.
Пусть этой конкретикой "забивают себе головы" разработчики.
Я же, в данном случае, буду оперировать более расширенным (чем строб) понятием -
импульс 9-го такта.
После всех этих рассуждений, можно заняться практическим делом.
Вашему вниманию предлагается учебная программа потокового чтения, из EEPROM
памяти 24С64А, 16-ти байтов данных, с названием Read_2.asm.
Изменив соответствующую константу (.16), можно изменить и количество считываемых
байтов.

;********************************************************************************
; Read_2.asm ЧТЕНИЕ ИЗ 24С64А МАССИВА БАЙТОВ ДАННЫХ (учебная программа).
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах".
; Автор: Корабельников Евгений Александрович
; http://ikarab.narod.ru karabea@lipetsk.ru
; Эта программа входит в состав 2-го подраздела 3-го раздела.
;********************************************************************************
2
; "Мастер" - PIC16F84A.
; "Помощник" - 24C64A.
; Кнопка пуска чтения подключена к выводу RA0.
; Светодиод (индицирует конец цикла чтения) подключен к выводу RA1.
; Вывод RA2 подключен к линии такта (SCL).
; Вывод RA3 подключен к линии данных (SDA).
; Порт В задействован под индикацию числового значения считанного байта
; в двоичном, весовом коде (светодиод активен - 1, не активен - 0).
; Кварц 4 Мгц. (1м.ц.=1мкс.).
; Объем программы: 98 команд.
;********************************************************************************
LIST p=16F84A ; Установка типа микроконтроллера.
__CONFIG 03FF5H ; Бит защиты выключен, WDT включен,
; стандартный XT - генератор.
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
OptionR equ 01h ; Регистр OptionR - 1-й банк.
Status equ 03h ; Регистр Status.
TrisA equ 05h ; Регистр TrisA - 1-й банк.
TrisB equ 06h ; Регистр TrisB - 1-й банк.
PortA equ 05h ; Регистр управления защелками порта A.
PortB equ 06h ; Регистр управления защелками порта В.
;================================================================================
; Определение названий и положения регистров общего назначения.
;================================================================================
Temp equ 0Ch ; Регистр обработки данных.
Count_Bit equ 0Dh ; Счетчик битов байта.
Read equ 0Eh ; Регистр обработки данных при чтении байта.
Count_Bait equ 0Fh ; Счетчик количества считываемых байтов.
SecL equ 10h ; Младший разряд счетчика паузы.
SecH equ 11h ; Старший разряд счетчика паузы.
;================================================================================
; "Привязка" названий битов регистров специального назначения к номерам битов.
;================================================================================
RP0 equ 5 ; Бит выбора банка.
C equ 0 ; Бит флага переноса-заёма.
SCL equ 2 ; Бит регистра PortA, который формирует такт.
SDA equ 3 ; Бит регистра PortA, который формирует данные
Z equ 2 ; Бит флага нулевого результата.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
F equ 1 ; Результат направить в регистр.
W equ 0 ; Результат направить в аккумулятор.
;================================================================================
org 0 ; Начать выполнение программы с нулевого
; адреса PC.
;********************************************************************************

;********************************************************************************
; "РАБОЧАЯ ЧАСТЬ" ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'00000001' ; RA0 (к нему подключена кнопка) работает "на
movwf TrisA ; вход", остальные RA... работают на выход.
clrf TrisB ; Все RB... работают на выход.
movlw b'11111101' ; Предделитель с Кдел.=32 подключен к WDT,
movwf OptionR ; подтягивающие резисторы порта В отключены.
bcf Status,RP0 ; Переход в 0-й банк.

movlw b'00001100' ; На линиях SDA и SCL выставляются единицы,


movwf PortA ; светодиод погашен.
clrf PortB ; "Гашение" светодиодов, подключенных к
3
; RB0...7.
movlw .16 ; Запись в регистр Count_Bait количества
movwf Count_Bait ; байтов, считываемых из EEPROM памяти.
;---------------------------------------------------------
; Ожидание нажатия кнопки.
;---------------------------------------------------------
KNOPKA_NO clrwdt ; Сброс WDT.
btfsc PortA,0 ; Если кнопка отжата, то уход в
goto KNOPKA_NO ; "вечное кольцо" ПП KNOPKA_NO.
; Если кнопка нажата, то программа
; исполняется далее.
;********************************************************************************
; ПРОЦЕДУРА ЧТЕНИЯ
;********************************************************************************
; Формирование старт-условия.
;================================================================================
bcf PortA,SDA ; SDA=0.
bcf PortA,SCL ; SCL=0.
;================================================================================
; "Администраторская" ПП (без названия), "рулящая" очередностью обработки байтов.
;================================================================================
; Задание числового значения режимного байта (для записи).
;---------------------------------------------------------
movlw B'10100000' ; Запись в регистр Temp режимного байта (1010-
movwf Temp ; код функциональности, 000–адрес м/схемы,
; 0–режим записи).
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;---------------------------------------------------------
; Задание числового значения старшего байта адреса.
;---------------------------------------------------------
movlw .0 ; Запись в регистр Temp
movwf Temp ; старшего байта адреса.
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;---------------------------------------------------------
; Задание числового значения младшего байта адреса.
;---------------------------------------------------------
movlw .0 ; Запись в регистр Temp
movwf Temp ; младшего байта адреса.
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;================================================================================
; Формирование стоп-условия.
;================================================================================
bcf PortA,SDA ; SDA=0.
bsf PortA,SCL ; SCL=1.
bsf PortA,SDA ; SDA=1.
nop ; Задержка на 1 м.ц.
;================================================================================
; Формирование старт-условия.
;================================================================================
bcf PortA,SDA ; SDA=0.
bcf PortA,SCL ; SCL=0.
;---------------------------------------------------------
; Задание числового значения режимного байта (для чтения).
;---------------------------------------------------------
movlw B'10100001' ; Запись в регистр Temp режимного байта (1010-
movwf Temp ; код функциональности, 000–адрес м/схемы,
; 1–режим чтения).
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
4
;********************************************************************************
; Подпрограмма приема байта (без названия. Можно как-нибудь назвать).
;********************************************************************************
SNOVA_2 movlw .8 ; Запись в счетчик битов количества
movwf Count_Bit ; битов в одном байте.

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


bsf TrisA,SDA ; Вывод SDA работает на вход.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Прием текущего бита.
;================================================================================
SNOVA_1 bcf Status,C ; Сброс в 0 флага переноса-заема (С).

bsf PortA,SCL ; SCL=1

btfsc PortA,SDA ; На линии SDA 0 или 1?


bsf Status,C ; Если 1, то С=1.
bcf PortA,SCL ; Если 0, то С=0 (см. выше), а SCL=0.

rlf Read,F ; Циклический сдвиг влево. Этим обеспечивается


; обработка битов байта, начиная с бита
; старшего разряда (№7...№0).
decfsz Count_Bit,F ; Декремент счетчика битов (Count_Bit-1=...).
goto SNOVA_1 ; Если результат не=0, то переход на чтение
; следующего бита.
;================================================================================
; Формирование сигнала АСК (вырабатывает "мастер").
;================================================================================
; Начало формирования сигнала АСК.
;-----------------------------------------------------
bcf PortA,SDA ; SDA=0

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


bcf TrisA,SDA ; Вывод SDA работает на выход.
bcf Status,RP0 ; Переход в 0-й банк.
;-----------------------------------------------------
; Формирование импульса 9-го такта под сигнал АСК.
;-----------------------------------------------------
movlw .1 ; Анализ содержимого счетчика байтов,
subwf Count_Bait,W; с целью формирования сигнала NO ACK
btfsc Status,Z ; после считывания последнего байта.
goto $+4 ; Если байт не последний, то переход
; на команду movf Read,W.
bsf PortA,SCL ; SCL=1
nop ; Задержка на 1 м.ц.
bcf PortA,SCL ; SCL=0
;================================================================================
; Вывод считанного байта в PortB (на индикацию).
;================================================================================
movf Read,W ; Вывод считанного байта (через регистр W) на
movwf PortB ; индикацию (на светодиоды, подключенные к
; RB0...7).
;================================================================================
; Задержка на 261629 м.ц.
;================================================================================
movlw .255 ;
movwf SecL ;
movlw .255 ;
movwf SecH ; Стандартный, 2-байтный
WR clrwdt ; вычитающий счетчик с
decfsz SecL,F ; "врезкой" в него
goto WR ; команды clrwdt.
decfsz SecH,F ;
goto WR ;
;------------------------------------------------------
5
; Декремент содержимого счетчика считываемых байтов.
;------------------------------------------------------
decfsz Count_Bait,F; Декремент с ветвлением.
goto SNOVA_2 ; Если результат не=0, то читается следующий
; байт.
; Если результат =0, то программа исполняется
; далее.
;================================================================================
; Формирование стоп-условия.
;================================================================================
bsf PortA,SCL ; SCL=1.
bsf PortA,SDA ; SDA=1.
;================================================================================
; Завершение полного цикла программы.
;================================================================================
bsf PortA,1 ; "Загорание" светодиода окончания чтения.
clrwdt ; Сброс WDT.
goto $-1 ; Уход в "мертвое", "вечное кольцо" до
; выключения и последующего включения питания.
;********************************************************************************
; Подпрограмма передачи байта.
;********************************************************************************
BAIT_WR movlw .8 ; Запись в счетчик битов количества
movwf Count_Bit ; битов в одном байте.
;================================================================================
; Передача текущего бита
;================================================================================
SNOVA rlf Temp,F ; Циклический сдвиг влево. Этим обеспечивается
; обработка битов байта, начиная с бита
;старшего разряда (№7...№0).
bcf PortA,SDA ; SDA=0.

btfsc Status,C ; Что "ушло" в бит С?


bsf PortA,SDA ; Если в бите С 1, то SDA=1.
bsf PortA,SCL ; SCL=1. (Если в бите С 0, то предыдущая
; команда не исполняется. Вместо нее –
; "виртуальный" NOP).
bcf PortA,SCL ; SCL=0.
decfsz Count_Bit,F ; Декремент счетчика битов (Count_Bit-1=...).
goto SNOVA ; Если результат не=0, то переход на обработку
; следующего бита.
;********************************************************************************
; Группа команд формирования импульса 9-го такта и анализа состояний флага АСК.
;********************************************************************************
; Начало формирования импульса 9-го такта.
;--------------------------------------------------------------------------------
bsf PortA,SCL ; Формируется строб (перепад от 0 к 1)
; импульса 9-го такта.
;--------------------------------------------------------------------------------
; Подготовка к анализу состояний флага АСК (перестройка направления работы
; вывода RA3).
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
bsf TrisA,SDA ; Вывод SDA работает на вход.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Анализ состояний флага АСК ("плавающая" задержка).
;================================================================================
ACK btfsc PortA,SDA ; На линии SDA 0 или 1 ?
goto ACK ; Если 1, то снова анализ (задержка до
; появления 0).
;--------------------------------------------------------------------------------
; Конец формирования импульса 9-го такта.
;--------------------------------------------------------------------------------
bcf PortA,SCL ; Если 0, то формируется спад импульса
; 9-го такта.
6
;--------------------------------------------------------------------------------
; Обратная перестройка направления работы вывода RA3.
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
bcf TrisA,SDA ; Вывод SDA работает на выход.
bcf Status,RP0 ; Переход в 0-й банк.
return ; Возврат по стеку в "администраторскую" ПП.
;********************************************************************************
end ; Конец программы.

Программа Read_2.asm является "дочерью" программы Read_1.asm.


Поэтому, объясню только специфику.
Количество считываемых байтов "поставлено на счетчик".
Соответственно, организован счетчик байтов на основе регистра общего назначения с
названием Count_Bait.
В подготовительных операциях ПП Start (это "виртуальное" название, так как явного
названия нет), в регистр Count_Bait записывается константа, числовое значение
которой определяет количество считываемых байтов.
В данном случае, считывается 16 байтов, но это количество может быть и иным.
Если нужно считать количество байтов большее, чем максимальное числовое
значение одного байта, то нужно организовать 2-х разрядный счетчик количества
считываемых байтов.
В этом случае, по максимуму, можно считать весь объем памяти 24С64А (а также и
других 24Схх).
После считывания 1-го байта, "мастер" вырабатывает "полноценный" (с импульсом 9-го
такта) сигнал АСК, после чего, считанный байт, "лежащий" в регистре Read, выводится
на индикацию в линейку светодиодов, подключенных к выводам порта В.
Для того чтобы обеспечить удобный, визуальный контроль выведенного на индикацию
(считанного) числа, нужна задержка, иначе смена показаний будет осуществляться
очень быстро.
Для обеспечения этого удобства, и нужна фиксированная задержка (см. текст
программы).
В данном случае, с целью задействования, в счетчике задержки, всего 2-х (а не 3-х)
регистров общего назначения, я выставил константы по максимуму (.255) и увеличил
внутренний цикл ПП задержки на 1 м.ц. путем "врезки" в этот цикл команды clrwdt
(совместил "приятное с полезным").
Получилось 261629 м.ц.
Если Вы захотите увеличить интервал времени между сменой показаний, то нужно
либо увеличить значение внутреннего цикла ПП задержки путем "врезки" в него
NOPов, clrwdt или goto $+1, либо организовать 3-х разрядный счетчик.
Обращаю Ваше внимание на то, что эта задержка не является обязательным
элементом процедуры чтения. Она является "элементом визуального удобства".
Далее происходит декремент содержимого счетчика считываемых байтов (decfsz
Count_Bait,F) и переход на начало процедуры считывания следующего байта (goto
SNOVA_2).
Далее все повторяется снова, до тех пор, пока, из 24С64А, не считается (и не будет
выведен на индикацию) последний, 16-й, байт данных.
После этого - "стоп машина".
Ниже Вы видите "разрисовку" сказанного, в части касающейся перехода к считыванию
следующего байта.

7
На этой картинке Вы видите импульс 9-го такта, о котором шла речь выше.
Между передним его стробом и следующим, передним стробом импульса 1-го такта,
транзистор оконечного каскада АСК, аппаратными средствами 24С64А, закрывается
для того, чтобы ноль сигнала АСК, на линии SDA, определялся только "мастером".
После прохождения импульса 9-го такта, счетчик адреса 24С64А будет
автоинкрементирован и содержимое следующей ячейки памяти будет записано в
триггеры внутреннего, сдвигового регистра.
По переднему стробу тактового импульса №1, на линии SDA, будет выставлен бит №7
следующего считываемого байта, затем, через 1 м.ц. произойдет определение его
значения (0 или 1) и т.д. (в соответствии со сказанным в предыдущем подразделе).
Точно то же самое будет происходить и на любом "стыке" между считываемыми
байтами.
Процедура завершения считывания массива байтов будет выглядеть так:

Как видите, в соответствии со сказанным выше, после считывания, из памяти 24С64А,


последнего байта данных, "мастер" не вырабатывает импульс 9-го такта.
Выполнение этого алгоритма обеспечивается группой из 4-х команд, входящих в
состав группы команд формирования сигнала АСК.
Принцип работы этих 4-х команд очень прост: если в регистре счетчика байтов
Count_Bait "лежит" число, отличное от 1, то импульс 9-го такта вырабатывается, а если
это число =1, то происходит "скачек" (обход) рабочей точки программы через группу
команд формирования импульса 9-го такта (то есть, он не вырабатывается).
Теперь о том, что нужно, предварительно, записать в первые 16 ячеек памяти 24С64А
в ПониПроге.
Я писал:
01 02 04 08 10 20 40 80 40 20 10 08 04 02 01 00
8
В этом случае, при считывании, в линейке светодиодов, будет что-то типа "бегущего огня".
Можно придумать и что-то другое.
Хотите "цветомузыку"?
Запишите в 24С64А какой нибудь HEX файл (например, той же программы
Read_2.asm).
Хотите подольше "насладиться этим зрелищем"?
Увеличьте значение константы количества считываемых байтов.
Хотите еще дольше?
Запишите в память 24С64А какой-нибудь "массивный" HEX файл и увеличьте до 2-х
разрядность счетчика считываемых байтов.
Кстати, в темноте, получаются очень любопытные визуальные эффекты, повторения
которых практически не заметно.
Если у Вас есть ребенок, то можете сделать для него такую "игрушку".
Пошли дальше.
Теперь устраиваю "крутые разборки" с чтением от текущего адреса.
Не нужно большого ума, чтобы понять, что, прежде чем организовывать чтение от
текущего адреса, нужно заранее просчитать текущий адрес, от которого должна
начаться эта разновидность чтения, иначе можно считать не то, что нужно.
В принципе, все это не так уж и сложно и зависит от специфики конкретной программы.
Сейчас я не буду "лезть в дебри", а покажу, как, сразу же после завершения потокового
чтения по адресному запросу, организуется потоковое чтение от текущего адреса.
Проверочное устройство - то же самое.
Программа называется Read_3.asm, и она является "дочерью" программы Read_2.asm
("цена вопроса" - всего 4 дополнительные команды).

;********************************************************************************
; Read_3.asm ЧТЕНИЕ ИЗ 24С64А НЕСКОЛЬКИХ МАССИВОВ БАЙТОВ ДАННЫХ
; (учебная программа)
; Сначала производится потоковое чтение по адресному запросу, а
; затем, потоковое чтение от текущего адреса.
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах".
; Автор: Корабельников Евгений Александрович
; http://ikarab.narod.ru karabea@lipetsk.ru
; Эта программа входит в состав 2-го подраздела 3-го раздела.
;********************************************************************************
; "Мастер" - PIC16F84A.
; "Помощник" - 24C64A.
; Кнопка пуска чтения подключена к выводу RA0.
; Светодиод (индицирует конец цикла чтения) подключен к выводу RA1.
; Вывод RA2 подключен к линии такта (SCL).
; Вывод RA3 подключен к линии данных (SDA).
; Порт В задействован под индикацию числового значения считанного байта
; в двоичном, весовом коде (светодиод активен - 1, не активен - 0).
; Кварц 4 Мгц. (1м.ц.=1мкс.).
; Объем программы: 102 команды.
;********************************************************************************
LIST p=16F84A ; Установка типа микроконтроллера.
__CONFIG 03FF5H ; Бит защиты выключен, WDT включен,
; стандартный XT - генератор.
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
OptionR equ 01h ; Регистр OptionR - 1-й банк.
Status equ 03h ; Регистр Status.
TrisA equ 05h ; Регистр TrisA - 1-й банк.
TrisB equ 06h ; Регистр TrisB - 1-й банк.
PortA equ 05h ; Регистр управления защелками порта A.
PortB equ 06h ; Регистр управления защелками порта В.
;================================================================================
; Определение названий и положения регистров общего назначения.
;================================================================================
Temp equ 0Ch ; Регистр обработки данных.
9
Count_Bit equ 0Dh ; Счетчик битов байта.
Read equ 0Eh ; Регистр обработки данных при чтении байта.
Count_Bait equ 0Fh ; Счетчик количества считываемых байтов.
SecL equ 10h ; Младший разряд счетчика паузы.
SecH equ 11h ; Старший разряд счетчика паузы.
Flag equ 12h ; Указатель чтения от текущего адреса.
;================================================================================
; "Привязка" названий битов регистров специального назначения к номерам битов.
;================================================================================
RP0 equ 5 ; Бит выбора банка.
C equ 0 ; Бит флага переноса-заёма.
SCL equ 2 ; Бит регистра PortA, который формирует такт.
SDA equ 3 ; Бит регистра PortA, который формирует данные
Z equ 2 ; Бит флага нулевого результата.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
F equ 1 ; Результат направить в регистр.
W equ 0 ; Результат направить в аккумулятор.
;================================================================================
org 0 ; Начать выполнение программы с нулевого
; адреса PC.
;********************************************************************************

;********************************************************************************
; "РАБОЧАЯ ЧАСТЬ" ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'00000001' ; RA0 (к нему подключена кнопка) работает "на
movwf TrisA ; вход", остальные RA... работают на выход.
clrf TrisB ; Все RB... работают на выход.
movlw b'11111101' ; Предделитель с Кдел.=32 подключен к WDT,
movwf OptionR ; подтягивающие резисторы порта В отключены.
bcf Status,RP0 ; Переход в 0-й банк.

movlw b'00001100' ; На линиях SDA и SCL выставляются единицы,


movwf PortA ; светодиод погашен.

clrf PortB ; "Гашение" светодиодов, подключенных к


; RB0...7.
movlw .2 ; Считываются 2 массива
movwf Flag ; по 16 байтов.
;---------------------------------------------------------
; Ожидание нажатия кнопки.
;---------------------------------------------------------
KNOPKA_NO clrwdt ; Сброс WDT.
btfsc PortA,0 ; Если кнопка отжата, то уход в
goto KNOPKA_NO ; "вечное кольцо" ПП KNOPKA_NO.
; Если кнопка нажата, то программа
; исполняется далее.
;********************************************************************************
; ПРОЦЕДУРА ЧТЕНИЯ
;********************************************************************************
; Формирование старт-условия.
;================================================================================
bcf PortA,SDA ; SDA=0.
bcf PortA,SCL ; SCL=0.
;================================================================================
; "Администраторская" ПП (без названия), "рулящая" очередностью обработки байтов.
;================================================================================
; Задание числового значения режимного байта (для записи).
;---------------------------------------------------------
movlw B'10100000' ; Запись в регистр Temp режимного байта (1010-
10
movwf Temp ; код функциональности, 000–адрес м/схемы,
; 0–режим записи).
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;---------------------------------------------------------
; Задание числового значения старшего байта адреса.
;---------------------------------------------------------
movlw .0 ; Запись в регистр Temp
movwf Temp ; старшего байта адреса.
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;---------------------------------------------------------
; Задание числового значения младшего байта адреса.
;---------------------------------------------------------
movlw .0 ; Запись в регистр Temp
movwf Temp ; младшего байта адреса.
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;================================================================================
; Формирование стоп-условия.
;================================================================================
bcf PortA,SDA ; SDA=0.
bsf PortA,SCL ; SCL=1.
bsf PortA,SDA ; SDA=1.
nop ; Задержка на 1 м.ц.
;================================================================================
; Формирование старт-условия.
;================================================================================
SNOVA_3 bcf PortA,SDA ; SDA=0.
bcf PortA,SCL ; SCL=0.

movlw .16 ; Запись в регистр Count_Bait количества


movwf Count_Bait ; байтов, считываемых из EEPROM памяти.
;---------------------------------------------------------
; Задание числового значения режимного байта (для чтения).
;---------------------------------------------------------
movlw B'10100001' ; Запись в регистр Temp режимного байта (1010-
movwf Temp ; код функциональности, 000–адрес м/схемы,
; 1–режим чтения).
call BAIT_WR ; Условный переход в ПП передачи байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;********************************************************************************
; Подпрограмма приема байта (без названия. Можно как-нибудь назвать).
;********************************************************************************
SNOVA_2 movlw .8 ; Запись в счетчик битов количества
movwf Count_Bit ; битов в одном байте.

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


bsf TrisA,SDA ; Вывод SDA работает на вход.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Прием текущего бита.
;================================================================================
SNOVA_1 bcf Status,C ; Сброс в 0 флага переноса-заема (С).

bsf PortA,SCL ; SCL=1

btfsc PortA,SDA ; На линии SDA 0 или 1?


bsf Status,C ; Если 1, то С=1.
bcf PortA,SCL ; Если 0, то С=0 (см. выше), а SCL=0.

rlf Read,F ; Циклический сдвиг влево. Этим обеспечивается


11
; обработка битов байта, начиная с бита
; старшего разряда (№7...№0).
decfsz Count_Bit,F ; Декремент счетчика битов (Count_Bit-1=...).
goto SNOVA_1 ; Если результат не=0, то переход на чтение
; следующего бита.
;================================================================================
; Формирование сигнала АСК (вырабатывает "мастер").
;================================================================================
; Начало формирования сигнала АСК.
;-----------------------------------------------------
bcf PortA,SDA ; SDA=0

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


bcf TrisA,SDA ; Вывод SDA работает на выход.
bcf Status,RP0 ; Переход в 0-й банк.
;-----------------------------------------------------
; Формирование импульса 9-го такта под сигнал АСК.
;-----------------------------------------------------
movlw .1 ; Анализ содержимого счетчика байтов,
subwf Count_Bait,W; с целью формирования сигнала NO ACK
btfsc Status,Z ; после считывания последнего байта.
goto $+4 ; Если байт не последний, то переход
; на команду movf Read,W.
bsf PortA,SCL ; SCL=1
nop ; Задержка на 1 м.ц.
bcf PortA,SCL ; SCL=0
;================================================================================
; Вывод считанного байта в PortB (на индикацию).
;================================================================================
movf Read,W ; Вывод считанного байта (через регистр W) на
movwf PortB ; индикацию (на светодиоды, подключенные к
; RB0...7).
;================================================================================
; Задержка на 261629 м.ц.
;================================================================================
movlw .255 ;
movwf SecL ;
movlw .255 ;
movwf SecH ; Стандартный, 2-байтный
WR clrwdt ; вычитающий счетчик с
decfsz SecL,F ; "врезкой" в него
goto WR ; команды clrwdt.
decfsz SecH,F ;
goto WR ;
;------------------------------------------------------
; Декремент содержимого счетчика считываемых байтов.
;------------------------------------------------------
decfsz Count_Bait,F; Декремент с ветвлением.
goto SNOVA_2 ; Если результат не=0, то читается следующий
; байт.
; Если результат =0, то программа исполняется
; далее.
;================================================================================
; Формирование стоп-условия.
;================================================================================
bsf PortA,SCL ; SCL=1.
bsf PortA,SDA ; SDA=1.

decfsz Flag,F ; Декремент указателя чтения от текущего


; адреса.
goto SNOVA_3 ; Если результат не=0, то переход на чтение
; от текущего адреса.
; Если =0, то программа исполняется далее.
;================================================================================
; Завершение полного цикла программы.
;================================================================================
12
bsf PortA,1 ; "Загорание" светодиода окончания чтения.
clrwdt ; Сброс WDT.
goto $-1 ; Уход в "мертвое", "вечное кольцо" до
; выключения и последующего включения питания.
;********************************************************************************
; Подпрограмма передачи байта.
;********************************************************************************
BAIT_WR movlw .8 ; Запись в счетчик битов количества
movwf Count_Bit ; битов в одном байте.
;================================================================================
; Передача текущего бита
;================================================================================
SNOVA rlf Temp,F ; Циклический сдвиг влево. Этим обеспечивается
; обработка битов байта, начиная с бита
; старшего разряда (№7...№0).
bcf PortA,SDA ; SDA=0.

btfsc Status,C ; Что "ушло" в бит С?


bsf PortA,SDA ; Если в бите С 1, то SDA=1.
bsf PortA,SCL ; SCL=1. (Если в бите С 0, то предыдущая
; команда не исполняется. Вместо нее –
; "виртуальный" NOP).
bcf PortA,SCL ; SCL=0.
decfsz Count_Bit,F ; Декремент счетчика битов (Count_Bit-1=...).
goto SNOVA ; Если результат не=0, то переход на обработку
; следующего бита.
;********************************************************************************
; Группа команд формирования импульса 9-го такта и анализа состояний флага АСК.
;********************************************************************************
; Начало формирования импульса 9-го такта.
;--------------------------------------------------------------------------------
bsf PortA,SCL ; Формируется строб (перепад от 0 к 1)
; импульса 9-го такта.
;--------------------------------------------------------------------------------
; Подготовка к анализу состояний флага АСК (перестройка направления работы
; вывода RA3).
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
bsf TrisA,SDA ; Вывод SDA работает на вход.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Анализ состояний флага АСК ("плавающая" задержка).
;================================================================================
ACK btfsc PortA,SDA ; На линии SDA 0 или 1 ?
goto ACK ; Если 1, то снова анализ (задержка до
; появления 0).
;--------------------------------------------------------------------------------
; Конец формирования импульса 9-го такта.
;--------------------------------------------------------------------------------
bcf PortA,SCL ; Если 0, то формируется спад импульса
; 9-го такта.
;--------------------------------------------------------------------------------
; Обратная перестройка направления работы вывода RA3.
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
bcf TrisA,SDA ; Вывод SDA работает на выход.
bcf Status,RP0 ; Переход в 0-й банк.

return ; Возврат по стеку в "администраторскую" ПП.


;********************************************************************************
end ; Конец программы.

Вплоть до окончания потокового чтения по адресному запросу, все то же самое, что и в


программе Read_2.asm.

13
Еще раз обращаю Ваше внимание на то, что после считывания последнего байта,
импульс
9-го такта, под сигнал АСК (NO ACK), "мастером" не вырабатывается, иначе никакого
последующего чтения, от текущего адреса, не будет (глюк).
Кто не верит, тот может проверить (путем блокировки первых 4-х команд группы
команд формирования импульса 9-го такта).
Принцип такого комбинированного чтения простой: программными средствами, после
окончания считывания предыдущего массива байтов, рабочая точка программы, после
формирования стоп-старта, "отфутболивается" на начало процедуры задания
числового значения режимного байта (для чтения), то есть, адресного запроса не
формируется.
Чтобы такое стало возможным, нужно создать критерий этого "отфутболивания".
Он также очень простой: организуется регистр указателя чтения от текущего адреса
(Flag), в который, в начале исполнения программы, записывается константа .2 (число
чтений).
После завершения чтения по адресному запросу, содержимое регистра Flag
декрементируется decfsz Flag,F (2-1=1 не=0), после чего, рабочая точка программы и
"отфутболивается" на начало процедуры чтения от текущего адреса (на метку
SNOVA_3).
После завершения этой разновидности чтения, происходит еще один декремент decfsz
Flag,F (1-1=0), после чего "срабатывает" сценарий "программа исполняется далее"
("стоп-машина").
Обращаю Ваше внимание на то, что я убрал группу команд записи количества байтов
(movlw .16 и movwf Count_Bait) из подготовительных операций "виртуальной" (в
смысле, без названия) ПП Start, и "врезал" ее немного ниже метки SNOVA_3.
Если этого не сделать (оставить так, как было), то, при чтении от текущего адреса,
считается не заданное количество байтов (.16), а 255 байтов.
Теперь о том, что нужно, предварительно, записать в первые 32 ячейки памяти 24С64А
в ПониПроге. Я писал:
01 02 04 08 10 20 40 80 40 20 10 08 04 02 01 00
03 06 0C 18 30 60 C0 60 30 18 0C 06 03 00 FF 00
В этом случае, в линейке светодиодов, при чтении по адресному запросу, будет "бегущий
огонь" с активностью одного светодиода, а при чтении от текущего адреса, с
активностью двух светодиодов.
В конце, все светодиоды "вспыхнут", а затем погаснут. Можете придумать что-то свое.
Если, после окончания чтения по адресному запросу, нужно организовать несколько
последовательных циклов чтения от текущего адреса, то нужно, вместо константы .2,
записать в регистр Flag константу с большим (ударение на "о") числовым значением.
После этого, в части касающейся чтения от текущего адреса, будет последовательно
считано несколько массивов байтов (зависит от значения константы), по 16 байтов в
каждом.
Можно придумать и еще что-то более мудреное, это уже дело техники.
Сейчас же, главное - понять суть.

Подвожу общий итог по чтению.


1. Первый режимный байт и адресный запрос формируются так же, как и при записи.
2. Далее, формируется стоп-старт и 2-й режимный байт, с R/W=1.
3. После полного завершения "конфигурирования" под режим чтения, в 24Схх
начинает работать внутренний, сдвиговый регистр, тактовым сигналом для которого
являются передние стробы тактовых импульсов №№ 1 ... 8, вырабатываемых
"мастером".
По этим стробам, содержимое внутреннего, сдвигового регистра 24Схх (считываемый
байт), сдвигается на 1 такт влево, что приводит к "выпихиванию" бита (через буферное
устройство и оконечный каскад формирователя сигнала АСК) в линию SDA.
4. После завершения последовательного "выпихивания", в линию SDA, всех 8-ми битов
считываемого байта (порядок - №7 ... №0), и при необходимости считывания
следующего байта, "мастер" вырабатывает "полноценный" сигнал АСК (с импульсом 9-
го такта).
5. Импульс 9-го такта инициирует автоинкремент и перезапись, из соответствующей
14
ячейки EEPROM памяти в триггеры внутреннего, сдвигового регистра, следующего,
считываемого байта, после чего, указанным выше способом, осуществляется побитная
"транспортировка" этого байта на линию SDA.
6. Если нужно закончить чтение, то, после считывания последнего байта, "мастер"
формирует сигнал NO ACK (без импульса 9-го такта).
7. При организации чтения от текущего адреса, необходимо, на момент его начала,
учитывать текущее состояние счетчика адреса.
Просто? Думаю, что да, но сколько "крови пролито" и сколько "мути профильтровано"!
Вот это и есть суть аналитической работы, сводящаяся, в конечном итоге, к сути
работы скульптора (отсекание от глыбы всего лишнего).
В этом смысле, аналитическая работа есть самое натуральное искусство,
превращающее бесформенную глыбу в нечто более эстетичное.
Естественно, для этого нужен и хороший инструмент, и художественный вкус, и
терпение, и ...
Все это, со временем, приобретаемо. Главное, чтобы было желание работать и работа
была любимой. При наличии этого, можно такое натворить ...
Как там наш амнезийный боец? Пойду на целину гляну. Ба ... 10 соток вспахано.
Молодец. Держи калории, заработал.
Да ты уже и не амнезийный совсем: вон как глазенки бегают и ехидства почти нет.
Так, глядишь, на целинных просторах, и русифицируешься потихоньку.
Пора повышать по службе. Завтра будешь пахать с лошадью. Норма - 20 соток.
Справишься, дам трактор. Буду из тебя делать механизатора широкого профиля.
Квалифицированная рабсила страсть как нужна.
Не дрейфь, подсоблю, да и лошадь смирная.
Следующий раздел будет посвящен "повышению этой квалификации".

Дополнительная информация.

О сокращении количества команд в процедурах чтения и записи.


Программы Write … .asm, Read … .asm и Stroka.asm “ваялись” мной из расчета
наиболее комфортного “въезда” в суть производимых действий.
Исходя из этого, я не стал “рвать” функционально обособленные группы команд на
части и “разбрасывать” их по тексту программы, хотя, таким способом, количество
команд, в текстах указанных выше программ, можно сократить.
Первым обратил на это внимание Сергей Рослик, что есть хороший признак, в основе
которого лежит что-то типа стремления хорошего хозяина “протянуть все гайки” в
только что купленом “велосипеде”.
Это же, является одним из элементов “шлифовки” программы, в процессе доведения
ее до “бриллиантового” уровня.
Суть предложения Сергея заключается в переносе команд movwf Temp из
“администраторской” ПП в ту ПП, в которую осуществляется переход по стеку.
Например, для программы Write_1.asm, это выглядит так:
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
;================================================================================
; "Администраторская" ПП (без названия), "рулящая" очередностью обработки байтов.
;================================================================================
; Задание числового значения режимного байта.
;---------------------------------------------------
movlw B'10100000' ; Запись в регистр W режимного байта (1010-
; код функциональности, 000–адрес м/схемы,
; 0–режим записи).
call BAIT_WR ; Условный переход в ПП обработки байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;---------------------------------------------------
; Задание числового значения старшего байта адреса.
;---------------------------------------------------

15
movlw .0 ; Запись в регистр W
; старшего байта адреса.
call BAIT_WR ; Условный переход в ПП обработки байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;---------------------------------------------------
; Задание числового значения младшего байта адреса.
;---------------------------------------------------
movlw .2 ; Запись в регистр W
; младшего байта адреса.
call BAIT_WR ; Условный переход в ПП обработки байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;---------------------------------------------------
; Задание числового значения байта данных.
;---------------------------------------------------
movlw .47 ; Запись в регистр W байта данных,
; предназначенного для записи (2Fh).
call BAIT_WR ; Условный переход в ПП обработки байта
; BAIT_WR.
;-----> Возврат по стеку из ПП BAIT_WR.
;================================================================================
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
;********************************************************************************
; Подпрограмма обработки байта.
;********************************************************************************
BAIT_WR movwf Temp ; Копирование содержимого регистра W
; в регистр Temp.
movlw .8 ; Запись в счетчик битов количества
movwf Count ; битов в одном байте.
;================================================================================
; Обработка текущего бита
;================================================================================
SNOVA rlf Temp,F ; Циклический сдвиг влево. Этим обеспечивается
; обработка битов байта, начиная с бита
; старшего разряда (№7...№0).
bcf PortB,SDA ; SDA=0.
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
При помощи такой простенькой “комбинации из двух пальцев”, объем текста программы
Write_1.asm уменьшается аж на 3 команды.
То же самое можно “провернуть” и с другими текстами программ.
С точки зрения первичного “въезда”, лучше работать с указанными выше программами
(без этой доработки), но как только “въезд” произойдет, смело берите в руки
“скальпель” и “без зазрения совести”, вырезайте все лишнее, только следите за тем,
чтобы программа “не дала дуба”.
По поводу “бриллиантовости”: с мелкими отклонениями от этой “генеральной линии”
(для Вашей же пользы), программы максимально “скомпрессированы” и составлены так,
что в них четко прослеживается заданная последовательность работы, при соблюдении
всех предельных временных характеристик 24С64А/32А.
При этом, их объем меньше объема большинства аналогичных, программ и количество
переходов в них минимально.
Надеюсь, что эти программы “приживутся” и “сослужат хорошую службу” как на стадии
первичного “въезда”, так и далее.
Если у кого-то из Вас есть соображения по поводу уменьшения количества команд или
эффективного (выигрыш обязательно должен быть) изменения программной
“конструкции”, то, как говорится, милости просим.
Есть вполне реальный шанс, коллективными усилиями, “сваять” “бриллиантовые”
программы в “статусе эталонов”.

О способе формирования уровней на линиях SDA и SCL.

16
А эта информация от Альберто.
Альберто сторонник способа формирования уровня единицы за счет внешнего,
подтягивающего резистора, и резон в этом есть, так как, в части касающейся
формирования единичного уровня, он более комфортно “вписывается” в концепцию
интерфейса I2C, нежели установка уровня единицы за счет резистора коллекторной
(стоковой) нагрузки оконечного каскада защелки, выход которой подключен к
соответствующей линии (то, что применил я).
Вот “вырезка” из его программы, иллюстрирующая этот способ:
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подпрограммы для работы с EEPROM
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;********************************************************************************
; Формирование на линии SCL "1" за счет подтягивающего резистора
;--------------------------------------------------------------------------------
SCL_HI:
bsf Status,RP0 ; Переход в банк 1
bsf TrisB,SCL ; Установка вывода SCL на вход
bcf Status,RP0 ; Переход в банк 0
return
;--------------------------------------------------------------------------------
; Формирование на линии SDA "1" за счет подтягивающего резистора
;--------------------------------------------------------------------------------
SDA_HI:
bsf Status,RP0 ; Переход в банк 1
bsf TrisB,SDA ; Установка вывода SDA на ввод
bcf Status,RP0 ; Переход в банк 0
return
;--------------------------------------------------------------------------------
; Формирование на линии SCL "0" средствами микроконтроллера
;--------------------------------------------------------------------------------
SCL_LO:
bcf PortB,SCL ; Обнулить вывод SCL
bsf Status,RP0 ; Переход в банк 1
bcf TrisB,SCL ; Установка вывода SCL на выход
bcf Status,RP0 ; Переход в банк 0
return
;--------------------------------------------------------------------------------
; Формирование на линии SDA "0" средствами микроконтроллера
;--------------------------------------------------------------------------------
SDA_LO:
bcf PortB,SDA ; Обнулить вывод SCL
bsf Status,RP0 ; Переход в банк 1
bcf TrisB,SDA ; Установка вывода SCL на выход
bcf Status,RP0 ; Переход в банк 0
return
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
По большому счету, “право на жизнь” имеет и то, и другое, так как, в части
касающейся ранее сказанного, принципиальной разницы нет.
И в самом деле, если транзистор оконечного каскада защелки закрыт (формируется
уровень 1), то его переход коллектор - эмиттер (или сток – исток) имеет высокое
сопротивление, что эквивалентно обрыву цепи.
В итоге, коллекторная (или стоковая) нагрузка транзистора выполняет функцию того же
внешнего, подтягивающего резистора, только меньшего номинала и “упакованного”
внутри ПИКа.
Его малый номинал (по отношению к номиналу “штатного”, внешнего, подтягивающего
резистора) ни к чему плохому не приведет, так как такого рода “подтяжки”
осуществляются в интервалах времени, в которых входные сопротивления выводов
24С64А, подключенных к линиям SDA и SCL, велики (перегружаться нечему, токи
мизерные).

17
Примененный мной способ формирования уровней, прельщает меня отсутствием
большого количества перестроек направлений работы соответствующих выводов портов
и отсутствием внешнего, подтягивающего резистора на линии SCL.
Моя логика проста до одури: если, в обеих случаях, результат один и тот же, то
выгоднее воспользоваться менее “массивными” процедурами, так как это выигрыш и по
количеству команд, и по скорости.
С другой стороны, способ, предложенный Альберто, вполне может оказаться “палочкой
– выручалочкой” в тех случаях, когда речь идет о “полноценном” интерфейсе I2C (или
1-Wire, о котором речь пойдет далее).
Так что советую Вам “положить на это глаз”. В хозяйстве все пригодится.
В нашем деле нужно видеть дальше собственного носа.
Пару слов об Альберто.
Это мой друг (родственная душа, хоть и на том конце земного шарика), который мне
очень помогает, и человек, которого я, со спокойной совестью, могу назвать
профессионалом, причем, профессионалом увлеченным и любящим свою работу.
При этом я имею ввиду не то, что он “святее всех святых” и знает все (знать все –
утопия), а реальную способность человека к эффективному и успешному
самообразованию.
Темпы впечатляют (по-моему, это “только цветочки”…), причем, это находит свое
отражение в реальном “железе”, “крутизна” которого растет быстрыми темпами.
Лично для меня, именно это и есть основной показатель профессионализма.
Совершенствование - только вопрос времени.
Советую Вам прислушиваться к мнению Альберто. Оно того стоит.
Кстати, следующий раздел (по 1-Wire), будет “ваяться” на основе информации,
предоставленной мне Альберто (на 1-Wire он уже “руку набил”), за что я ему
признателен.
В паре, мы “раздолбаем” этот 1-Wire “в пух и прах”. Даже и не сомневайтесь.

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

18