Автоматическое определение микросхем I2C EEPROM |
![]() |
Добавил(а) microsin | ||||||||||||||||||||||||||||||||||||||||||
В этой статье (перевод апноута AN690 Microchip [1]) описывается метод автоматического определения размера памяти EEPROM с последовательным интерфейсом I2C. Рассматриваются темы: • Автоопределение размера памяти, подключенной к шине I2C [Автоопределение размера памяти, подключенной к шине I2C] В приложениях с микроконтроллерами, где используется память Serial EEPROM, часто встает проблема согласования требований приложения и оптимизации стоимости используемых компонентов. Пользователю часто нужно использовать разные размеры памяти для разных версий приложения, однако ценовые ограничения требуют использовать каждый раз минимальный размер памяти. Примером типового приложения может быть базовая станция (приемник) дистанционно управляемой системы открытия двери гаража. Версии, которые могут хранить в памяти 4, 20, 200 или 1000 пользователей, могли бы с одним и тем же исходным кодом, подходящим к различным используемым микросхемам памяти. Microchip поставляет широкий диапазон емкости памяти с интерфейсом I2C (от 16 байт в 24C00 до 32k байт 24C256). У микроконтроллера должен быть способ определить, какая память используется на шине I2C, чтобы можно было правильно её адресовать. Для решения этой проблемы есть 2 возможных метода - один состоит в предоставлении какой-либо конфигурационной информации для контроллера, например с помощью DIP-переключателей или перемычек, и другой способ подразумевает автоматическое определение конфигурации памяти. В этом апноуте показано, как просто и безопасно реализовать автоматическое детектирование подключенной памяти. Описанные программные техники демонстрируются на обычном микроконтроллере PIC16C62A среднего ценового диапазона, и это может быть немедленно протестировано на демо-плате PICDEM2. Весь код может быть адаптирован для других микроконтроллеров семейства PICmicro (с ядрами 12, 14, 16 и/или другими конфигурациями выводов) путем незначительных изменений в исходном коде. [Стандарт I2C] Протокол I2C использует двунаправленную шину, работающую по принципу главного устройства и подключенных к нему подчиненных устройств (схема master/slave). Главное устройство (master) это обычно микроконтроллер, который управляет шиной, генерирует такты (SCL) и формирует сигналы START и STOP на шине. Serial EEPROM ведет себя как подчиненное (slave) устройство, и оно работает как передатчик данных во время операций чтения. Во время операций записи EEPROM работает как приемник, формируя сигналы положительного и отрицательного подтверждения (ACK и NACK) для устройства master. Сигналы START и STOP используются для управления потоком данных по шине. Нормальная операция начинается с сигнала START и заканчивается сигналом STOP. За START начинается команда чтения или записи, содержащая адрес устройства, эту команду формирует master. Этот первый байт называется байтом управления, он идентифицирует подчиненное устройство и определяет следующую операцию - чтение это будет или запись. Типовой байт управления для Serial EEPROM показан на рис. 1. Таким образом, байт управления начинается с сигнала START, за которым идет 4-битный идентификатор типа устройства (для устройства типа EEPROM это будут биты 1010), затем 3 бита, выбирающие конкретную микросхему на шине I2C (A2, A1, A0), бит чтения/записи (R/W), за которым должно идти подтверждение от slave-устройства (ACK). Рис. 1. Структура байта управления. [Smart Serial или I2C?] Последовательная шина I2C имеет много преимуществ перед другими последовательными шинами для встраиваемых устройств. Шина I2C с триггерами Шмитта на входах, срабатывающих по уровню, дает лучшую помехозащищенность по сравнению с технологиями, которые основаны на перепадах уровня. Для обмена с микросхемами памяти не требуются коды операций и используют интуитивно-понятную схему операций. Однако стандартный протокол ограничивает адресацию памяти максимумом 16K байт при использовании 8-битного адреса и трех выводов A0, A1 и A2 (8 x 2 килобайта). Здесь заключается некая дилемма. С появлением более современных персональных устройств связи, таких как сотовые телефоны, наладонники и другие переносные устройства, 16K байт будет недостаточно. Поэтому в связи с требованиями индустрии к повышению размеров памяти I2C во встраиваемых приложениях появилась концепция Smart Serial, удовлетворяющая требованиям уменьшения износа памяти, повышения безопасности данных. Также с этой концепцией была добавлена функциональность поддержки пониженного потребления энергии. Компанией Microchip была разработана схема адресации для I2C Serial EEPROM, основанная на стандартном протоколе I2C и адресе устройства, но был введен дополнительный байт адреса, чтобы позволить разработчику применить до 256K бит на устройство и добавить от 1 до 8 устройств на одну системную шину I2C. Это позволило будущее расширение памяти, и дало продвинутые возможности в маленьких, эффективных по стоимости разработках. Для первого байта, или управляющего байта, Smart Serial придерживаются стандартного протокола I2C (см. рис. 2). Следующие 2 байта (вместо одного) определяют адрес запрашиваемой области памяти. Рис. 2. Запись байта. [Другой набор подпрограмм для шины I2C] Компанией Microchip Technology было опубликовано множество апноутов с интерфейсом к шине I2C: AN515, AN537, AN558, AN567, AN608, AN554, AN578 и AN535. Ниже будут будут использованы техники из этих даташитов, и на основе их кода будут создан компактный, мощный набор подпрограмм. Сначала будет модифицирован базовый набор подпрограмм [3, 4, 6, 8, 10], чтобы они поддерживали адресацию Standard I2C и Smart Serial, выбирали runtime схему адресации посредством флага SMART. Листинг 1 (i2c.inc) показывает новый набор подпрограмм. Как обычно, здесь присутствует 2 слоя функций: • Нижний слой (состоящий из подпрограмм: BSTOP, BSTART, RXI2C, TXI2C, BITIN, BITOUT, ERR), который реализует отправку и определение одиночных бит и байтов на шине, и на этом слое нет нового кода. • Верхний слой (состоящий из подпрограмм: RDbyte, WRbyte и SETI2C), который обрабатывает команды и заботится о схемах адресации. В этой документации в основном обсуждается именно этот слой. Нововведение здесь следующее: в функцию SETI2C перенесен весь код, который работает с деталями схемы адресации. Эта функция получает флаг SMART на входе, и предоставляет адресацию Standard или Smart в соответствии с его значением. Функции RDbyte и WRbyte полагаются на SETI2C для генерации команды и адреса, чтобы добиться совместимости со Standard и Smart Serial. [Определение схемы адресации] Следующий небольшой шаг к автоматическому определению размера памяти - нам нужно найти метод, чтобы автоматически отличить Smart Serial и Standard Serial EEPROM. Предлагается простой и компактный алгоритм, состоящий из 4 шагов: 1. Перевод I2C подпрограмм в режим Smart Serial (установкой флага SMART). 2. Выдается команда write в ячейку 0000, с записью 1. Если память стандартная I2C, то эта команда интерпретируется как команда последовательной записи (sequential write) двух байт, в результате запишется байт 00 в ячейку 0000 и байт 01 в ячейку 0001. Если же память Smart Serial, то мы получим корректную интерпретацию адреса, и в ячейку 0000 будет записан байт 01. 3. Подпрограммы I2C переводятся в стандартный режим (Standard I2C Mode, путем очистки флага SMART). 4. Выдается команда read ячейки 0000. Если память действительно Standard I2C, то эта команда read даст нам содержимое ячейки 0000, которая была установлена в 0. Если же память типа Smart Serial, то получится команда чтения с частичной (неполной) адресации. То, что произойдет, не относится непосредственно к работе шины I2C, давайте проанализируем эти два возможных случая. a) Частичная адресация только установит старшие значащие биты внутреннего регистра адреса, и оставит не измененными младшие 8 бит. Это означает, что будет прочитана ячейка 0000. Если в обоих случаях процесс завершится чтением 1, то это укажет нам на память Smart Serial. Если будет прочитан 0, то это последовательная память Standard I2C. Листинг 2 (i2cauto.asm) реализует этот простой алгоритм на 10 строках ассемблера. Замечание: очевидно, что описанная процедура повредит содержимое ячеек 0000 и 0001, и не существует способа сохранить и восстановить их (пока не будет определена схема адресации!). [Определение размера памяти] Последний шаг к автоматическому определению размера памяти - разработка алгоритма, который определит размер памяти по имеющейся схеме адресации. Предположим, что уже известен тип памяти - Standard или Smart, и необходимо определить её размер. Детектирующий алгоритм будет базироваться на простом предположении: если память имеет размер N, то попытка адресации вне диапазона 0..N-1 приведет к попаданию обратно в этот диапазон. Поскольку самые старшие (дополнительные) биты адреса будут просто игнорироваться, для устройства они не будут иметь значения. Это можно просто проверить по даташиту каждой микросхемы памяти. Можно разработать простую тест-функцию, которая скажет нам, имеет ли память размер N, или у неё размер меньше. На псевдокоде эта функция будет выглядеть примерно так: bool TestIfSizeIs (u32 N) { // Адреса памяти находятся в диапазоне 0..N-1? u8 TEMP; TEMP = Read(0000); if (Read(N) == TEMP) { Write(0000, TEMP+1); if (Read(N) == TEMP+1) { Write(0,TEMP-1); return TRUE; } } // Иначе: return(FALSE) } С помощью такой функции мы можем организовать цикл проверки размеров памяти. В случае памяти Standard I2C цикл может проверять от N=128 до N=2048 (микросхемы от 24C01 до 24C16) удваивая N на каждой итерации: u8 StandardI2CMemDetect (void) { // Функция вернет номер модели микросхемы памяти 1..16. u16 N = 128; u8 MODEL = 1; do { if (TestIfSizeIs(N)) break; else { N=N*2; MODEL=MODEL*2; } } while(N <= 2048); return MODEL; } Подобным образом функция может проанализировать память Smart Serial в диапазоне от N=4096 до N=32768. Обратите внимание, что в этом простом алгоритме не резервируются ячейки памяти. Изменяемая ячейка в процессе тестирования всегда должна быть сохранена и восстановлена. Все готово для реализации алгоритма определения размера микросхемы. Сначала мы определим схему адресации, после чего войдем в цикл, измеряющий реальный размер памяти. В зависимости от схемы адресации цикл будет проверять разные диапазоны размеров памяти, соответствующие разным размерам моделей микросхем памяти, доступных на рынке. Листинг 2 (i2cauto.asm) реализуют на ассемблере оба алгоритма (определение схемы адресации и размера). Код может быть протестирован на PIC16C62A (плата PICDEM2) или любой другой целевой системе (после модификации используемых ножек выводов листинга 2 i2cauto.asm). После установки памяти I2C в сокет DIL платы PICDEM2, подайте на неё питание или нажмите кнопку сброса, и светодиоды покажут в двоичном представлении значение TYPE (см. таблицу 1). Таблица 1. Значение TYPE для разных микросхем памяти.
Вы можете экспериментировать и изменить предлагаемый код (см. ниже врезку "Приложение A: код ассемблера для PIC16C62A"), чтобы он соответствовал Вашим определенным требованиям. Однако старайтесь учитывать допустимое количество перезаписей (ограниченный ресурс) микросхем EEPROM, и используйте программную утилиту "Endurance" от Microchip Technology, когда разрабатываете приложения с особыми требованиями к надежности [11, 12]. [Совместимость] Почти весь представленный код строго следует существующим стандартам I2C и Smart Serial, поэтому он должен быть совместим с любым устройством Serial EEPROM от любого производителя, который придерживается этих стандартов. Однако код проверялся только с микросхемами Microchip Serial EEPROM, и пользователь должен самостоятельно обеспечить совместимость кода с микросхемами памяти от других производителей. Кроме того, возможны некоторые проблемы совместимости на шаге детектирования схемы адресации. Фактически поведение последовательной памяти в случае частичной адресации (что происходит на шаге 4 в случае Smart Serial) не является частью спецификации. Несмотря на то, что с текущей реализации протокола Smart Serial предлагаемое решение работает нормально (с микросхемами Microchip вплоть до 24C256), не гарантируется, что это также хорошо будет работать и в будущем. [Листинг 1: I2C.INC] ;**********************************************************************
;* Файл: I2C.INC
;**********************************************************************
;* Автор: Lucio Di Jasio
;* Компания: Microchip Technology
;* Ревизия: RevA0
;* Дата: 5-7-98
;* Ассемблировано с помощью MPASM v02.15
;**********************************************************************
;* Примеры подпрограмм READ/WRITE шины I2C/TWI для обоих
;* поддерживаемых схем адресации Smart Serial и Standard I2C.
;* Версия PIC16CXXX mid-range (ядро 14 бит)
;* Примечания:
;* 1) Все тайминги основаны на кварце 4 МГц с соответствующим
;* временем инструкции 1 мкс.
;* 2) Адреса и литеральные значения даны в HEX-форме, если не указано
;* что-то другое.
;*****************************************************************************
;* Назначение файла регистров
;*****************************************************************************
CBLOCK
FLAGS INDHI ; адрес INDLO DATO ; буфер данных для функций чтения и записи ERCODE ; код ошибки (см. таблицу ниже) EEBUF ; буфер чтения/записи SLAVEbuf ; SLAVE-адрсе (+ addrHi на 24LC16) COUNT AUX ENDC
;**********************************************************************
; Определения флагов; #define FLAG_EE FLAGS,0 ; ошибки шины I2C #define SMART FLAGS,1 ; Smart(1) Standard(0) ;
;*****************************************************************************
;* Назначение бит
;*****************************************************************************
#define SLAVE B'10100000' ; Адрес устройства (1010xxx0); коды ошибок #define ERR_NACK 1 ; не прочитан ACK #define ERR_STOP 2 ; SDA заблокирован на STOP #define ERR_TOWR 3 ; таймаут чтения (> 20 мс) #define ERR_LOCK 4 ; SDA заблокирован в BITOUT ;*****************************************************************************
;* RDbyte
;* Чтение одного байта из устройства памяти serial EEPROM
;*
;* Вход: INDHI/LO
;* SLAVE = адрес устройства (1010xxx0)
;* Выход: DATO = данные, прочитанные из serial EEPROM
;*****************************************************************************
RDbyte bcf FLAG_EE ; сброс флага ошибки call SETI2C ; установка указателя адреса ; вход в последовательное чтение (sequential reading)
RDnext call BSTART ; START movf SLAVEbuf,W ; используется SLAVE addr(+IndHi при 24LC16) movwf EEBUF bsf EEBUF,0 ; команда чтения call TXI2C ; вывод SLAVE + address + команда read call RXI2C ; чтение в DATO и ACKnowledge movf EEBUF,W movwf DATO bsf STATUS,C ; ACK = 1 (NOT ACK) call BITOUT ; для остановки ввода (STOP) goto BSTOP ; генерация STOP-бита ;*****************************************************************************
;* WRbyte
;* Запись одного байта в устройство EEPROM
;*
;* Вход: DATO = записываемые данные
;* INDHI/LO = адрес EEPROM
;* SLAVE = адрес устройства (1010xxx0)
;* PROT = 1 SmartSerial | 0 Standard
;* Выход: FLAG_EE = установится, если операция завершилась неудачно
;*****************************************************************************
WRbyte bcf FLAG_EE ; сброс флага ошибки call SETI2C ; установка указателя адреса movf DATO,W ; перемещение DATO movwf EEBUF ; в буфер call TXI2C ; вывод DATO и детектирование ACKnowledge call BSTOP ; генерация STOP-бита; цикл ожидания завершения записи movlw .80 ; 80 = таймаут 20 мс movwf AUX WRpoll CLRWDT ; сброс сторожевого таймера bcf FLAG_EE call BSTART ; старт movlw SLAVE movwf EEBUF call TXI2C ; и команда записи btfss FLAG_EE ; если не ACK -> код ошибки 3 -> BUSY goto WRpollE WRbusy decfsz AUX,F goto WRpoll movlw ERR_TOWR ; таймаут записи call ERR WRpollE goto BSTOP ; выход с отправкой сигнала STOP ;*****************************************************************************
;* SETI2C
;* Устанавливает указатель адреса на INDHI/LO, используется схема
;* адресации Smart или Standard, в зависимости от флага SMART.
;*
;* Вход: INDHI = адрес EEPROM
;* INDLO
;* SLAVE = адрес устройства (1010xxx0)
;* SMART = 1 Smart Serial | 0 Standard I2C
;* Выход: SLAVEbuf для sequential read
;*****************************************************************************
SETI2C btfsc SMART ; если 0, то Standard I2C goto Smart ; если 1, то Smart Serial Standard bcf STATUS,C ; rlf INDHI,W ; добавление к slave-адресу iorlw SLAVE ; старших бит адреса movwf EEBUF movwf SLAVEbuf ; сохранение для sequential read call BSTART ; генерация START-бита call TXI2C ; вывод первого байта команды goto SETseq Smart movlw SLAVE ; подготовка slave-адреса movwf EEBUF movwf SLAVEbuf ; сохранение для sequential read call BSTART ; генерация START-бита call TXI2C ; вывод первого байта команды movf INDHI,W ; movwf EEBUF ; вывод старшего байта адреса call TXI2C SETseq movf INDLO,W ; отправка младшего байта адреса movwf EEBUF goto TXI2C ; вывод адреса слова ;*****************************************************************************
;* TXI2C
;* Передает 8 бит данных
;*;* Вход: EEBUF ;* Выход: нет
;*****************************************************************************
TXI2C movlw .8 ; Set counter for eight bits movwf COUNT TXlp rlf EEBUF,F ; бит данных находится в CARRY call BITOUT ; отправка бита decfsz COUNT,F ; отправлено 8 бит? goto TXlp ; нет... call BITIN ; чтение бита ACK movlw ERR_NACK btfsc STATUS,C ; проверка подтверждения call ERR ; нет подтверждения от устройства return ;*****************************************************************************
;* BITOUT
;* Отправка одного бита
;*
;* Вход: бит в флаге переноса CARRY
;* Выход: бит передается по шине I2C
;* Если необходимо, то установятся биты ошибки.
;*****************************************************************************
BITOUT btfss STATUS,C ; 0 или 1? goto Bit0 Bit1 bsf STATUS,RP0 ; выбор RAM bank 1 bsf SDA ; вход SDA (pull up -> 1) bcf STATUS,RP0 ; обратно в RAM bank 0 movlw ERR_LOCK btfss SDA ; Проверка на ошибку call ERR ; SDA заблокирован микросхемой памяти goto Clk1 Bit0 bsf STATUS,RP0 ; выбор RAM bank 1 bcf SDA ; выход SDA bcf STATUS,RP0 ; обратно в RAM bank 0 bcf SDA ; сброс в 0 nop ; задержка Clk1 bsf SCL ; перевод SCL в лог. 1 nop nop nop ; задержка минимум 4 мкс nop nop bcf SCL ; перевод SCL в лог. 0 return ;*****************************************************************************
;* RXI2C
;* Прием 8 бит данных
;*
;* Вход: нет
;* Выход: RXBUF = принятый байт данных
;*****************************************************************************
RXI2C movlw .8 ; 8 бит данных movwf COUNT clrf EEBUF RXlp call BITIN ; новый бит в CARRY rlf EEBUF,F ; ввод нового бита decfsz COUNT,F ; обработано 8 бит? goto RXlp return ;*****************************************************************************
;* BITIN
;* Прием одного бита
;*
;* Вход: нет
;* Выход: EEBUF, 0 принятый бит
;*****************************************************************************
BITIN bsf STATUS,RP0 ; выбор RAM bank 1 bsf SDA ; установка SDA для ввода bcf STATUS,RP0 ; обратно в RAM bank 0 bsf SCL ; SCL = 1 nop nop nop nop ; предоставляется минимальное время установки CLRC btfsc SDA ; чтение SDA в CARRY bsf STATUS,C bcf SCL ; возврат с SCL = 0 return ;*****************************************************************************
;* Генерация бита START
;*
;* Вход: нет
;* Выход: инициализирован обмен по шине
;*****************************************************************************
BSTART bsf STATUS,RP0 ; выбор RAM bank 1 bsf SDA ; вход SDA (pull up -> 1) bcf STATUS,RP0 ; обратно в RAM bank 0 bsf SCL ; SCL = 1 nop nop nop nop ; 5 мкс перед спадом SDA bsf STATUS,RP0 ; выбор RAM bank 1 bcf SDA ; выход SDA bcf STATUS,RP0 ; обратно в RAM bank 0 bcf SDA ; SDA = 0 nop nop nop nop ; 4 мкс перед спадом SCL bcf SCL ; начало последовательности тактов return ;*****************************************************************************
;* Генерация бита STOP
;*
;* Вход: нет
;* Выход: STOP condition на шине
;*****************************************************************************
BSTOP bsf STATUS,RP0 ; выбор RAM bank 1 bcf SDA ; выход SDA bcf STATUS,RP0 ; обратно в RAM bank 0 bcf SDA ; SDA = 0 bsf SCL ; SCL = 1 nop nop nop nop ; 4 мкс перед нарастанием SDA bsf STATUS,RP0 ; выбор RAM bank 1 bsf SDA ; вход SDA (pull-up -> 1) пока SCL = 1 bcf STATUS,RP0 ; обратно в RAM bank 0 movlw ERR_STOP ; получение кода ошибки btfss SDA ; лог. 1? call ERR ; ошибка, SDA заблокирован перед STOP bcf SCL ; SCL = 0 return ;*****************************************************************************
;* TWI/I2C - таблица ошибок состояния обмена CPU
;*
;* Вход: W-reg = код ошибки
;* Выход: ERCODE = код ошибки
;* FLAG(ERROR) = 1
;*****************************************************************************
ERR bcf STATUS,RP0 ; обратно в RAM bank 0; запись последней ошибки movwf ERCODE ; сохранение кода ошибки bsf FLAG_EE ; установка флага ошибки return [Листинг 2: I2CAUTO.ASM] LIST n=0, c=132 RADIX HEX PROCESSOR PIC16C62A ;**********************************************************************
;* Файл: I2CAUTO.ASM
;**********************************************************************
;* Автор: Lucio Di Jasio
;* Компания: Microchip Technology
;* Ревизия: RevA0
;* Дата: 5-7-98
;* Ассемблировано с помощью MPASM v02.15
;**********************************************************************
;* Подключаемые файлы:
;* p16c62A.inc rev1.01
;*
;**********************************************************************
;* Программное определение размера памяти I2C EEPROM.
;*
;* PIC16CXXX /+5V
;* +-----------+ |
;* | Vdd+--------------+--------+ 24CXXX
;* | | +++ | +--------+
;* | | | | +--+Vdd |
;* | | | | 4k7 | |
;* | | +++ | |
;* | RC4+--------------+-----------+SDA |
;* | RC3+--------------------------+SCL |
;* | | | |
;* | Vss+--------------+-----------+Vss |
;* +-----------+ | +--------+
;* GND
;*
;* Можно проверить на PICDEM2 demo board.
;********************************************************************** INCLUDE "P16C62A.INC" __CONFIG _XT_OSC & _CP_OFF & _WDT_ON __IDLOCS H'62A0' ;**********************************************************************
;* Внешний кварц 4 МГц
;* нет защиты кода
;* нет сторожевого таймера
;* ID code "62A0"
;**********************************************************************
; Назначение выводов
#define SDA PORTC,4 ; i I2C SDA #define SCL PORTC,3 ; o I2C SCL MASKA equ 0FF ; все не используемые входы MASKB equ 00 ; все выходы для подключения LED MASKC equ b'11110111' ; на этом порте сигналы SCL и SDA ; SCL настраивается на выход ;------------------------------------------------------------
; Назначение RAM CBLOCK 20 TEMP SIZELO ; размер памяти SIZEHI TYPE ; тип памяти ENDC ;********************************************************************** org 00 ; вектор сброса goto Start ;********************************************************************** org 04 ; вектор прерывания retfie ; возврат с повторным разрешением прерываний ;********************************************************************** INCLUDE "i2c.inc" ;**********************************************************************
;* MemDetect: автоматическое определение размера памяти
;*
;* Вход: нет
;* Выход: SIZEHI/LO детектированный размер памяти
;* TYPE тип памяти (см. таблицу ниже)
;* FLAG_EE флаг ошибки шины
;* ERCODE код ошибки шины
;*
;* Standard I2C Smart Serial
;* TYPE SIZE MODEL TYPE SIZE MODEL
;* 01 128 24C01/21/41 32 4096 24C32
;* 02 256 24C02/62 64 8192 24C65/64
;* 04 512 24C04 128 16384 24C128
;* 08 1024 24C08 0 32768 24C256
;* 16 2048 24C16/164
;*
;**********************************************************************
MemDetect clrf INDHI ; адрес 0000h clrf INDLO bsf SMART ; write(smart, 0000, 1) movlw 1 movwf DATO call WRbyte bcf SMART call RDbyte ; read(standard, 0000) movf DATO,W btfsc STATUS,Z goto StandardD SmartD bsf SMART ; это Smart Serial movlw HIGH(.4096) movwf SIZEHI ; размер = 4096 байт clrf SIZELO movlw .32 movwf TYPE ; начинаем с TYPE = 24C32 goto TestD StandardD bcf SMART ; это Standard Serial movlw .128 movwf SIZELO ; размер = 128 byte clrf SIZEHI movlw 01 movwf TYPE ; начинаем с TYPE = 24C01 TestD call RDbyte ; TEMP=read(0) movf DATO,W movwf TEMP LoopDet movf SIZELO,W ; DATO=read(SMART, size) movwf INDLO movf SIZEHI,W movwf INDHI call RDbyte movf DATO,W xorwf TEMP,W ; сравнение TEMP с DATO btfss STATUS,Z goto LoopDN incf TEMP,W ; если равно, то TEMP=TEMP+1 movwf TEMP movwf DATO clrf INDHI clrf INDLO call WRbyte ; write(SMART, 0000, TEMP) movf SIZELO,W ; if (read(SMART, size) == TEMP) movwf INDLO movf SIZEHI,W movwf INDHI call RDbyte movf DATO,w ; если все еще одинаковое значение, то это значит, xorwf TEMP,W ; что мы достигли реального размера памяти btfsc STATUS,Z goto DetEx LoopDN bcf STATUS,C ; удвоение размера памяти rlf SIZELO,F rlf SIZEHI,F bcf STATUS,C rlf TYPE,F ; удвоение кода TYPE btfss TYPE,4 goto LoopDet DetEx nop return ;**********************************************************************
; Инициализация портов и регистра опций
Start bsf STATUS,RP0 ; выбор RAM bank 1 movlw MASKA ; установка регистров tris movwf PORTA ; PORTA movlw MASKB ; movwf PORTB ; PORTB movlw MASKC ; movwf PORTC ; PORTC movlw b'00000111' ; разрешение pullup, прескалер TMR0 1:256 movwf OPTION_REG bcf STATUS,RP0 clrf FLAGS ; сброс всех флагов
Main call MemDetect ; определение размера памяти movf TYPE,W ; если используется плата PICDEM2, то movwf PORTB ; TYPE отправляется на светодиоды LED MainLoop goto MainLoop ; зацикливание до сброса END [Ссылки] 1. AN690 I2C Memory Autodetect site:microchip.com (00690a.pdf). |