Поиск по сайту: |
|
По базе: |
|
Главная страница > Применение > Микроконтроллеров > MSP430 |
|
||||||||||||
Реализация шины SMBus на базе микроконтроллера MSP430Краткое содержание Данный пример применения описывает программную реализацию шины системного управления (system management bus (SMBus)) на базе микроконтроллера MSP430. Рассмотрены протоколы ведущего (master) устройства, базирующегося на прерываниях ведомого (slave), а также примеры использования ведущего устройства. Шина SMBus является подвидом шины 2C и широко используется в смарт-батареях (smart batteries) и других системных устройствах. 1 Введение SMbus это двухпроводной синхронный последовательный протокол, являющийся производным от I2C. Так же, как и 2C, он использует линии последовательного тактирования (SCL) и данных (SDA). Для исключения неопределённого состояния на линии используются подтягивающие (pullup) резисторы или источники тока, а устройства, подключенные к шине должны иметь выходы типа «открытый коллектор» либо «открытый сток». Это соответствует монтажному «И» всех устройств, что означает, что каждое из устройств может либо перевести шину в состояние лог. «0», либо освободить её. Так как подключённые к шине устройства могут быть запитаны от различных напряжений, они не должны переводить линию в состояние лог. «1». Все устройства разделяются на ведущие (master) и ведомые (slave). Ведущее устройство может инициировать передачу и формирует тактовый сигнал. Ведомое принимает либо передаёт данные, но при этом процесс передачи инициируется ведущим. Устройства могут иметь как признаки ведущего и ведомого одновременно, так и быть исключительно одним либо другим. Например, ведомое устройство может в критических случаях становиться ведущим и передавать системе сообщения о неисправности. Алгоритм такого поведения целиком определяется конкретной областью применения. Каждое устройство на шине имеет уникальный 7-битный адрес. Это позволяет подключать к линии до 128 устройств, однако некоторые адреса являются зарезервированными. Различные коммерчески доступные устройства имеют адреса, присвоенные координационным комитетом SMBus. При приёме и передаче данных используются семь различных протоколов. Это «Быстрая команда» (Quick Command), «Отправить байт» (Send Byte), «Принять байт» (Receive Byte), «Записать Слово/Байт» (Write Byte/Word), «Прочитать Слово/Байт» (Read Byte/Word), «Запрос состояния» (Process Call), и «Чтение/запись Блока» (Block Read/Write). Каждый протокол имеет собственный конкретный набор действий, но общая схема схожа для всех протоколов. Передача всегда начинается с символа «Старт» (S). Этот символ передаётся переводом обеих линий в состояние лог. «1», последующим переводом линии SDA в состояние лог. «0» и, наконец, выставлением лог. «0» на шине SCL. После передачи стартовой последовательности, начинается передача 8-ми блоков, завершающаяся подтверждением (ACK). Подтверждение передаётся ведомым устройством путём перевода линии SDA в состояние лог. «0» во время передачи ведущим сигнала SCL. Если линия SDA не была переведена в такое состояние за время импульса на шине SCL, это состояние называется неподтверждением (NACK). Первый 8-битный блок является 7-битным адресом ведомого устройства вкупе с битом, определяющим направление передачи во всех протоколах, за исключением «Быстрой команды». В последнем же данный бит собственно является командой. После передачи адреса и направления, ведущий ожидает подтверждения от ведомого. При этом он формирует одиночный импульс на линии SCL и контролирует перевод ведомым в это время линии SDA в состояние лог. нуля. Если подтверждение не получено, ведущее устройство прекращает передачу и повторяет её позднее. Эта операция также может использоваться для определения присутствия ведомого на шине. После получения подтверждения, передаётся либо получается очередной блок из 8-ми бит, либо передаётся символ останова (P). Этот символ формируется переводом обеих линий в состояние лог. «0», последующим переводом линии SCL в состояние лог. «1» и завершается переводом в лог. «1» линии SDA. Остальные 8-битные блоки могут быть данными, командами либо следующей комбинацией адреса и бита чтения/записи. Точный формат каждого из протоколов можно найти в документе System Management Bus specification на сайте . Ввиду того, что на шине используется подключение устройств по принципу «монтажное «И»», она обладает механизмом арбитража. Если более одного ведущего устройства пытаются передавать данные, первый из них, «отпустивший» шину во время того, как оставшийся удерживает её в состоянии лог. «0» должен отдать арбитраж. Чтобы обеспечить эффективность такого метода, каждое ведущее устройство должно проверять состояние шины каждый раз после перевода её в состояние лог. «1». Если после этого шина удерживается в состоянии лог. «0», ведущее устройство должно прекратить передачу и повторить попытку позднее. В результате такого решения системы арбитража, устройства с меньшими адресами имеют приоритет над устройствами со старшими адресами. Если два ведущих пытаются начать передачу одновременно, тот из них, который передаёт старший адрес, первым освободит линию и потеряет, таким образом, приоритет. Рабочими частотами шины являются 10 кГц и 100 кГц. Это аналогично шине 2C, за исключением того, что 2C не имеет ограничения скорости снизу, при этом устройства могут занимать шину на неограниченное время. SMBus имеет более жёсткие ограничения, ограничивая минимальную скорость. Несмотря на это, ведомые устройства не обязаны работать с той же частотой, что и ведущие. Единственным ограничением является минимальная скорость их работы в 10 кГц. Возможность работы с разной скоростью реализована следующим образом: если ведомому устройству требуется дополнительное время для завершения операции, оно принуждает ведущего к ожиданию удержанием линии SCL в состоянии лог. «0». Это называется «удлинением тактового сигнала» (clock-low extending). Ведущее устройство должно дождаться, пока ведомое «отпустит» линию SCL, но , если это займёт больше времени, чем разрешено спецификацией, произойдёт тайм-аут. Этим обеспечивается минимальная скорость шины. Дополнительную информацию по протоколу SMBus можно найти на форуме Smart Battery System Implementers Forum (SBS IF). Комитет SBS IF образован представителями фирм Benchmarq Microelectronics Inc., Duracell Inc., Energizer Power Systems, Intel Corporation, Linear Technology Corporation, Maxim Integrated Products, Mitsubishi Electric Corporation, National Semiconductor Corporation, Toshiba Battery Co., и Varta Batterie AG. Комитетом опубликована спецификация SMBus, доступная для скачивания на сайте в формате pdf. 2 Аппаратная часть На рис. 1 приведен пример подключения шины SMBus. В этом случае MSP430 подключен к смарт-батарее. Батарея питает шину и MSP430, но это не является обязательным, необходимым условием является лишь общая «земля». Подтягивающие (pull up) резисторы обозначены как RP. Для уменьшения потребляемого тока, значения RP выбраны максимально возможными в рамках требований спецификации. Существуют также специальные драйвера шины SMBus, используемые вместо подтягивающих резисторов. Такие устройства обеспечивают максимальный ток на фронте и минимальный при низком уровне на шине.
3 Реализация ведущего устройства шины SMBus Программа ведущего устройства шины SMBus для MSP430 реализует все существующие типы протоколов. Для экономии регистров, параметры передаются через стек. Максимальная глубина стека 40 байт. Память вне стека не затрагивается, кроме случая операций над блоками. Во время передачи блока его начало передаётся как параметр (блок растёт в сторону верхних адресов памяти). Во время записи блока его размер известен до начала передачи, во время приёма блока его размер передаётся ведомым устройством. При этом следует соблюдать осторожность, чтобы данные из блока не затёрли программную или оперативную память. Программа состоит из двух основных частей: подпрограмм верхнего уровня и подпрограмм нижнего уровня. Низкоуровневые подпрограммы обрабатывают сдвиг бит, временнЫе характеристики и работу с портами ввода-вывода. Протоколы SMBus, по существу, состоят из нескольких стандартных блоков, которые вызываются и повторяются в определенном порядке. Эти стандартные блоки обрабатываются подпрограммами нижнего уровня. Подпрограммы верхнего уровня обеспечивают пользовательский интерфейс и сохраняют регистры. На каждый протокол приходится одна такая подпрограмма, в них устанавливаются параметры, а затем вызываются подпрограммы нижнего уровня. Для обеспечения требования протокола SMBus к выходам («открытый коллектор»), выводы процессора переключаются со входа на выход и наоборот. В выходных защёлках портов всегда присутствует лог. «0». Это означает, что MSP430 может «освободить» линию переключением вывода на вход, либо «занять» её (т.е. выставить там лог. «0») путём переключения вывода на выход. Выбор требуемых выводов осуществляется «привязкой» их в начале программы к конкретным линиям SDA, SCL и DNC. SDA и SCL соответствуют линиям данных и тактирования шины SMBus. DNC является одновременно линиями SCL и SDA. Соответствующий порт выбирается назначением OUT, DIR и IN. В зависимости от конкретного применения, могут использоваться не все протоколы. Ненужные подпрограммы могут быть «закомментированы», что уменьшит размер кода. Удаление подпрограмм высокого уровня является очевидным, при этом возможно также удаление некоторых неиспользуемых подпрограмм низкого уровня. Так как SMBus поддерживает несколько ведущих устройств на шине (multimaster) и «горячее включение» (hot-plug), это приводит к появлению ошибок. Их причинами являются занятость шины, отсутствие ведомого устройства, конфликты между несколькими ведущими устройствами и помехи на шине. Программа включает обработку ошибок и флаг ошибки. При обнаружении ошибки передача прекращается, программа выставляет флаг ошибки и возвращается из подпрограммы верхнего уровня. Пользовательская программа должна проверять данный флаг для определения успешного (возвращает 1) или ошибочного (возвращает 0) завершения. Обработка события ошибки осуществляется пользовательской программой. Основная программа включает в себя подпрограммы верхнего и нижнего уровней и располагается отдельно от пользовательской программы. Место, где должна располагаться пользовательская программа оставлено свободным. Для передачи данных по шине SMBus, просто вызывается соответствующая подпрограмма верхнего уровня. Примеры передачи параметров приведены в комментариях к каждой подпрограмме. Исходные коды приведены в приложении A. Также в приложениях приводятся демонстрационные программы, иллюстрирующие различные протоколы и примеры работы с смарт-батареей. 4 Примеры реализации программы ведущего устройства шины SMBus 4.1 Поиск устройств на шине Первый пример довольно прост. В нём производится поиск устройств, присутствующих на шине и отображение адреса последнего найденного устройства. Это весьма удобно во время проверки соединений шины. Первоначально пример был написан для поиска адресов устройств, он наглядно демонстрирует возможность уменьшения размера кода при помощи удаления неиспользуемых подпрограмм. Ввиду простоты примера, была удалена значительная часть кода. Оставшийся код можно запускать из-под программы монитора отладочного модуля MSP430x33x (EVK part number MSP-EVK430x330). 4.2 Чтение данных смарт-батареи Этот пример значительно объёмнее первого. В нём используются протоколы «Чтение слова», «Запись слова» и «Чтение блока» для связи со смарт-батареей. В примере считываются температура, напряжение, производитель, химическая разновидность и ёмкость батареи. Также используется запись значения в регистр «Предупреждение об оставшейся ёмкости» (RemainingCapacityAlarm), записанное значение проверяется. Эти операции производятся циклически, результат отображается на ЖКИ. Пример демонстрирует использование более сложных протоколов и процесс обработки возвращаемых данных. В данной конфигурации программа протоколов SMBus запускается из EPROM отладочного модуля MSP430x33x (EVK part number MSP-EVK430x330), а пользовательская программа запускается из монитора этого модуля. 5 Реализация ведомого устройства шины SMBus Эта программа представляет пример реализации ведомого устройства шины SMBus и построена на базе прерываний. Назначения при помощи оператора. equ в начале программы позволяют выбрать адрес ведомого устройства, выводы и порты. В программе реализован протокол «Отправка байта» (что для ведомого устройства означает передачу байта к нему от ведущего). В промежутке между прерываниями ведомое устройство может находиться в режиме пониженного потребления либо выполнять другие задачи. Так как прерывание происходит каждый раз при переходе линии SDA из состояния лог. «1» в лог. «0», ведомое устройство при загруженности шины проводит значительную часть времени в подпрограмме обработки прерываний. Чтобы исключить контроль шины ведомым устройством во время работы с другими ведомыми могут быть использованы внешние элементы, контролирующие шину и формирующие прерывания только при совпадении адреса ведомого устройства. Ещё одним недостатком использования прерываний без дополнительных внешних устройств является время обработки прерывания. Так как оно составляет несколько тактов, при этом существует вероятность пропуска стартовой последовательности. При реализации поллинга вероятность пропустить стартовую посылку снижается, но процессор постоянно занят отслеживанием состояния шины. Выбор оптимального решения зависит от конкретной реализации. Вариант с прерываниями позволяет процессору обслуживать другие задачи во время неактивного состояния шины, но при этом есть вероятность пропустить первую попытку установления связи. Вариант с поллингом не оставляет процессору возможности обрабатывать другие задачи вне зависимости от состояния шины. Потребление также при этом возрастает, так как процессор не может быть переведен в режим пониженного энергопотребления во время неактивного состояния шины. На базе данного протокола возможна реализация остальных. В нашем примере обрабатываются стартовые и стоповые последовательности, приём 7-битных блоков адреса и 8-битных блоков данных / команд. Использование этих процедур в требуемом порядке позволяет реализовать некоторые другие протоколы. Регистры не сохраняются в стеке с целью обеспечения требований спецификации в области наиболее быстрой стартовой последовательности. Время между переходом линий SDA и SCL в состояние лог. «0» может составлять всего 4 мс. Если известно, что ведущее устройство выдаёт сигналы с большей длительностью, можно сохранять регистры в стеке в начале процедуры, но это может привести к пропуску стартовой посылки при работе с более быстрым ведущим устройством. 6 Заключение Необходимость увеличения времени жизни батарей в переносных устройствах привела к разработке батарей со сложным химическим составом и повышению требований к технологиям мониторинга. Шина SMBus предоставляет удобный и чёткий интерфейс для мониторинга смарт-батарей, а сверхнизкое потребление микроконтроллера MSP430 делает его незаменимым для таких систем. Приложение A Программа ведущего устройства шины SMBus;***************************************************************************************** ; Программа ведущего устройства шины SMBus, параметры передаются через стек ;***************************************************************************************** RAM_orig .set 00240h ; Стартовый адрес в ОЗУ SP_orig .set 005DEh ; Указатель стека EPROM .set 08850h ; Размещение EPROM ;––– Определения управляющих регистров WDTCTL .equ 0120h WDTHold .equ 80h WDT_wrkey .equ 05A00h ;PORT 0 P0IE .equ 015h P0DIR .equ 012h P0IN .equ 010h P0OUT .equ 011h ; port 2 P2IN .equ 028h P2OUT .equ 029h P2IE .equ 02Dh P2SEL .equ 02Eh P2DIR .equ 02Ah SDA .equ 020h SCL .equ 080h DNC .equ 0A0h OUT .equ P2OU TDIR .equ P2DIR IN .equ P2IN LCD1 .equ 031h LCDM .equ 030h IE1 .equ 0h IE2 .equ 01h IFG1 .equ 02h IFG2 .equ 03h block .equ 0550h alcd .equ 0B500h ; Размещение таблицы символов ; ASCII для ЖКИ ;***************************************************************************************** ; Reset : инициализация процессора ;***************************************************************************************** .sect ”MAIN”,RAM_orig RESET MOV #SP_orig,SP ; Инициализация указателя стека ;******************************************************************************* ; Начало пользовательской программы ;***************************************************************************************** ; Здесь должна быть расположена пользовательская программа ;***************************************************************************************** ; Завершение пользовательской программы ;***************************************************************************************** .sect ”smbus”, EPROM ;***************************************************************************************** ; Подпрограммы верхнего уровня, п/п нижнего уровня вызываются индивидуально ; для реализации различных протоколов ;***************************************************************************************** ; Протокол «Быстрая команда» 1 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; стоп (stop) из ; ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; не используется unused ; не используется unused ; не используется unused ; адрес address старшая область памяти high mem ; ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; SUB #06h, SP ; остальные параметры не используются ; CALL #qcp ; ADD #08h, SP ; вычесть объём параметров ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * qcp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 28(SP), R7 ; получить адрес из стека CALL #sbit ; отправить стартовую посылку и адрес ;CALL #sendone ; отправить «1» или CALL #sendzero ; отправить «0» CALL #ack ; ждём подтверждения (ACK) CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Отправить байт» 2 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; стоп (stop) из ; ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; не используется unused ; не используется unused ; данные data ; адрес address старшая область памяти high mem ; ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #055h ; отправляемые данные ; SUB #04h, SP ; остальные параметры не используются ; CALL #sbp ; ADD #08h, SP ; вычесть объём параметров ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок sbp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 28(SP), R7 ; получить адрес из стека MOV.B 26(SP), R8 ; получить данные из стека CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить байт команды CALL #ack ; ждём подтверждения (ACK) CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Принять байт» 3 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; данные (data) в ? ; неподтверждение(NACK) из ; стоп (stop) из ; ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; данные data ; не используется unused ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #08h ; код команды ; SUB #04h, SP ; зарезервировать место под принимаемые данные ; CALL #rcbp ; POP R8 ; переместить данные в R8 ; ADD #06h, SP ; вычесть объём параметров ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * rbp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) CALL #rsbit ; отправить повторяющиеся стартовую посылку и адрес CALL #sendone ; отправить «1» для чтения CALL #ack ; ждём подтверждения (ACK) CALL #rbyte ; принять байт данных CALL #nack ; отправить неподтверждение (NACK) CALL #pbit ; отправить стоповую посылку MOV.B R14, 22(SP) ; копировать байт данных в стек MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Принять слово» 7 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; данные (data) в ? ; подтверждение(acknowledge) в ? ; данные (data) в ? ; подтверждение(acknowledge) в ? ; стоп (stop) из ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; младший байт данных low data byte ; старший байт данных high data byte ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #008h ; код команды “температура батареи” ; PUSH #00h ; зарезервировать байт под принимаемые данные ; PUSH #00h ; зарезервировать байт под принимаемые данные ; CALL #rwp ; POP R10 ; переместить данные в R10 ; POP R11 ; переместить данные в R11 ; ADD #04h, SP ; освободить место, занимаемое командой и адресом ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * rwp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) CALL #rsbit ; отправить повторяющиеся стартовую посылку и адрес CALL #sendone ; отправить «1» для чтения CALL #ack ; ждём подтверждения (ACK) CALL #rbyte ; принять младший байт данных MOV.B R14, 22(SP) ; сохранить младший байт данных в стеке CALL #sack ; ждём подтверждения (ACK) CALL #rbyte ; принять старший байт данных CALL #nack ; отправить неподтверждение (NACK) CALL #pbit ; отправить стоповую посылку MOV.B R14, 24(SP) ; сохранить старший байт данных в стеке MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Запись блока» 8 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт, блок памяти ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; счётчик байт (byte count) из ; подтверждение(acknowledge) в ? ; данные (data) из ; подтверждение(acknowledge) в ? ; ; данные (data) в ? ; подтверждение(acknowledge) в ? ; ; данные и ACK повторяются n раз ; стоп (stop) из ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; счётчик байт byte count ; указатель блока block pointer ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #0020h ; код команды “температура батареи” ; PUSH #00550h ; указатель на начало блока ; PUSH #00h ; зарезервировать байт под счётчик ; CALL #blkw ; POP R10 ; переместить данные в R10 ; ADD #06h, SP ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * blkw PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса MOV 24(SP), R9 ; стартовый адрес блока MOV.B #00h, R15 ; циклический байтовый счётчик CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) MOV.B 22(SP), R8 ; копировать счётчик байт CALL #sbyte ; отправить счётчик байт CALL #ack ; ждём подтверждения (ACK) blk_rep MOV.B 0(R9), R8 ; передать данные из блока CALL #sbyte ; отправить байт данных CALL #ack ; ждём подтверждения (ACK) INC R15 ; инкремент счётчика положения блока INC R9 ; инкремент указателя блока CMP 22(SP), R15 ; проверка завершения данных JNZ blk_rep ; повтор до завершения CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Чтение блока» 9 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт, блок памяти ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; запись(W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; старт (start) из ; адрес(address) из ; чтение(R) из ; подтверждение(acknowledge) в ? ; счётчик байт (byte count) в ? ; подтверждение(acknowledge) из ; данные (data) в ? ; подтверждение(acknowledge) из ; ; данные и ACK повторяются n раз ; неподтверждение(NACK) из ; стоп (stop) из ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; счётчик байт byte count ; указатель блока block pointer ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #0020h ; код команды “температура батареи” ; PUSH #00550h ; указатель на начало блока ; PUSH #00h ; зарезервировать байт под счётчик ; CALL #blkr ; POP R10 ; переместить счётчик в R10 ; ADD #06h, SP ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * blkr PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B #00h, R15 ; циклический байтовый счётчик MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса MOV 24(SP), R9 ; стартовый адрес блока CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) CALL #rsbit ; отправить повторяющиеся стартовую посылку и адрес CALL #sendone ; отправить «1» для чтения CALL #ack ; ждём подтверждения (ACK) CALL #rbyte MOV.B R14, 22(SP) ; поместить счётчик в стек CALL #sack ; отправить подтверждение (ACK) rblk_rep CALL #rbyte ; принять байт данных MOV.B R14, 0(R9) ; переместить данные из блока INC R15 ; инкремент счётчика положения блока INC R9 ; инкремент указателя блока CMP 22(SP), R15 ; проверка завершения данных JZ blk_done ; повтор до завершения CALL #sack ; отправить подтверждение (ACK) CMP 22(SP), R15 ; проверка завершения данных JNZ rblk_rep ; повтор до завершения blk_done CALL #nack ; отправить неподтверждение (NACK) CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ;********************************************************************* ; Подпрограммы нижнего уровня, общие для всех протоколов ;********************************************************************* ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; отправка стартовой последовательности и адреса ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbit ; «отпустить» обе линии BIC.B #DNC, DIR ; проверка освобождения шины MOV #05h, R10 ; счётчик на 50 микросекунд wait MOV.B IN, R11 ; копировать состояние входов в R11 AND #DNC, R11 ; маска входов CMP #DNC, R11 ; если линии SDA или SCL в лог. «0»то шина занята JNZ busy DEC R10 ; декремент счётчика JNZ wait rsbit BIC.B #DNC, DIR ; дополнительное освобождение линии с целью ; использования этой же подпрограммы для ; команды повторяющегося старта ; отправка стартовой последовательности BIS.B #SDA, DIR BIS.B #SCL, DIR ; отправка адреса MOV.B #07h, R13 ; счётчик на 7 бит адреса MOV.B R7, R11 ; копировать адрес в R11 ashift RLA.B R11 ; сдвиг влево, при этом СЗР 7-битного адреса ; будет находиться на 7-й позиции MOV.B R11, R12 ; скопировать его для возможности маскирования ; без потери данных AND.B #080h, R12 ; маскировать все биты кроме СЗР CMP.B #00h, R12 ; сравнить с 0 JNZ one CALL #sendzero ; отправить «1» JMP zero one CALL #sendone ; отправить «0» zero DEC R13 ; декремент счётчика JNZ ashift ; если счётчик <7 бит, повторить сдвиг RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; подтверждение (ACK) не принято, отправить STOP и busy ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbusy CALL #pbit ; отправить STOP и busy ADD #02h, SP ; удалить данные из стека, так как ; инструкция RET не использовалась MOV.B #00h, 28(SP) ; код ошибки POP R13 ; восстановление регистров POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Ожидание подтверждения (ACK) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ack BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство ;MOV #008h, R11 ; счётчик на ?50 мкс MOV #02FFh, R11 ; удлинённый счётчик для батареи PS100Z–200 clkex MOV.B IN, R10 ; проверка шины DEC R11 JZ busy ; арбитраж – время истекло AND.B #SCL, R10 ; проверка линии SCL JZ clkex ; ожидание подтверждения (ACK) (SDA переходит в лог. «0») MOV #05F6h, R11 ; счётчик таймаута для NACK wack MOV.B IN, R10 ; проверка шины DEC R11 JZ sbusy ; таймаут NACK–– отправить бит P и повторить попытку AND.B #SDA, R10 ; маскировать всё, кроме SDA JNZ wack ; приём ACK или ожидание таймаута BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка стоповой последовательности ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * pbit BIS.B #SDA, DIR ; выставить лог. «0» на линии SDA BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL NOP BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL NOP BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка байта (используются также sendzero и sendone) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbyte ; отправка данных MOV.B #08h, R13 ; счётчик на ?50 мкс MOV.B R8, R11 ; копировать данные в R11 dshift MOV.B R11, R12 AND.B #080h, R12 ; маскировать все биты, кроме СЗР CMP.B #00h, R12 ; сравнить с 0 JNZ on CALL #sendzero ; отправить «1» JMP zer on CALL #sendone ; отправить «0» zer RLA.B R11 ; сдвиг влево, отправляемый бит в СЗР DEC R13 ; декремент счётчика на 8 JNZ dshift RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Приём байта ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * rbyte MOV.B #08h, R12 ; счётчик на 8 бит данных BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA rrep BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL MOV #0035h, R13 ; удлинённый счётчик для батареи PS100Z–200 ; удлинение тактового сигнала clkxtn MOV.B IN, R10 ; проверка шины DEC R13 JZ busy ; выход по таймауту AND.B #SCL, R10 JZ clkxtn ; ожидание, если SCL не «1» MOV.B IN, R10 ; проверка шины RLA.B R11 ; вход = МЗР AND.B #SDA, R10 ; проверка SDA JZ inzero BIS.B #01h, R11 ; установить «1» в МЗР inzero DEC R12 JNZ rrep ; продолжение для оставшейся части байта MOV.B R11, R14 ; копирование данных BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка неподтверждения (NACK) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * nack BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство ; ждём установки «1» на линии SCL clkn MOV.B IN, R10 AND.B #SCL, R10 ; проверка линии SCL JZ clkn BIS.B #SCL, DIR ; «отпустить» SCL RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка подтверждения (ACK) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sack ; ждём, пока ведомый «отпустит» линию SDA MOV #000Fh, R11 ; счётчик на ?50 мкс swaita MOV.B IN, R10 ; проверка шины DEC R11 JZ busy AND.B #SDA, R10 ; проверка SCL JZ swaita BIS.B #SDA, DIR ; перевести SDA в «0» BIC.B #SCL, DIR ; перевести SCL в «1» MOV #000Fh, R11 ; счётчик на ?50 мкс swait MOV.B IN, R10 ; проверка шины DEC R11 JZ busy AND.B #SCL, R10 ; проверка SCL JZ swait BIS.B #SCL, DIR ; перевести SCL в «0» BIC.B #SDA, DIR ; «отпустить» SDA RET ;––– очистка ЖКИ show_clr MOV #15, r5 ; очистка дисплейной памяти show_clr1 MOV.b #0, LCD1–1(r5) DEC r5 JNZ show_clr1 RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Определения для ЖКИ ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LCD_TYPE ;–––ЖКИ модуля STK/EVK a .equ 01h b .equ 02h c .equ 10h d .equ 04h e .equ 80h f .equ 20h g .equ 08h h .equ 40h ;––– Определения символов LCD_Tab .byte a+b+c+d+e+f ; отображает”0” .byte b+c ; отображает”1” .byte a+b+d+e+g ; отображает”2” .byte a+b+c+d+g ; отображает”3” .byte b+c+f+g ; отображает”4” .byte a+c+d+f+g ; отображает”5” .byte a+c+d+e+f+g ; отображает”6” .byte a+b+c ; отображает”7” .byte a+b+c+d+e+f+g ; отображает”8” .byte a+b+c+d+f+g ; отображает”9” .byte 0 ; отображает ”:” пустой .byte g ; отображает”;” – .byte a+d+e+f ; отображает”<” [ .byte d+g ; отображает”=” .byte a+b+c+d ; отображает”>” ] .byte a+b+e+g ; отображает”?” .byte a+b+d+e+f+g ; отображает”@” .byte a+b+c+e+f+g ; отображает”A” .byte c+d+e+f+g ; отображает”B” b .byte a+d+e+f ; отображает”C” .byte b+c+d+e+g ; отображает”D” d .byte a+d+e+f+g ; отображает”E” .byte a+e+f+g ; отображает”F” .byte a+b+c+d+f+g ; отображает”G” .byte b+c+e+f+g ; отображает”H” .byte b+c ; отображает”I” .byte b+c+d+e ; отображает”J” .byte 0 ; отображает”K” .byte d+e+f ; отображает”L” .byte a+b+c+e+f ; отображает”M” .byte c+e+g ; отображает”N” n .byte c+d+e+g ; отображает”O” o .byte a+b+e+f+g ; отображает”P” .byte 0 ; отображает”Q” .byte e+g ; отображает”R” r .byte a+c+d+f+g ; отображает”S” .byte d+e+f+g ; отображает”T” t .byte c+d+e ; отображает”U” u .byte 0 ; отображает”V” .byte 0 ; отображает”W” .byte 0 ; отображает”X” .byte b+c+d+f+g ; отображает”Y” .byte a+b+d+e+g ; отображает”Z” 2 LCD_Tab_End .even ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Вектора прерываний ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; .sect ”Int_Vect”,0FFFFh–1 ; без программы монитора ; .word RESET ; POR, внеш. Reset, Watchdog ; .end .sect ”Int_Vect”,05FFh–1 ; с программой монитора .word RESET ; POR, внеш. Reset, Watchdog .end Приложение B Программа поиска адресов ;**************************************************************************** ; Программа поиска адресов ;–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– ; Программа сканирует шину SMBus на предмет подключенных устройств. ; Начинает с адреса 0x00 и перебирает все 128 возможных адресов. ; Текущий адрес при сканировании отображается на правой части ЖКИ ; На левой части отображается адрес последнего из найденных устройств. Когда устройство ; найдено, программа приостанавливается, адрес переносится в левую часть ЖКИ, после ; чего выполнение продолжается. ; Наличие устройства на шине проверяется посылкой стартовой последовательности, ; адреса устройства и ожидания подтверждения. Далее тестируется следующий адрес. ; ; Программа поиска адресов является примером удаления неиспользуемых частей кода. ; Т.к. ей не требуются некоторые протоколы, некоторые подпрограммы ; верхнего и нижнего уровней были удалены. ;**************************************************************************** RAM_orig .set 00240h ; Стартовый адрес SP_orig .set 005DEh ; указатель стека ;––– Определения управляющих регистров WDTCTL .equ 0120h WDTHold .equ 80h WDT_wrkey .equ 05A00h ;PORT 0 P0IE .equ 015h P0DIR .equ 012h P0IN .equ 010h P0OUT .equ 011h ; port 2 P2IN .equ 028h P2OUT .equ 029h P2IE .equ 02Dh P2SEL .equ 02Eh P2DIR .equ 02Ah SDA .equ 020h SCL .equ 080h DNC .equ 0A0h OUT .equ P2OUT DIR .equ P2DIR IN .equ P2IN LCD1 .equ 031h LCDM .equ 030h IE1 .equ 0h IE2 .equ 01h IFG1 .equ 02h IFG2 .equ 03h address .equ 0500h ; Адрес в ОЗУ для переменной сканирования ;**************************************************************************** ; Reset : Инициализация процессора ;**************************************************************************** .sect ”MAIN”,RAM_orig RESET MOV #SP_orig,SP ; Инициализация указателя стека ;**************************************************************************** ; Начало пользовательской программы ;**************************************************************************** CALL #show_clr ; Сброс адреса res MOV.B #00FFh, address ; адрес начинается с 0xFF ; Начало цикла перебора адресов retry INC.B address ; переход к следующему адресу из 0xFF в 0x00 CMP.B #080h, address ; адрес = 80? JZ res ; сброс адреса по переполнению ; пауза MOV #02Fh, R7 ; цикл паузы dela2 MOV #031Fh, R6 dela DEC R6 JNZ dela DEC R7 JNZ dela2 ; Отображение сканируемого адреса MOV #0000h, R5 ; очистка (убедиться, что очищается старший байт) MOV.B address, R5 ; R5 ? младший байт AND #000Fh, R5 ; маска на старшую тетраду MOV.B LCD_Tab(R5),LCD1+1 ; отобразить младшую тетраду 0–F MOV.B address, R5 ; R5 ? младший байт AND #00F0h, R5 ; маска на младшую тетраду RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо MOV.B LCD_Tab(R5), LCD1+2 ; отобразить старшую тетраду 0–F PUSH #00h ; место для кода ошибки PUSH address ; поместить адрес в стек SUB #06, SP CALL #hunt POP R10 ; вернуть данные в R10 POP R11 ; вернуть данные в R11 ADD #04h, SP ; освободить место для адреса и команд POP R9 ; вернуть код ошибки CMP #00h, R9 JZ retry ; повтор при неудаче MOV #0FFh, R7 dela4 MOV #0B4Fh, R6 dela3 DEC R6 JNZ dela3 DEC R7 JNZ dela4 MOV #0000h, R5 ; очистка (убедиться, что очищается старший байт) MOV.B address, R5 ; R5 ? младший байт AND #000Fh, R5 ; маска на старшую тетраду MOV.B LCD_Tab(R5),LCD1+4 ; отобразить младшую тетраду 0–F MOV.B address, R5 ; R5 ? младший байт AND 00F0h, R5 ; маска на младшую тетраду RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо MOV.B LCD_Tab(R5), LCD1+5 ; отобразить старшую тетраду 0–F JMP retry ; повтор для следующего адреса ;**************************************************************************** ; Завершение пользовательской программы ;**************************************************************************** ;**************************************************************************** ; Подпрограммы верхнего уровня, п/п нижнего уровня вызываются индивидуально ; для реализации различных протоколов ;**************************************************************************** ;**************************************************************************** ; Поиск это модифицированная часть протокола «Чтение байта» ;**************************************************************************** hunt PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса CALL #sbit ; отправить стартовую последовательность и адрес CALL #sendzero ; отправить 0 для записи CALL #ack ; ждём подтверждения (ACK) MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ;**************************************************************************** ; Подпрограммы нижнего уровня, общие для всех протоколов ;**************************************************************************** ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; отправка стартовой последовательности и адреса ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbit ; «отпустить» обе линии BIC.B #DNC, DIR ; проверка освобождения шины MOV #05h, R10 ; счётчик на 50 микросекунд wait MOV.B IN, R11 ; копировать состояние входов в R11 AND #DNC, R11 ; маска входов CMP #DNC, R11 ; если линии SDA или SCL в лог. «0»то шина занята JNZ busy DEC R10 ; декремент счётчика JNZ wait rsbit BIC.B #DNC, DIR ; дополнительное освобождение линии с целью ; использования этой же подпрограммы для ; команды повторяющегося старта ; отправка стартовой последовательности BIS.B #SDA, DIR BIS.B #SCL, DIR ; отправка адреса MOV.B #07h, R13 ; счётчик на 7 бит адреса MOV.B R7, R11 ; копировать адрес в R11 ashift RLA.B R11 ; сдвиг влево, при этом СЗР 7-битного адреса ; будет находиться на 7-й позиции MOV.B R11, R12 ; скопировать его для возможности маскирования ; без потери данных AND.B #080h, R12 ; маскировать все биты кроме СЗР CMP.B #00h, R12 ; сравнить с 0 JNZ one CALL #sendzero ; отправить «1» JMP zero one CALL #sendone ; отправить «0» zero DEC R13 ; декремент счётчика JNZ ashift ; если счётчик <7 бит, повторить сдвиг RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; подтверждение (ACK) не принято, отправить STOP и busy ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbusy CALL #pbit ; отправить STOP и busy ADD #02h, SP ; удалить данные из стека, так как ; инструкция RET не использовалась MOV.B #00h, 28(SP) ; код ошибки POP R13 ; восстановление регистров POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Обработка занятости системы ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * busy3 ADD #06h, SP ; удаление лишних данных процедур sendone или sendzero busy ADD #02h, SP ; удалить данные из стека, так как ; инструкция RET не использовалась MOV.B #00h, 28(SP) ; код ошибки POP R13 ; восстановление регистров POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправить «1» ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sendone PUSH R10 PUSH R11 BIC.B #SDA, DIR ; установить лог. «1» на линии SDA BIC.B #SCL, DIR ; установить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство MOV.B #04h, R11 ; установить число тактов для верного времени clkext MOV.B IN, R10 ; проверка шины DEC R11 JZ busy3 ; арбитраж – время истекло AND.B #SCL, R10 ; проверка линии SCL JZ clkext ; арбитраж: убедиться, что на линии SDA действительно лог. «1», иначе приоритет ; отдаётся другому ведущему устройству MOV.B IN, R10 ; проверка шины AND.B #SDA, R10 ; маскировать всё, кроме SDA JZ busy3 BIS.B #SCL, DIR ; освободить линию SCL MOV.B IN, R10 ; определение повторяющейся ; стартовой последовательности AND.B #SDA, R10 JZ busy3 POP R11 POP R10 RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправить «0» ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sendzero PUSH R10 PUSH R11 BIS.B #SDA, DIR ; выставить лог. «0» на линии SDA BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство MOV #04h, R11 ; счётчик времени перехода SCL в «1» clke MOV.B IN, R10 ; проверка шины DEC R11 JZ busy3 ; арбитраж – время истекло AND.B #SCL, R10 ; проверка линии SCL JZ clke BIS.B #SCL, DIR ; освободить линию SCL POP R11 POP R10 RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Ожидание подтверждения (ACK) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ack BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство ;MOV #008h, R11 ; счётчик на ?50 мкс MOV #02FFh, R11 ; удлинённый счётчик для батареи PS100Z–200 clkex MOV.B IN, R10 ; проверка шины DEC R11 JZ busy ; арбитраж – время истекло AND.B #SCL, R10 ; проверка линии SCL JZ clkex ; ожидание подтверждения (ACK) (SDA переходит в лог. «0») MOV #05F6h, R11 ; счётчик таймаута для NACK wack MOV.B IN, R10 ; проверка шины DEC R11 JZ sbusy ; таймаут NACK–– отправить бит P и повторить попытку AND.B #SDA, R10 ; маскировать всё, кроме SDA JNZ wack ; приём ACK или ожидание таймаута BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка стоповой последовательности ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * pbit BIS.B #SDA, DIR ; выставить лог. «0» на линии SDA BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL NOP BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL NOP BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA RET ;––– очистка ЖКИ show_clr MOV #15, r5 ; очистка дисплейной памяти show_clr1 MOV.b #0, LCD1–1(r5) DEC r5 JNZ show_clr1 RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Определения для ЖКИ ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LCD_TYPE ;–––ЖКИ модуля STK/EVK a .equ 01h b .equ 02h c .equ 10h d .equ 04h e .equ 80h f .equ 20h g .equ 08h h .equ 40h LCD_Tab .byte a+b+c+d+e+f ;отображает ”0” .byte b+c ; отображает”1” .byte a+b+d+e+g ; отображает”2” .byte a+b+c+d+g ; отображает”3” .byte b+c+f+g ; отображает”4” .byte a+c+d+f+g ; отображает”5” .byte a+c+d+e+f+g ; отображает”6” .byte a+b+c ; отображает”7” .byte a+b+c+d+e+f+g ; отображает”8” .byte a+b+c+d+f+g ; отображает”9” .byte a+b+c+e+f+g ; отображает”A” .byte c+d+e+f+g ; отображает”B” b .byte a+d+e+f ; отображает”C” .byte b+c+d+e+g ; отображает”D” d .byte a+d+e+f+g ; отображает”E” .byte a+e+f+g ; отображает”F” LCD_Tab_End .even ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Вектора прерываний ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * .sect ”Int_Vect”,05FFh–1 ; с программой монитора .word RESET ; POR, внеш. Reset, Watchdog .end Приложение C Программа работы со смарт-батареей;**************************************************************************** ; Программа SBData ; –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– ; Читает температуру, напряжение, производителя, хим. конфигурацию, ёмкость, и ; предупреждение об оставшейся ёмкости из монитора батареи с шиной SMBus. ; Также производится запись в регистр «Предупреждение об оставшейся ёмкости» ; (RemainingCapacityAlarm). ; ; В данном частном случае применялся батарейный смарт-модуль PowerSmart PS100Z–200 ; Другие данные из батареи можно читать, меняя команды. ; Контроллер смарт-батареи PowerSmart поддерживает стандарт SMBus V1.0 ; и спецификацию Smart Battery data ; Настоящая конфигурация программы написана для использования с пользовательской ; программой под управлением программы монитора ; на отладочной плате 337 EVK, подпрограммы SMBus находятся в EPROM. Также требуется ; Таблица ASCII символов для ЖКИ ; Здесь использован файл ASCII.txt. На него ссылается указатель alcd. ;**************************************************************************** RAM_orig .set 00240h ; Стартовый адрес SP_orig .set 005DEh ; указатель стека EPROM .set 08850h ; Размещение EPROM ;––– Определения управляющих регистров WDTCTL .equ 0120h WDTHold .equ 80h WDT_wrkey .equ 05A00h ;PORT 0 P0IE .equ 015h P0DIR .equ 012h P0IN .equ 010h P0OUT .equ 011h ; port 2 P2IN .equ 028h P2OUT .equ 029h P2IE .equ 02Dh P2SEL .equ 02Eh P2DIR .equ 02Ah SDA .equ 020h SCL .equ 080h DNC .equ 0A0h OUT .equ P2OUT DIR .equ P2DIR IN .equ P2IN LCD1 .equ 031h LCDM .equ 030h IE1 .equ 0h IE2 .equ 01h IFG1 .equ 02h IFG2 .equ 03h block .equ 0550h alcd .equ 0B500h ; Размещение таблицы символов ASCII для ЖКИ ;**************************************************************************** ; Reset : Initialize processor ;**************************************************************************** .sect ”MAIN”,RAM_orig RESET MOV #SP_orig,SP ; Инициализация указателя стека ;**************************************************************************** ; Начало пользовательской программы ;**************************************************************************** repeat CMP.B #0FFh, R8 JNZ skp INC.B R7 ; инкремент старшего байта значения ; для протокола записи слова MOV.B #00h, R8 skp INC.B R8 ; инкремент значения ; для протокола записи слова skp0 ; Чтение температуры CALL #show_clr PUSH #00h ; место для кода ошибки PUSH #000Bh ; поместить адрес в стек PUSH #008h ; поместить команду чтения ; температуры батареи PUSH #00h ; зарезервировать байт для данных PUSH #00h ; зарезервировать байт для данных CALL #rwp POP R10 ; поместить данные в R10 POP R11 ; поместить данные в R11 ADD #04h, SP ; освободить место команды и адреса POP R9 ; читать код ошибки CMP #00h, R9 JZ skp0 ; повтор при неудаче RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 XOR R10, R11 ; объединить 2 байта данных MOV R11, R12 SUB #0AAAh, R12 ; перевод в градусы Цельсия CALL #display ; вызов подпрограммы отображения XOR.B #40h, LCD1+1 ; добавить децимальную точку MOV.B alcd+’T’, LCD1+5 CALL #delay ; вызов подпрограммы задержки skp1 ; чтение напряжения CALL #show_clr PUSH #00h ; место для кода ошибки PUSH #000Bh ; поместить адрес в стек PUSH #009h ; поместить в стек команду ; чтения напряжения батареи PUSH #00h ; зарезервировать байт для данных PUSH #00h ; зарезервировать байт для данных CALL #rwp POP R10 ; поместить данные в R10 POP R11 ; поместить данные в R11 ADD #04h, SP ; освободить место команды и адреса POP R9 ; читать код ошибки CMP #00h, R9 JZ skp1 ; повтор при неудаче RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 XOR R10, R11 ; объединить 2 байта данных MOV R11, R12 CALL #display ; вызов подпрограммы отображения XOR.B #40h, LCD1+3 ; добавить децимальную точку MOV.B alcd+’U’, LCD1+5 CALL #delay ; вызов подпрограммы задержки skp2 ; чтение названия производителя CALL #show_clr PUSH #00h ; место для кода ошибки PUSH #000Bh ; поместить адрес в стек PUSH #0020h ; поместить в стек команду ; чтения имени производителя PUSH #block ; зарезервировать байт для данных PUSH #00h ; зарезервировать байт для данных CALL #blkr POP R10 ; поместить данные в R10 ADD #06h, SP POP R9 ; читать код ошибки CMP #00h, R9 JZ skp2 ; повтор при неудаче MOV.B block, R5 ; копировать символ MOV.B alcd(R5), LCD1+6 ; отобразить символ MOV.B block+1, R5 ; копировать символ MOV.B alcd(R5), LCD1+5 ; отобразить символ MOV.B block+2, R5 ; копировать символ MOV.B alcd(R5), LCD1+4 ; отобразить символ MOV.B block+3, R5 ; копировать символ MOV.B alcd(R5), LCD1+3 ; отобразить символ MOV.B block+4, R5 ; копировать символ MOV.B alcd(R5), LCD1+2 ; отобразить символ MOV.B block+5, R5 ; копировать символ MOV.B alcd(R5), LCD1+1 ; отобразить символ MOV.B block+6, R5 ; копировать символ MOV.B alcd(R5), LCD1+0 ; отобразить символ CALL #delay ; вызов подпрограммы задержки skp3 ; чтение химической конфигурации CALL #show_clr PUSH #00h ; место для кода ошибки PUSH #000Bh ; поместить адрес в стек PUSH #0022h ; поместить в стек команду ; чтения химической конфигурации PUSH #block ; зарезервировать байт для данных PUSH #00h ; зарезервировать байт для данных CALL #blkr POP R10 ; поместить данные в R10 ADD #06h, SP POP R9 ; читать код ошибки CMP #00h, R9 JZ skp3 ; повтор при неудаче MOV.B block, R5 ; копировать символ MOV.B alcd(R5), LCD1+6 ; отобразить символ MOV.B block+1, R5 ; копировать символ MOV.B alcd(R5), LCD1+5 ; отобразить символ MOV.B block+2, R5 ; копировать символ MOV.B alcd(R5), LCD1+4 ; отобразить символ MOV.B block+3, R5 ; копировать символ MOV.B alcd(R5), LCD1+3 ; отобразить символ CALL #delay ; вызов подпрограммы задержки skp4 ; чтение ёмкости батареи CALL #show_clr PUSH #00h ; место для кода ошибки PUSH #000Bh ; поместить адрес в стек PUSH #0018h ; поместить в стек команду ; чтения ёмкости батареи PUSH #00h ; зарезервировать байт для данных PUSH #00h ; зарезервировать байт для данных CALL #rwp POP R10 ; поместить данные в R10 POP R11 ; поместить данные в R11 ADD #04h, SP ; освободить место команды и адреса POP R9 ; читать код ошибки CMP #00h, R9 JZ skp4 ; повтор при неудаче RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 XOR R10, R11 MOV R11, R12 CALL #display ; вызов подпрограммы отображения XOR.B #40h, LCD1+3 ; добавить децимальную точку MOV.B alcd+’A’, LCD1+1 MOV.B alcd+’H’, LCD1+0 CALL #delay ; вызов подпрограммы задержки skp5 ; запись предупреждения об оставшейся ёмкости (RemainingCapacityAlarm) CALL #show_clr PUSH #00h ; место для кода ошибки PUSH #000Bh ; поместить адрес в стек PUSH #001h ; поместить в стек команду PUSH R8 ; зарезервировать байт для данных PUSH R7 ; зарезервировать байт для данных CALL #wwp POP R11 ; поместить данные в R11 POP R10 ; поместить данные в R10 ADD #04h, SP ; освободить место команды и адреса POP R9 ; читать код ошибки CMP #00h, R9 JZ skp5 ; повтор при неудаче RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 XOR R10, R11 MOV R11, R12 CALL #display ; вызов подпрограммы отображения MOV.B alcd+’S’, LCD1+6 CALL #delay ; вызов подпрограммы задержки skp6 ; считывание оставшейся ёмкости (RemainingCapacityAlarm) CALL #show_clr PUSH #00h ; место для кода ошибки PUSH #000Bh ; поместить адрес в стек PUSH #001h ; поместить в стек команду PUSH #00h ; зарезервировать байт для данных PUSH #00h ; зарезервировать байт для данных CALL #rwp POP R10 ; поместить данные в R10 POP R11 ; поместить данные в R11 ADD #04h, SP ; освободить место команды и адреса POP R9 ; читать код ошибки CMP #00h, R9 JZ skp6 ; повтор при неудаче RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 RLA R11 XOR R10, R11 MOV R11, R12 CALL #display ; вызов подпрограммы отображения MOV.B alcd+’R’, LCD1+6 CALL #delay ; вызов подпрограммы задержки JMP repeat ; завершение программы, бесконечный цикл ;**************************************************************************** ; Окончание пользовательской программы ;**************************************************************************** delay PUSH R6 PUSH R7 MOV #00DFh, R7 ; вложенный цикл задержки dela4 MOV #0D40h, R6 dela3 DEC R6 JNZ dela3 DEC R7 JNZ dela4 POP R7 POP R6 RET display ; подпрограмма отображения PUSH R5 PUSH R12 PUSH R13 PUSH R14 PUSH R15 MOV #16, R15 ; процедура преобразования hex ? BCD CLR R14 ; входные значения в R12, выходные в R13 и R14 CLR R13 ls1 RLA R12 DADD R13, R13 DADD R14, R14 DEC R15 JNZ ls1 MOV.B R13, R5 ; поместить 2 младших BCD-разряда в R5 AND #000Fh, R5 ; маскировать всё, кроме младшей тетрады MOV.B LCD_Tab(R5),LCD1+0 ; Отобразить младшую тетраду MOV.B R13, R5 ; поместить 2 младших BCD-разряда в R5 AND #00F0h, R5 ; маскировать всё, кроме старшей тетрады RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо MOV.B LCD_Tab(R5), LCD1+1 ; Отобразить старшую тетраду SWPB R13 ; обмен байтами в R13 MOV.B R13, R5 ; поместить 2 старших BCD-разряда в R5 AND #000Fh, R5 ; маскировать всё, кроме младшей тетрады MOV.B LCD_Tab(R5),LCD1+2 ; Отобразить младшую тетраду MOV.B R13, R5 ; поместить 2 старших BCD-разряда в R5 AND #00F0h, R5 ; маскировать всё, кроме старшей тетрады RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо MOV.B LCD_Tab(R5), LCD1+3 ; Отобразить старшую тетраду MOV.B R14, R5 ; поместить 2 младших BCD-разряда в R5 AND #000Fh, R5 ; маскировать всё, кроме младшей тетрады MOV.B LCD_Tab(R5),LCD1+4 ; Отобразить младшую тетраду MOV.B R14, R5 ; поместить 2 младших BCD-разряда в R5 AND #00F0h, R5 ; маскировать всё, кроме старшей тетрады RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо RRA R5 ; сдвиг вправо MOV.B LCD_Tab(R5), LCD1+5 ; Отобразить старшую тетраду POP R15 POP R14 POP R13 POP R12 POP R5 RET .sect ”smbus”, EPROM ;**************************************************************************** ; Подпрограммы верхнего уровня, п/п нижнего уровня вызываются индивидуально ; для реализации различных протоколов ;**************************************************************************** ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Быстрая команда» 1 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-–––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; стоп (stop) из ; ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; не используется unused ; не используется unused ; не используется unused ; адрес address старшая область памяти high mem ; ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; SUB #06h, SP ; остальные параметры не используются ; CALL #qcp ; ADD #08h, SP ; вычесть объём параметров ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * qcp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 28(SP), R7 ; получить адрес из стека CALL #sbit ; отправить стартовую посылку и адрес ;CALL #sendone ; отправить «1» или CALL #sendzero ; отправить «0» CALL #ack ; ждём подтверждения (ACK) CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Записать байт» 4 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; данные (data) из ; подтверждение(acknowledge) в ? ; стоп (stop) из ; ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; не используется unused ; данные data ; команда command ; адрес address старшая область памяти high mem ; ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #001h ; поместить команду в стек ; PUSH #055h ; отправляемые данные ; SUB #02h, SP ; остальные параметры не используются ; CALL #wbp ; ADD #08h, SP ; вычесть объём параметров ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок wbp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) MOV.B 24(SP), R8 ; отправка данных CALL #sbyte ; отправить байт данных CALL #ack ; ждём подтверждения (ACK) CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Записать слово» 5 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; данные (data) из ; подтверждение(acknowledge) в ? ; данные (data) из ; подтверждение(acknowledge) в ? ; стоп (stop) из ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; не используется unused ; данные data ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #001h ; код команды ; PUSH #0AAh ; младший отправляемый байт ; PUSH #055h ; старший отправляемый байт ; CALL #wwp ; ADD #08h, SP ; освободить место, занимаемое параметрами ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * wwp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) MOV.B 24(SP), R8 ; данные для записи – младший байт CALL #sbyte ; отправить младший байт данных CALL #ack ; ждём подтверждения (ACK) MOV.B 22(SP), R8 ; данные для записи – старший байт CALL #sbyte ; отправить старший байт данных CALL #ack ; ждём подтверждения (ACK) CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Читать байт» 6 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; данные (data) в ? ; неподтверждение(NACK) из ; стоп (stop) из ; ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; младший байт данных data ; не используется unused ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #000Bh ; поместить адрес в стек ; PUSH #008h ; код команды чтения температуры батареи ; PUSH #00h ; зарезервировать байт для данных (не используется) ; PUSH #00h ; зарезервировать байт для данных ; CALL #rbp ; POP R10 ; переместить данные в R10 ; ADD #06h, SP ; освободить место команды и адреса ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * rbp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) CALL #rsbit ; отправить повторяющиеся стартовую посылку и адрес CALL #sendone ; отправить «1» для чтения CALL #ack ; ждём подтверждения (ACK) CALL #rbyte ; принять байт данных CALL #nack ; отправить неподтверждение (NACK) CALL #pbit ; отправить стоповую посылку MOV.B R14, 22(SP) ; копировать байт данных в стек MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Читать слово» 7 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт ; ––––––––––––––––––––––––––-––––––––––––––––––––––––––-–––––––––––––––––––––––– ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; данные (data) в ? ; подтверждение(acknowledge) в ? ; данные (data) в ? ; подтверждение(acknowledge) в ? ; стоп (stop) из ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; младший байт данных low data byte ; старший байт данных high data byte ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #008h ; код команды “температура батареи” ; PUSH #00h ; зарезервировать байт под принимаемые данные ; PUSH #00h ; зарезервировать байт под принимаемые данные ; CALL #rwp ; POP R10 ; переместить данные в R10 ; POP R11 ; переместить данные в R11 ; ADD #04h, SP ; освободить место, занимаемое командой и адресом ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * rwp PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) CALL #rsbit ; отправить повторяющиеся стартовую посылку и адрес CALL #sendone ; отправить «1» для чтения CALL #ack ; ждём подтверждения (ACK) CALL #rbyte ; принять младший байт данных MOV.B R14, 22(SP) ; сохранить младший байт данных в стеке CALL #sack ; ждём подтверждения (ACK) CALL #rbyte ; принять старший байт данных CALL #nack ; отправить неподтверждение (NACK) CALL #pbit ; отправить стоповую посылку MOV.B R14, 24(SP) ; сохранить старший байт данных в стеке MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Запись блока» 8 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт, блок памяти ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; чтение/запись(R/W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; счётчик байт (byte count) из ; подтверждение(acknowledge) в ? ; данные (data) из ; подтверждение(acknowledge) в ? ; ; данные (data) в ? ; подтверждение(acknowledge) в ? ; ; данные и ACK повторяются n раз ; стоп (stop) из ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; счётчик байт byte count ; указатель блока block pointer ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #0020h ; код команды “температура батареи” ; PUSH #00550h ; указатель на начало блока ; PUSH #00h ; зарезервировать байт под счётчик ; CALL #blkw ; POP R10 ; переместить данные в R10 ; ADD #06h, SP ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * blkw PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса MOV 24(SP), R9 ; стартовый адрес блока MOV.B #00h, R15 ; циклический байтовый счётчик CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) MOV.B 22(SP), R8 ; копировать счётчик байт CALL #sbyte ; отправить счётчик байт CALL #ack ; ждём подтверждения (ACK) blk_rep MOV.B 0(R9), R8 ; передать данные из блока CALL #sbyte ; отправить байт данных CALL #ack ; ждём подтверждения (ACK) INC R15 ; инкремент счётчика положения блока INC R9 ; инкремент указателя блока CMP 22(SP), R15 ; проверка завершения данных JNZ blk_rep ; повтор до завершения CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Протокол «Чтение блока» 9 ; ========================================================================== ; Влияние на регистры: нет ; Влияние на память: стек, максимум 40 байт, блок памяти ; Описание Шаг Направление ; ––––––––––––––––––––––––––––––––––––––––––––––––––––-––––––––––––––––––––––––– ; старт (start) из ; адрес(address) из ; запись(W) из ; подтверждение(acknowledge) в ? ; команда (command) из ; подтверждение(acknowledge) в ? ; старт (start) из ; адрес(address) из ; чтение(R) из ; подтверждение(acknowledge) в ? ; счётчик байт (byte count) в ? ; подтверждение(acknowledge) из ; данные (data) в ? ; подтверждение(acknowledge) из ; ; данные и ACK повторяются n раз ; неподтверждение(NACK) из ; стоп (stop) из ; Параметры в стеке ; –––––––––––––––––––– ; флаг ошибки error_flag младшая область памяти low mem ; счётчик байт byte count ; указатель блока block pointer ; команда command ; адрес address старшая область памяти high mem ; ––––––––––––––––– ; Пример использования ; –––––––––––––– ; PUSH #00h ; место для кода ошибки ; PUSH #00Bh ; поместить адрес в стек ; PUSH #0020h ; код команды “температура батареи” ; PUSH #00550h ; указатель на начало блока ; PUSH #00h ; зарезервировать байт под счётчик ; CALL #blkr ; POP R10 ; переместить счётчик в R10 ; ADD #06h, SP ; POP R9 ; читать из стека код ошибки ; CMP #00h, R9 ; JZ error ; ошибочное завершение – вызов обработчика ошибок ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * blkr PUSH SR PUSH R7 PUSH R8 PUSH R9 PUSH R14 PUSH R15 PUSH R10 PUSH R11 PUSH R12 PUSH R13 MOV.B #00h, R15 ; циклический байтовый счётчик MOV.B 26(SP), R8 ; параметр команды MOV.B 28(SP), R7 ; параметр адреса MOV 24(SP), R9 ; стартовый адрес блока CALL #sbit ; отправить стартовую посылку и адрес CALL #sendzero ; отправить «0» для записи CALL #ack ; ждём подтверждения (ACK) CALL #sbyte ; отправить код команды CALL #ack ; ждём подтверждения (ACK) CALL #rsbit ; отправить повторяющиеся стартовую посылку и адрес CALL #sendone ; отправить «1» для чтения CALL #ack ; ждём подтверждения (ACK) CALL #rbyte MOV.B R14, 22(SP) ; поместить счётчик в стек CALL #sack ; отправить подтверждение (ACK) rblk_rep CALL #rbyte ; принять байт данных MOV.B R14, 0(R9) ; переместить данные из блока INC R15 ; инкремент счётчика положения блока INC R9 ; инкремент указателя блока CMP 22(SP), R15 ; проверка завершения данных JZ blk_done ; повтор до завершения CALL #sack ; отправить подтверждение (ACK) CMP 22(SP), R15 ; проверка завершения данных JNZ rblk_rep ; повтор до завершения blk_done CALL #nack ; отправить неподтверждение (NACK) CALL #pbit ; отправить стоповую посылку MOV.B #01h, 30(SP) ; возвращает «1» при успешном завершении POP R13 POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ;**************************************************************************** ; Подпрограммы нижнего уровня, общие для всех протоколов ;**************************************************************************** ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; отправка стартовой последовательности и адреса ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbit ; «отпустить» обе линии BIC.B #DNC, DIR ; проверка освобождения шины MOV #05h, R10 ; счётчик на 50 микросекунд wait MOV.B IN, R11 ; копировать состояние входов в R11 AND #DNC, R11 ; маска входов CMP #DNC, R11 ; если линии SDA или SCL в лог. «0»то шина занята JNZ busy DEC R10 ; декремент счётчика JNZ wait rsbit BIC.B #DNC, DIR ; дополнительное освобождение линии с целью ; использования этой же подпрограммы для ; команды повторяющегося старта ; отправка стартовой последовательности BIS.B #SDA, DIR BIS.B #SCL, DIR ; отправка адреса MOV.B #07h, R13 ; счётчик на 7 бит адреса MOV.B R7, R11 ; копировать адрес в R11 ashift RLA.B R11 ; сдвиг влево, при этом СЗР 7-битного адреса ; будет находиться на 7-й позиции MOV.B R11, R12 ; скопировать его для возможности маскирования ; без потери данных AND.B #080h, R12 ; маскировать все биты кроме СЗР CMP.B #00h, R12 ; сравнить с 0 JNZ one CALL #sendzero ; отправить «1» JMP zero one CALL #sendone ; отправить «0» zero DEC R13 ; декремент счётчика JNZ ashift ; если счётчик <7 бит, повторить сдвиг RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; подтверждение (ACK) не принято, отправить STOP и busy ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbusy CALL #pbit ; отправить STOP и busy ADD #02h, SP ; удалить данные из стека, так как ; инструкция RET не использовалась MOV.B #00h, 28(SP) ; код ошибки POP R13 ; восстановление регистров POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Обработка состояния занятости (busy) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * busy3 ADD #06h, SP ; удалить лишние данные от подпрограмм ; sendone или sendzero busy ADD #02h, SP ; удалить данные из стека, так как ; инструкция RET не использовалась MOV.B #00h, 28(SP) ; код ошибки POP R13 ; восстановить регистры POP R12 POP R11 POP R10 POP R15 POP R14 POP R9 POP R8 POP R7 POP SR RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправить «1» ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sendone PUSH R10 PUSH R11 BIC.B #SDA, DIR ; установить лог. «1» на линии SDA BIC.B #SCL, DIR ; установить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство MOV.B #04h, R11 ; установить число тактов для верного времени clkext MOV.B IN, R10 ; проверка шины DEC R11 JZ busy3 ; арбитраж – время истекло AND.B #SCL, R10 ; проверка линии SCL JZ clkext ; арбитраж: убедиться, что на линии SDA действительно лог. «1», иначе приоритет ; отдаётся другому ведущему устройству MOV.B IN, R10 ; проверка шины AND.B #SDA, R10 ; маскировать всё, кроме SDA JZ busy3 BIS.B #SCL, DIR ; освободить линию SCL MOV.B IN, R10 ; определение повторяющейся ; стартовой последовательности AND.B #SDA, R10 JZ busy3 POP R11 POP R10 RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправить «0» ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sendzero PUSH R10 PUSH R11 BIS.B #SDA, DIR ; выставить лог. «0» на линии SDA BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство MOV #04h, R11 ; счётчик времени перехода SCL в «1» clke MOV.B IN, R10 ; проверка шины DEC R11 JZ busy3 ; арбитраж – время истекло AND.B #SCL, R10 ; проверка линии SCL JZ clke BIS.B # SCL, DIR ; освободить линию SCL POP R11 POP R10 RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Ожидание подтверждения (ACK) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ack BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство ;MOV #008h, R11 ; счётчик на ?50 мкс MOV #02FFh, R11 ; удлинённый счётчик для батареи PS100Z–200 clkex MOV.B IN, R10 ; проверка шины DEC R11 JZ busy ; арбитраж – время истекло AND.B #SCL, R10 ; проверка линии SCL JZ clkex ; ожидание подтверждения (ACK) (SDA переходит в лог. «0») MOV #05F6h, R11 ; счётчик таймаута для NACK wack MOV.B IN, R10 ; проверка шины DEC R11 JZ sbusy ; таймаут NACK–– отправить бит P и повторить попытку AND.B #SDA, R10 ; маскировать всё, кроме SDA JNZ wack ; приём ACK или ожидание таймаута BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка стоповой последовательности ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * pbit BIS.B #SDA, DIR ; выставить лог. «0» на линии SDA BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL NOP BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL NOP BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка байта (используются также sendzero и sendone) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sbyte ; отправка данных MOV.B #08h, R13 ; счётчик на ?50 мкс MOV.B R8, R11 ; копировать данные в R11 dshift MOV.B R11, R12 AND.B #080h, R12 ; маскировать все биты, кроме СЗР CMP.B #00h, R12 ; сравнить с 0 JNZ on CALL #sendzero ; отправить «1» JMP zer on CALL #sendone ; отправить «0» zer RLA.B R11 ; сдвиг влево, отправляемый бит в СЗР DEC R13 ; декремент счётчика на 8 JNZ dshift RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Приём байта ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * rbyte MOV.B #08h, R12 ; счётчик на 8 бит данных BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA rrep BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL MOV #0035h, R13 ; удлинённый счётчик для батареи PS100Z–200 ; удлинение тактового сигнала clkxtn MOV.B IN, R10 ; проверка шины DEC R13 JZ busy ; выход по таймауту AND.B #SCL, R10 JZ clkxtn ; ожидание, если SCL не «1» MOV.B IN, R10 ; проверка шины RLA.B R11 ; move over for input as LSB AND.B #SDA, R10 ; проверка SDA JZ inzero BIS.B #01h, R11 ; установить «1» в МЗР inzero DEC R12 JNZ rrep ; продолжение для оставшейся части байта MOV.B R11, R14 ; копирование данных BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка неподтверждения (NACK) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * nack BIC.B #SDA, DIR ; выставить лог. «1» на линии SDA BIS.B #SCL, DIR ; выставить лог. «0» на линии SCL BIC.B #SCL, DIR ; выставить лог. «1» на линии SCL ; проверка удлинения тактового сигнала (clock low extending), ; чтобы не опережать ведомое устройство ; ждём установки «1» на линии SCL clkn MOV.B IN, R10 AND.B #SCL, R10 ; проверка линии SCL JZ clkn BIS.B #SCL, DIR ; «отпустить» SCL RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Отправка подтверждения (ACK) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * sack ; ждём, пока ведомый «отпустит» линию SDA MOV #000Fh, R11 ; счётчик на ?50 мкс swaita MOV.B IN, R10 ; проверка шины DEC R11 JZ busy AND.B #SDA, R10 ; проверка SCL JZ swaita BIS.B #SDA, DIR ; перевести SDA в «0» BIC.B #SCL, DIR ; перевести SCL в «1» MOV #000Fh, R11 ; счётчик на ?50 мкс swait MOV.B IN, R10 ; проверка шины DEC R11 JZ busy AND.B #SCL, R10 ; проверка SCL JZ swait BIS.B #SCL, DIR ; перевести SCL в «0» BIC.B #SDA, DIR ; «отпустить» SDA RET ;––– очистка ЖКИ show_clr MOV #15, r5 ; очистка дисплейной памяти show_clr1 MOV.b #0, LCD1–1(r5) DEC r5 JNZ show_clr1 RET ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Определения для ЖКИ ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LCD_TYPE ;–––ЖКИ модуля STK/EVK a .equ 01h b .equ 02h c .equ 10h d .equ 04h e .equ 80h f .equ 20h g .equ 08h h .equ 40h ;––– Определения символов LCD_Tab .byte a+b+c+d+e+f ; отображает”0” .byte b+c ; отображает”1” .byte a+b+d+e+g ; отображает”2” .byte a+b+c+d+g ; отображает”3” .byte b+c+f+g ; отображает”4” .byte a+c+d+f+g ; отображает”5” .byte a+c+d+e+f+g ; отображает”6” .byte a+b+c ; отображает”7” .byte a+b+c+d+e+f+g ; отображает”8” .byte a+b+c+d+f+g ; отображает”9” .byte 0 ; отображает ”:” пустой .byte g ; отображает”;” – .byte a+d+e+f ; отображает”<” [ .byte d+g ; отображает”=” .byte a+b+c+d ; отображает”>” ] .byte a+b+e+g ; отображает”?” .byte a+b+d+e+f+g ; отображает”@” .byte a+b+c+e+f+g ; отображает”A” .byte c+d+e+f+g ; отображает”B” b .byte a+d+e+f ; отображает”C” .byte b+c+d+e+g ; отображает”D” d .byte a+d+e+f+g ; отображает”E” .byte a+e+f+g ; отображает”F” .byte a+b+c+d+f+g ; отображает”G” .byte b+c+e+f+g ; отображает”H” .byte b+c ; отображает”I” .byte b+c+d+e ; отображает”J” .byte 0 ; отображает”K” .byte d+e+f ; отображает”L” .byte a+b+c+e+f ; отображает”M” .byte c+e+g ; отображает”N” n .byte c+d+e+g ; отображает”O” o .byte a+b+e+f+g ; отображает”P” .byte 0 ; отображает”Q” .byte e+g ; отображает”R” r .byte a+c+d+f+g ; отображает”S” .byte d+e+f+g ; отображает”T” t .byte c+d+e ; отображает”U” u .byte 0 ; отображает”V” .byte 0 ; отображает”W” .byte 0 ; отображает”X” .byte b+c+d+f+g ; отображает”Y” .byte a+b+d+e+g ; отображает”Z” 2 LCD_Tab_End .even ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Вектора прерываний ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; .sect ”Int_Vect”,0FFFFh–1 ; без программы монитора ; .word RESET ; POR, внеш. Reset, Watchdog ; .end .sect ”Int_Vect”,05FFh–1 ; с программой монитора .word RESET ; POR, внеш. Reset, Watchdog .end Приложение C Программа ведомого устройства шины SMBus ;**************************************************************************** ; Программа ведомого устройства шины SMBus ;**************************************************************************** USER_END .set 0FFFFh Device .set 325 ;––– Определения управляющих регистров SRE .equ 0h IE1 .equ 0h IE2 .equ 01h IFG1 .equ 02h IFG2 .equ 03h WDTCTL .equ 0120h WDTHold .equ 80h WDT_wrkey .equ 05A00h CPUOFF .set 10h OSCOFF .set 20h ;Порт PORT 0 P0IE .equ 015h P0DIR .equ 012h P0IN .equ 010h P0OUT .equ 011h P0IES .equ 014h P0IFG .equ 013h ;Порт port 2 P2IN .equ 028h P2OUT .equ 029h P2IE .equ 02Dh P2SEL .equ 02Eh P2DIR .equ 02Ah LCD1 .equ 031h LCDM .equ 030h OUT .equ P0OUT IN .equ P0IN DIR .equ P0DIR SDA .equ 010h SCL .equ 020h DNC .equ 030h ; Расположение таблицы Table .equ 0300h ;**************************************************************************** ; Reset : инициализация процессора ;**************************************************************************** .sect ”onreset”,0FFFEh .word INIT .sect ”intv”, 0FFE0h .word rbp .sect ”MAIN”,0C000h INIT .if Device = 325 MOV #03C0h, SP .endif .if Device = 337 MOV #05D0h, SP .endif MOV #(WDTHold+WDT_wrkey),&WDTCTL ; Остановить сторожевой таймер Watchdog Timer ; Инициализация порта port2 BIC.B #DNC, DIR ; Биты 1 и 0 - входы BIC.B #DNC, OUT ; установить лог. «1» на линиях SDA и SCL BIS.B #SDA, P0IE ; разрешить прерывания по P0.4 BIS.B #SDA, P0IES ; прерывание по спаду на P0.4 RESET nready ; шина не находится в состоянии готовности / нет стартовой посылки waddr ; возврат сюда, если неверный адрес устройства MOV.B #000h, error ; сброс флага ошибки MOV.B #055h, address ; адрес = 55h MOV.B #09h, data ; данные = 09h EINT ; общее разрешение прерываний ;**************************************************************************** ; Начало пользовательской программы ;**************************************************************************** repeat JMP repeat ; ожидание прерывания ;**************************************************************************** ; Завершение пользовательской программы ;**************************************************************************** ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; приём байта (здесь обрабатывается прерывание) ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * rbp ;PUSH R11 ; если известно, что стартовая посылка длительная, ; можно добавить эти строки ;PUSH R12 ;PUSH R13 ;PUSH R14 BIC.B #SDA, P0IFG ; очистить флаг прерывания ;**************************************************************************** ; проверка стартовой последовательности ;**************************************************************************** wait2 MOV.B IN, R11 ; копировать состояние входов в R11 DEC R9 JZ done AND #DNC, R11 ; маскировать все биты, кроме входов CMP #SCL, R11 ; убедиться, что на линии SDA лог. «0» ; а на SCL лог. «1» JNZ wait2 ; если нет - ожидаем wait3 MOV.B IN, R11 ; копировать состояние входов в R11 DEC R9 JZ done AND #DNC, R11 ; маскировать все биты, кроме входов JNZ wait3 ; если нет - ожидаем ;**************************************************************************** ; Стартовая последовательность получена ;**************************************************************************** MOV #007h, R13 ; счётчик на 7 адресных бит MOV #0000h, R12 ; регистр для сохранения адреса taddr MOV.B IN, R14 ; убедиться, что на линии SCL лог. «0» DEC R9 JZ done AND #SCL, R14 JNZ taddr addr MOV.B IN, R14 ; чтение порта DEC R9 JZ done MOV.B R14, R11 ; копировать данные AND #SCL, R14 ; маскировать все биты, кроме SCL JZ addr ; ждём лог. «1» на SCL AND #SDA, R11 ; маскировать все биты, кроме SDA JZ szero ; если «0» - просто сдвиг RLA.B R12 ; сдвиг влево BIS.B #0001h, R12 ; если «1» установить «1» в МЗР и сдвиг JMP sone szero RLA.B R12 ; арифметический сдвиг влево ? 0 sone DEC R13 ; декремент счётчика JNZ taddr ; повтор, если менее 7 бит MOV.B address, R13 ; копировать адрес устройства в R13 CMP.B R13, R12 ; и сравнить его с принятым адресом JNZ waddr ; переход, если адрес неверный ;**************************************************************************** ; адрес правильный, продолжаем ;**************************************************************************** ; чтение бита R/W (чтение/запись) rwait2 MOV.B IN, R11 ; ждём лог. «0» на SCL DEC R9 JZ done AND.B #SCL, R11 ; маскировать все биты, кроме SCL JNZ rwait2 rwait MOV.B IN, R11 ; ждём лог. «1» на SCL DEC R9 JZ done AND.B #SCL, R11 ; маскировать все биты, кроме SCL JZ rwait MOV.B IN, R11 ; копировать данные из порта AND.B #SDA, R11 ; маскировать все биты, кроме SDA JNZ done ; 0 если запись, переход, если 1 (чтение) ;**************************************************************************** ; Отправить бит подтверждения (ACK) ;**************************************************************************** rwait3 MOV.B IN, R11 ; ждём лог. «0» на SCL DEC R9 JZ done AND.B #SCL, R11 ; маскировать все биты, кроме SCL JNZ rwait3 BIS.B #SDA, DIR ; перевести линию SDA в лог. «0» rwait4 MOV.B IN, R11 ; ждём лог. «1» на SCL DEC R9 JZ done AND.B #SCL, R11 ; маскировать все биты, кроме SCL JZ rwait4 rwait5 DEC R9 JZ done MOV.B IN, R11 ; ждём лог. «0» на SCL AND.B #SCL, R11 ; маскировать все биты, кроме SCL JNZ rwait5 BIC.B #SDA, DIR ; «отпустить» линию SDA ;**************************************************************************** ; готов принять байт ;**************************************************************************** MOV #008h, R13 ; счётчик на 8 бит данных MOV #0000h, R12 ; регистр для сохранения адреса tdat MOV.B IN, R14 ; убедиться, что на линии SCL лог. «0» DEC R9 JZ done AND #SCL, R14 JNZ tdat dat MOV.B IN, R14 ; читаем данные из порта MOV.B R14, R11 ; копируем данные DEC R9 JZ done AND #SCL, R14 ; маскировать все биты, кроме SCL JZ dat ; ждём лог. «1» на SCL AND #SDA, R11 ; маскировать все биты, кроме SDA JZ szeroc ; если «0» - просто сдвиг RLA.B R12 BIS.B #0001h, R12 ; если «1» установить «1» в МЗР и сдвиг JMP szerob szeroc RLA.B R12 ; арифметический сдвиг влево szerob DEC R13 ; декремент счётчика JNZ tdat MOV.B R12, data ; копируем в ОЗУ ;**************************************************************************** ; Отправить бит подтверждения (ACK) ;**************************************************************************** rwait6 MOV.B IN, R11 ; ждём лог. «0» на SCL DEC R9 JZ done AND.B #SCL, R11 ; маскировать все биты, кроме SCL JNZ rwait6 BIS.B #SDA, DIR ; перевести линию SDA в лог. «0» rwait7 MOV.B IN, R11 ; ждём лог. «1» на SCL DEC R9 JZ done AND.B #SCL, R11 ; маскировать все биты, кроме SCL JZ rwait7 rwait8 MOV.B IN, R11 ; ждём лог. «0» на SCL DEC R9 JZ done AND.B #SCL, R11 ; маскировать все биты, кроме SCL JNZ rwait8 BIC.B #SDA, DIR ; «отпустить» линию SDA done ;POP R14 ; если известно, что стартовая посылка длительная, ; можно добавить эти строки ;POP R13 ;POP R12 ;POP R11 MOV #0FFh, R9 RETI ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; переменные ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * address .equ 0248h ; адрес устройства data .equ 0242h ; отправляемые данные datin .equ 0244h ; принимаемые данные error .equ 0246h ; флаг ошибки Приложение E Содержание файла ASCII.txt @B500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B7 12 8F 1F 3A 3D BD 13 BF 3F 00 00 00 00 00 00 00 BB BC A5 9E AD A9 3F BA 12 96 00 A4 B3 98 9C AB 00 88 3D AC 94 00 00 00 3E 8F 00 00 00 00 00 00 BB BC A5 9E AD A9 3F BA 12 96 00 A4 B3 98 9C AB 00 88 3D AC 94 00 00 00 3E 8F 00 q Популярный сайт знакомств общения maybe.ru
Главная - Микросхемы - DOC - ЖКИ - Источники питания - Электромеханика - Интерфейсы - Программы - Применения - Статьи |
|
Впервые? | Реклама на сайте | О проекте | Карта портала тел. редакции: +7 (995) 900 6254. e-mail:info@eust.ru ©1998-2023 Рынок Микроэлектроники |
|