AVR. Учебный Курс. Использование EEPROM

Иногда нужно сохранить данные так, чтобы они восстановились после перезагрузки контроллера. В этом тебе поможет EEPROM, почти все контроллеры серии AVR имеют на борту некоторое количество этой памяти. Физически и логически эта память находится в отдельном адресном пространстве, а чтение из EEPROM и запись туда осуществляется через специальные порты.

Чтобы что-то записать в EEPROM нужно в регистры адреса EEARH и EEARL (EEPROM Address Register) положить адрес ячейки в которую мы хотим записать байт. После чего нужно дождаться готовности памяти к записи – EEPROM довольно медленная штука. О готовности к записи нам доложит флаг EEWE (EEPROM Write Enable) регистра управления состоянием EECR, когда он будет равен 0, то память готова к следующей записи. Сам байт, который нужно записать, помещается в регистр EEDR (EEPROM Data Register). После чего взводится предохранительный бит EEMWE (EEPROM Master Write Enable), а затем, в течении четырех тактов, нужно установить бит EEWE и байт будет записан. Если в течении четырех тактов не успеешь выставить бит EEWE то предохранительный бит EEMWE сбросится и его придется выставлять снова. Это сделано для защиты от случайной записи в EEPROM память.

Чтение происходит примерно аналогичным образом, вначале ждем готовности памяти, потом заносим в регистры нужный адрес, а затем выставляем бит чтения EERE (EEPROM Read Enable) и следующей командой забираем из регистра данных EEDR наше число, сохраняя его в любом регистре общего назначения. Чтобы было понятно, я тебе набросал две процедурки – на чтение и на запись. Чтобы записать байт, нужно в регистры R16 и R17 занести младший и старший байт адреса нужной ячейки, а в регистр R21 байт который мы хотим записать. После чего вызвать процедуру записи. Аналогично и с чтением – в регистра R16 и R17 адрес, а в регистре R21 будет считанное значение.

Вот так выглядит запись в память:

1
2
3
4
5
	…
	LDI 	R16,0		; Загружаем адрес нулевой ячейки
	LDI 	R17,0		; EEPROM 
	LDI 	R21,45		; и хотим записать в нее число 45
	RCALL 	EEWrite 	; вызываем процедуру записи.

А так чтение:

1
2
3
4
	LDI 	R16,0		; Загружаем адрес нулевой ячейки
	LDI 	R17,0		; EEPROM из которой хотим прочитать байт
	RCALL 	EERead 		; вызываем процедуру чтения. После которой 
				; в R21 будет считанный байт.

Ну и, разумеется, сами процедуры чтения и записи

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
EEWrite:	
	SBIC	EECR,EEWE		; Ждем готовности памяти к записи. Крутимся в цикле
	RJMP	EEWrite 		; до тех пор пока не очистится флаг EEWE
 
	CLI				; Затем запрещаем прерывания.
	OUT 	EEARL,R16 		; Загружаем адрес нужной ячейки
	OUT 	EEARH,R17  		; старший и младший байт адреса
	OUT 	EEDR,R21 		; и сами данные, которые нам нужно загрузить
 
	SBI 	EECR,EEMWE		; взводим предохранитель
	SBI 	EECR,EEWE		; записываем байт
 
	SEI 				; разрешаем прерывания
	RET 				; возврат из процедуры
 
 
EERead:	
	SBIC 	EECR,EEWE		; Ждем пока будет завершена прошлая запись.
	RJMP	EERead			; также крутимся в цикле.
	OUT 	EEARL, R16		; загружаем адрес нужной ячейки
	OUT  	EEARH, R17 		; его старшие и младшие байты
	SBI 	EECR,EERE 		; Выставляем бит чтения
	IN 	R21, EEDR 		; Забираем из регистра данных результат
	RET

Да, при работе с EEPROM нужно в цикле ожидания готовности не забывать командой WDR сбрасывать Watch Dog Timer — специальный сторожевой таймер, отслеживающий зависание процессора. Если его не сбрасывать с нужной периодичностью, то он сбрасывает контроллер. Это, конечно, если Watch Dog используется. По дефолту он вырублен. Но помнить надо, иначе огребете трудно отслеживаемый глюк.

Впрочем, у EEPROM тоже есть свои прерывания. Это:

1
2
         .ORG $01E
         RETI             	; (EE_RDY) EEPROM Ready

И никто не помешает выбросить цикл ожидания и сделать массовую запись в ЕЕПРОМ на прерываниях! Аналогично как это сделано для USART. А если надо что то сохранить очень быстро, то можно и буферизированную с пробросом через RAM таким же образом запись заюзать. Т.е. сначала быстро сожрали в оперативку, а потом, неспеша, по прерываниям, загнать в EEPROM.

113 thoughts on “AVR. Учебный Курс. Использование EEPROM”

  1. Спасибо! Отличная статья! Как раз сейчас нужно будет использовать EEPROM. Конечно можно прочитать даташит, что я обычно и делаю, но там все довольно разбросано, а здесь раз прочитал и в голове сложилась четкая структура.

    P.S. Еще интересно, может у тебя уже был опыт по использованию карт памяти SD/MMC? Там же вроде элементарно по SPI с ними общаться.

      1. Впринципе туда можно любую файловую систему зарулить. Хоть Fat, хоть Ext2fs, хоть вобще BSD’шную файловую систему.
        А описаний и документации, как работать с этими системами хоть отбавляй!
        Хочу использовать SD катрочку в автомобильном логгере (запись показаний датчиков системы впрыска)

  2. Забыл написать, что у атмеловских контроллеров есть так называемая «мертвая зона» EEPROM-a. У 64й атмеги, например, это все адреса от 0x00 — 0x100. Так же была замечена тенденция (по крайней мере на атмегах), чем круче модель (ATMeag32->64->128), тем больше у нее мертвая зона EEPROM. Причем в документации, про нее нифига не написано и подбирать придется в ручную. Ах да, чем же она такая мертвая эта зона. А тем, что запись и чтение в ней происходят через раз, а то и не происходят вообще. Дрочится конечно можно, но лучше оставить эти 100 адресов на советси разработчиков и работать со стабильным ПЗУ.

  3. День добрый!
    Ребята, вы все занимаетесь электроникой, помогите решить задачу, пожалуйста!!!
    Для вас это не составит труда, а человеку поможете.

    Задание:
    Разработать систему измерения частоты и скважности сигнала с ТТЛ – совместимыми уровнями и вывод результата на индикатор МТ-16S2х (частота – верхняя строка, скважность — нижняя). Диапазон измеряемых частот — 1÷1000 Гц. Абсолютный шаг измерения скважности – не менее 0,1 мс. Период накопления данных при измерении частоты – 1 секунда.
    ядро м/п системы:
    ATMEGA-8, ATTINY2313 (AVR)
    Нужны:
    расчетные параметры устройств (адреса, режимы работы и.т.д.),
    принципиальную электрическую схему системы,
    блок-схему программы, программу на языке ассемблера.

    Помогите пожалуйста, я не понимаю в этом ничего. А вам может будет интересно.
    Зарание спасибо.

      1. Я бы с радостью задала вопрос, но я в этом ничего не понимаю.
        Это в институт надо принести, я студентка.
        Дали такое задание.
        Помогите пожалуйста.
        Я могу заплатить за работу.
        Просто очень надо, мне больше не к кому обратится.

        1. Я догадался.
          Ну что я могу сказать. Вы, похоже, сильно ошиблись специальностью, мне вас искренне жаль. В таком случае ничем помочь не могу. Если кто из комментов откликнется, то может быть вам повезет.

  4. Блин, парюсь уже часа 3 с этим EEPROM
    В .ESEG объявил константы, так Студия не цапает их сама при эмуляции — пришлось вручную через меню указывать файл .epp. Ладно, вроде заработало.
    Но!! В Протеусе никак не могу загрузить данные EEPROM. Уж и конвертер hex2bin скачал, .epp файл конвертнул в .bin, указал в настройках ATMega8 — Initial Contens of EEPROM этот файл. А нифига — смотрю в паузе на содержимое EEPROM — везде 0xFF
    Помогите, плиз!

    1. Хм… Помог сброс данных модели и последующий выбор .bin файла….
      И все-таки протеус очень веселый….

      З.Ы. Студия тоже не фонтан… Сменил в простеньком проекте мегу8 на мегу 32 — так студия перестала показывать состояние всех РВВ… Создал пустой проект, скопипастил код туда — все заработало :-) Чудеса просто…

  5. А вот такой насущный вопрос:
    Собираю схему электронного одометра. Надо будет хранить пробег включая сотни метров. Ясно, что возможность записи в EEPROM закончится очень быстро. Вопрос: 100,000 записей это для всей памяти либо для одной ячейки? Т.е. могу ли я записать в оду ячейку 100000 раз потом перейти к следующей и т.д. таким образом использовать EEPROM долгое время? Если нет, то какой выход в данной ситуации можно посоветовать?
    Спасибо!

    1. 1 применить память типа FRAM от Ramtron у ней число циклов перезаписи такое, что скорей у твоей машины все молекулы сотрутся.

      2 держать данные в памяти, а на епром сбрасывать раз в 10-15 минут.

      И 100 000 это для каждой ячейки.

  6. Я программлю в CodeVision AVR так там в хэлпе вот такая тема:
    Accessing the AVR internal EEPROM is accomplished using global variables, preceded by the keyword eeprom.

    Example:

    /* The value 1 is stored in the EEPROM during chip programming */

    eeprom int alfa=1;

    eeprom char beta;

    eeprom long array1[5];

    /* The string is stored in the EEPROM during chip programming */

    eeprom char string[]=”Hello”;

    void main(void) {
    int i;

    /* Pointer to EEPROM */
    int eeprom *ptr_to_eeprom;

    /* Write directly the value 0x55 to the EEPROM */
    alfa=0x55;

    /* or indirectly by using a pointer */

    ptr_to_eeprom=&alfa;

    *ptr_to_eeprom=0x55;

    /* Read directly the value from the EEPROM */
    i=alfa;
    /* or indirectly by using a pointer */
    i=*ptr_to_eeprom;
    }

    то есть доступ к еепрому понимается как доступ к обычной переменной. у меня мега8, я просто создал массив на 512 char-ов и пользуюсь. Отлично работает :)

  7. 1. Ошибка. В подпрограмме чтении байта проверяется флаг готовности записи.
    2. В статье нет никакого упоминания о EECR (EPROM Control Register), он встречается только в тексте программы. Откуда будем брать флаги готовности?

  8. По пункту 1 последнего комментария.
    А зачем проверять? Если только в контексте данного примера, учитывая, что идет сначала запись, а затем сразу же чтение и там где сейчас стоит многоточие нет кода с приличным количеством тактов? А если я просто читаю данные уже находящиеся в EEPROM, то тоже надо проверять EEWE? Получается не очень понятно из этого примера как считывать данные. imho надо было не выходить из подпрограммы записи пока не установится EEWE, т.е. убедиться что запись гарантированно завершена, тогда не понадобиться ожидать её завершения при чтении. Или я не прав? Очень неоднозначный пример получился.

    1. В свете применения RTOS или подобной диспетчеризации проверять нужно всегда. Т.к. в разных процессах чтение и запись могут быть очень близко друг от друга по времени. А ждать окончания записи в процедуре записи еденичного байта это лишняя потеря времени. Лучше тогда отдать управление диспетчеру, а запись массива делать не на ожидании флага, а с использованием прерывания готовности — не будет потерь времени, запись пройдет фоном.

      Так что пример очень однозначный и совершенно универсальный. В конце концов, так гласит даташит. =)

      1. Не, всё равно пример не хороший или эту проверку надо в статье детально описать — зачем она нужна. Ведь в даташите конкретно расписано, что EEWE надо проверять перед чтением, т.к. возможен вариант, что запись ещё не завершена. А если я вообще ничего в EEPROM не пишу? У меня вот программа специфическая, использует подбираемые мной константы задержки расположенные в EEPROM, а сам EEPROM я дома программирую, не трогая саму программу во FLASH. Зачем мне тогда EEWE? Совершенно не зачем.
        А если я использую такую подпрограмму записи без контроля того, закончена ли запись, то возможны проблемы. Вызвал подпрограмму, записал байт и решил после этого ресетнутся и всё, кирдык — последний байт не записался. Лучше уж в подпрограмме дождаться флага готовности и тогда выходить — данные целее будут.

        1. Всех вариантов использования не опишешь.
          Я указал самый очевидный и наиболее универсальный.

          Тем более в комментах к проге указано с какой целью делаем проверку готовности при чтении. Собственно, имхо, тут более пояснения и не требуются.
          А извраты вроде программного ресета после записи в епром это уже экзотика и если такое делаешь, то надо четко понимать последствия и и к чему это может привести. Ради такого события тупить в процедуре записи до окончания ее это нерационально с точки зрения расхода процессорного времени. Если уж хочется ресет по окончании — взвел флаг на необходимость ресета, а ресет сделается уже из прерывания по готовности епрома.

  9. может невтему, но у меня возникла проблема: при выполнении программы заполняется пространство ОЗУ (начинает заполняться с конца), это видно в протеусе. Я думаю это из-за записи адресов команд в стек после прерываний, в некоторых случаях я не использую reti после выполнения обработки прерывания. Можно ли как-то очистить стек? И почему такое происходит?
    микроконтроллер: MEGA16

  10. Всем Привет. Я вот тут тоже парюсь с EEPROM, в студии подгрузил файл *.eep а вот в протеусе чет никак не получается.
    Добавил в свойства контроллера в протеусе такую строку:

    {MODDATAFILE=..\MotoController\MotoController.eep}

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

      1. протеус вставляет в память тоже самое если открыть файл *.eep нотпадом.
        я методом научного тыка пытался изменить ееп файл так как мне надо, так протеус на изменения забил и вставляет в память то что было изначально в ееп файле.

        1. хм… возможно он ее грузит как бинарик, а еееп в хекс формате. Или наоборот, он жрет ее как хекс ,а ееп в бинаре. Я не помню формат ееп. Если что hex2bin и bin2hex утилиты тебе в помощь.

  11. Может вопрос не по теме, но все же. Разработал на базе меги 8535 тренажер, весь код залил в память программ, а нужные для работы данные в EEPROM. Т.е. получилось два
    файла [имя].hex [имя].eep, которые были успешно залиты в кристалл. Таких кристалла 4 шт., и вот в чем фокус один работает как должен, а три нет. Проверил сами кристаллы -вроде живы, проверил залитые файлы — во всех кристаллах идентичные. В чем может быть косяк?

    1. Классная статья только что ее применил в Atmega8L, все работает. После отключения питания и его восстановления сперва данные считываются из EEPROM если там 1 то моя плата входит в нужный мне режим работы если нет то и нет. Только заметил что в этой статье не описывается флаг EERIE. Флаг включения вектора прерывания после завершения процедуры записи в EEPROM.

      А еще у меня возник вопрос. В статье в примере взят начальный адрес для EEPROM 0x00, а какой может быть конечный адрес если в Atmega8 512 байт EEPROM? В даташите не нашел адресной карты ЕЕПРОМА. Для ОЗУ и для флэш памяти нашел. Но если логично предположить что у первого байта адрес 0x00 то у 512 байта он равен 0x1FF то есть 511. Так наверное.

      1. Ответ нашел таки в даташите, невнимательно смотрел. Так и есть у 512 байта конечный адрес 511. Получается адреса eeprom у atmega8 находятся в диапазоне от 0 до 511 или 0x00 до 0x1FF.

  12. Добрый день уважаемый DI HALT!)
    Помогите разобраться — задыхаюсь!(
    Я новичок поэтому не судите строго…
    Мне необходимо создать динамическую таблицу констант, ну т.е. записать массив из 55 чисел и затем работать с ними (пишу на ассемблере), а результат снова записывать в этот массив, ну вот это и будет динамическая таблица.
    1. Куда записывать ? Насколько я понял нет директивы записи массива чисел в Рам, есть .db для записи байтов во флэш либо в EEPROM… Во флэш я так понимаю, не прокатит, так как надо обновлять данные, тогда EEPROM остаётся…

    2.Облазил кучу ссылок — не могу найти пример записи в EEPROM массива на азме. В вашем примере
    всё понятно, но он для записи отдельной константы. Можете помочь с куском кода для записи массива в EEPROM ?

    1. А чем массив отличается от одного байта? Тем что там много байт. В ассемблере нет такого понятия как массив. Это все абстракция программиста. У тебя есть некоторая область в памяти. Это твой массив. У ней есть первая ячейка — начальный адрес, а адреса остальных ячеек вычисляются простым смещением относительно этой первой ячейки. Берешь и последовательно, побайтно записываешь все нужные тебе данные.

  13. Огромное спасибо за оперативность…
    Однако вопросов ещё много…
    Извините, я новичок:
    Каким образом мне производить запись в озу (через какую команду, неужели последовательно через РОН)?

    1. .include «m16def.inc» ; Присоединение файла описаний
      .list ; Включение листинга

      .dseg

      .org 0x60

      .def temp = r16 ; Определение главного рабочего регистра

      ldi temp,77 ;инициализация регистра

      array_55:
      .byte 55

      STS 0x61,temp

      и так далее…???
      Только почему-то у меня ошибка появляется: » code in .dseg » ???

      1. Сперва об ошибке компилятора: Ясно что проблема с выбором памяти для размещения. Но не понимаю куда нужно воткнуть .cseg: орг-директиву выбрал чтоб запись была после РОН и РВВ, temp — эт и есть РОН из РАМ, директива .byte тоже резервирует именно в РАМ, а ругань идёт именно на выделение места под «массив».

      2. Добрый Вечер.
        Потыкался я в команды и записал таки последовательно эти 55 байт…
        Однако как-то нерационально получилось, у меня 4 куска аналогичных приведённому ниже коду.Как вы думаете можно ли его записать по-проще?
        Например, нельзя ли использовать что-нибудь кроме R16-29 чтобы оттуда кидать в РАМ?
        =============================================================================
        .include «m16def.inc» ; Присоединение файла описаний
        .list ; Включение листинга

        .cseg
        ldi r16,28
        ldi r17,69
        ldi r18,66
        ldi r19,39
        ldi r20,75
        ldi r21,35
        ldi r22,18
        ldi r23,87
        ldi r24,21
        ldi r25,32
        ldi r26,123
        ldi r27,38
        ldi r28,86
        ldi r29,89
        .dseg
        array_55: .byte 55
        .cseg
        clr r31 ldi r30, 96

        st z, r16
        std z+1,r17
        std z+2,r18
        std z+3,r19
        std z+4,r20
        std z+5,r21
        std z+6,r22
        std z+7,r23
        std z+8,r24
        std z+9,r25
        std z+10,r26
        std z+11,r27
        std z+12,r28
        std z+13,r29
        ================================================================================

          1. Нет)
            Всё гораздо интереснее…
            Ладно карты на стол:
            1:
            Нужно сделать генерацию случайных чисел и последовательное их
            выплёвывание в порт мк.
            Для этого я использую алгоритм Митчелла Мура, суть вот в чём:
            Надо загнать в мк(использую мегу16) массив из 55 случайных чисел, соответственное 55 регистров а потом складывать
            24й и 55й — результат в 55й (если переполнение то по ходу по фиг),
            декрементируем (т.е. юзаем 23й и 54й) = результат
            в 54й, и так надо гонять этот массив (в книге термин — циклическая
            таблица).
            Когда меньший индекс (ну т.е. 24й например) станет = 0, записать в него
            55, когда старший — тоже записать(эт цикл) 0. вот…

            2: И потом всё это дело отфильтровать при помощи Цифрового фильтра,
            уравнение которого надо реализовать программно

            P.S.: Если удобно можете написать и в аську 487422360.

            1. 1. Где ты возьмешь случайные числа? Сам наплодишь или заранее таблицу сделаешь? Если заранее таблицу, то тебе проще так:

              Размещаешь ее в ПЗУ, в флешраме через .db 1,2,3 и так далее все твои 55 значений.
              Но изменять их нельзя, т.к. они в ПЗУ.

              Поэтому мы при старте через команду LPM копируем их в массив в ОЗУ, а дальше начинаем его гонять твоим методом. Получится намного компактней чем делать непосредственную загрузку из регистров.

              А можно случайные числа и так нагенерить, если есть ацп. Включить ее и начать брать самый младший бит — он почти всегда случаен. 8 самых младших битов снятых с ацп дадут тебе совершенно случайный байт. Случайный от природы — :)

              1. Мда…
                Вопросы растут по экспоненте…
                Вот код написал, но он не работает по-человечески (массив — из таблицы случайных чисел), можете помочь?:
                ———————————————————————
                .cseg
                .def temp = r16
                .org 0xEF
                Array: .db 28,69,66,39,75,31
                .db 35,18,87,21,32,46
                .db 123,38,86,89,93,75
                .db 54,47,59,98,76, 6
                .db 147,59,239,244,170,66
                .db 92,162,1,7,28,89
                .db 78,5,15,154,38,19
                .db 84,7,33,8,77,94
                .db 93,56,5,99,89,54
                .db 3,54,63,6,65, 84
                .db 213,90,83, 111,159,3

                ldi ZH,High(Array*2) ;загрузка адреса метки в
                ldi ZL,Low (Array*2) ;регистровую пару Z
                lpm ;загрузка ячейки по адресу (Z)
                mov temp,R0 ;копирование загруженного байта
                ———————————————————————
                1: Прогоняю пошагово, жёлтая стрелка доходит до 4й строчки массива и перескакивает на 1ю массива, до ldi даже не доходит. Однако во Флэш эти циферки лежат блин… (и ещё заметил какие-то махинации/изменения в SREG, регистры R20,R19,R17, тоже пляшут, может я что-то из периферии завёл?)
                2: Не пойму по поводу команды lpm — она загружает из Флэш по адресу что в Z-слове в РАМ, а именно в RO ? Тогда почему RO ? RO-R15 же не юзают…
                3: И ещё, не совсем понял Структурно Вашу идею, ну допустим получим мы в R0 последовательно, все 50-60 случайных чисел, а потом…
                НЕ ВИЖУ компактного способа перегона этого всего в РАМ

                1. Ну а какого хрена ты разместил массив вначале программы? Процессору все равно, он не различает данные и код и пытается твой массив случайных чисел выполнить аки команду. образуя при этом случайные команды процессора %)))

                  Поставь массив ПОСЛЕ кода.

                  2. А что сложного то?
                  В Z адрес твоего Array — это ты уже сделал.
                  В X адрес твоего массива который будет в памяти.

                  Дальше LPM и из R0 делаешь ST X+,R0 — перекладываешь в память. Если СТ не работает с R0 то либо ищи команду LPM Rn (есть в некоторых авр, может и в твоем есть) и сохраняй в любой другой регистр, либо из р0 перекладывай в р16 и сохраняй уже оттуда.

                  Потом тебе надо увеличить Z на 1 чтобы выбрать следующий элемент памяти в флеше. Сделать это можно через вычитание отрицательной величины

                  SUBI ZL,(-1)
                  SBCI ZH,(-1)

                  Это увеличит оба регистра зед.

                  И повторить это в цикле 50 или сколько там у тебя раз. Для этого надо будет предварительно загрузить счетчик значением 50 и уменьшать его после каждого прогона командой DEC, проверяя результат на ноль — BRNE — в начало цикла.

  14. Привет!Спасибо за продуктивный ответ)
    Начинаю прозревать что по чём…
    Теперь хотел спросить вот что:

    1.Компилирую в студио, ток чот я не понимаю, как заставить студию шоб прогнала прогу столько итераций, сколько надо (то бишь нужное количество случ.чисел).
    Делаю пошагово, и за цикл число записывается в РАМ. Как сделать чтоб прогнала до конца и записала в РАМ все числа? (после нажатия ф5 никаких изменений не вижу)

    2.Теперь другй большой косяк. Допустим я оставляю 4 строчки массива, в итоге эти числа есть в РАМ, а потом там ещё какие-то числа… ОТкуда? Я ж ничего не пишу больше туда…

    3. Что происходит когда стрелка пошагово в каждом цикле доходит до .db ?
    Происходит запись каждый раз массива во Флэш?

    4. И на сладкое :( как только ставлю 5 и более строчек в массиве, прогоняю пошагово, а стрелка доходит до 4й строки, пару раз дрогнет и снова в начало цикла.
    До SUBI даже не доходит. Причём снова эти махинации сo SREG и некоторыми РОН, что я не использую…

    6. вопрос про аврСтудио, не пойму как поставить DataBreakpoint:
    * курсор перед Loop
    * захожу в Debug -> DataBreakpoint: ничего не меняю а лишь ставлю 18 в поле Break Execution After
    * Syntax error: Symbol expected. ????????(

    7. А ещё вопрос немного отвлечённый, что означает два знака неравенства подряд , не равно?
    ————————————————————————————-
    .include «m16def.inc» ; Присоединение файла описаний
    .list ; Включение листинга

    .cseg
    .org 0x2D

    ldi ZH,High(Array*2) ;загрузка адреса метки в регистровую пару Z
    ldi ZL,Low (Array*2) ;(а именно загрузка адреса первого элемента массива)

    .dseg
    .byte 55
    .cseg
    clr XH
    ldi XL, 96 ;Загрузить в XL, адрес начального регистра РАМ
    Loop:
    ldi r17, 66
    lpm ;загрузка в r0, ячейки, адрес которой в(Z)
    mov r16,r0 ;копирование загруженного байта в r16
    st X, r16

    Array: .db 13, 69, 66, 39, 75, 31 ;
    .db 35, 18, 87,21, 32, 46
    .db 123, 38, 86, 89,93, 75
    .db 54, 47, 59,98, 76, 6
    .db 147, 59, 239, 244, 170, 66
    .db 92,162, 1, 7, 28, 89
    .db 78, 5, 15, 154, 38, 19
    .db 84, 7, 33, 8, 77, 94
    .db 93,56,5, 99, 89, 54
    .db 3,54,63,6, 65, 84
    .db 213, 90,83, 111, 159, 8

    SUBI ZL,(-1)
    SBCI ZH,(-1)
    SUBI XL,(-1)

    dec r17
    brne Loop
    nop

    ————————————————————————————-

    1. Вот ,уже лучше. Только вместо SUBI XL,(-1) лучше юзай команду st X+,R16 при сохранении, тогда у тебя Х увеличится автоматом после выполнения и SUBI XL,(-1) не потребуется вовсе.

      А не работает потому, что ты ОПЯТЬ ЗАПИХАЛ ДАННЫЕ В КОД!!!! И он опять пытается их выполнить словно команды.

      3. Что происходит когда стрелка пошагово в каждом цикле доходит до .db ?
      Происходит запись каждый раз массива во Флэш?

      НЕТ! В этот момент процессор думает, что перед ней очредная инструкция и пытается ее выполнить. ОН НЕ Различает данные и код. Данные надо писать туда куда процессор не сможет добраться самовольно. Например в самом конце программы, а перед данными делать

      RJMP Reset

      чтобы данные не выполнились.

      1. Спасибо за комментарии — очень ценные и всё по делу.
        Код изменил — запись в РАМ прошла успешно:
        cseg
        .org 0×2D

        ldi ZH,High(Array*2) ;загрузка адреса метки в регистровую пару Z
        ldi ZL,Low (Array*2) ;(а именно загрузка адреса первого элемента массива)

        .dseg
        .byte 55
        .cseg
        clr XH
        ldi XL, 96 ;Загрузить в XL, адрес начального регистра РАМ

        ldi r17, 56

        Loop:

        lpm ;загрузка в r0, ячейки, адрес которой в(Z)
        mov r16,r0 ;копирование загруженного байта в r16
        st X+, r16

        SUBI ZL,(-1)
        SBCI ZH,(-1)

        dec r17
        brne Loop
        nop

        Array: .db 13, 69, 66, 39, 75, 31 ;
        .db 35, 18, 87,21, 32, 46
        .db 123, 38, 86, 89,93, 75
        .db 54, 47, 59,98, 76, 6
        .db 147, 59, 239, 244, 170, 66
        .db 92,162, 1, 7, 28, 89
        .db 78, 5, 15, 154, 38, 19
        .db 84, 7, 33, 8, 77, 94
        .db 93,56,5, 99, 89, 54
        .db 3,54,63,6, 65, 84
        .db 213, 90,83, 111, 159, 8

        1. Теперь у меня другая задача, подскажите в какую сторону и «чем» копать:

          Сейча мне нужно брать из этого массива элемент самый последний в этой куче, то бишь 56й, добавлять 25й сохранять сумму в 56м и результат выплёвывать в порт.
          Короче если тупо в лоб:
          ==========================================================================
          lds r18, 151 ; Загрузить в r18 содержимое SRAM по адресу 151
          lds r19, 120 ; Загрузить в r19 содержимое SRAM по адресу 120
          add r18, r19 ; Прибавить к r18 содержимое r19
          sts 151, r18 ; Записать обратно
          ; выплёвывание в порт А микроконтроллера
          ==========================================================================
          далее мне нужно декрементировать индекс этих двух элементов массива (теперь это уже 55й и 23й)и по аналогии суммировать и в порт.
          Когда младший индекс станет равным 1 — то следующий элемент уже брать снова из 56го, соответственно когда старший — то ему 56й… и т.д.
          Команды толком не знаю, поэтому не представляю через что это организовать,
          Надо как-то последовательно (в цикле с проверкой на минимальный адрес 0х60) суммировать и перезаписывать элементы массива в РАМ.
          Читал Вашу статью по работе с памятью, всё ясно, но чтобы с декрементацией адреса регистров РАМ работать не нашёл ничего полезного…
          Что посоветуете?)

          1. Ну почитай систему команд чтоль. Их там всего 130.

            Тебе проще наверное ввести какой нибудь базисный указатель и от него плясать, при выборе чисел. А потом просто сдвигать этот указатель и все.

  15. Салют DI HALT!
    Вроде сделал я генерацию, отсимулировал тоже вроде, но не могу прошарить в
    аврСтудио, не пойму как поставить DataBreakpoint для определённого цикла (задолбался тыкать пошагово):
    * курсор после нужного Loop
    * захожу в Debug -> DataBreakpoint: ничего не меняю а лишь ставлю 18 в поле Break Execution After
    * Syntax error: Symbol expected. ????????(
    ———————————————————————————-
    И ещё, что значит символы больше и меньше подряд без пробела (типа А B ) ? Это означает A не равно B ?

      1. 1. Чтобы не проходить весь цыкл пошагово выдели команду ПОСЛЕ цыкла и нажми F9 — слева появится красный кружок. Чтобы пропустить цыкл нажми F5 и студия быстро его прокрутит и остановится на строке после цыкла.

        2. AB — означает A не равно B.

  16. Подскажите плиз логику WinAvr
    Например функции:
    uint8_t eeprom_read_byte (const uint8_t *__p);
    uint16_t eeprom_read_word (const uint16_t *__p);
    uint32_t eeprom_read_dword (const uint32_t *__p);
    Вот например описание первой функции: Read one byte from EEPROM address __p.
    Однако они все должны принимать адрес в int так как память адресуется 9 битами, и при извлекании любого числа адрес будет всегда 9 битный тоесть int.

    Atmel приводит коректные функции
    void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
    unsigned char EEPROM_read(unsigned int uiAddress);

    Это косяк WinAvr? Так как я немогу понять как 8-битный указатель может передать 9 битный адресс.

    1. А с чего ты вообще взял, что int это 9ти битный тип данных? Такого воообще по моему не бывает в природе, т.к. выравнивание идет по 8битам.

      А ииц епром оперирует семибитным адресом + бит направления.

      1. int — 16 бит, если конечно явно не изменять
        я наверно не так поставил вопрос, но уже сам разобрался
        память в 8меге адресуется 9 битам, в 32меге — 10 битами, просто в WinAvr делается ненужное преобразование указателя, а так как указатель 2 байтовый поэтому вся память доступна

  17. Уважаемые форумчане! Подскажите пожалуйста.Мне необходимо записать EEPROM константы с 0 адреса практически на весь обьем EEPROM. Этот кусок будет использоваться со сменяемыми рабочими программами.
    Написал программу используя пример из инета: (далее цитата)»В ряде случаев нужно предварительно заполнить EEPROM константами, которые будут использоваться в дальнейшем при работе программы. Для этого в исходный текст программы нужно включить следующее определение
    (например для заполнения 32 байт, начиная с адреса 0):
    __EEPROM_DATA (0x41, 0xA0, 0x42, 0xA1, 0xE0, 0x45, 0xA3, 0xA4);
    __EEPROM_DATA (0xA5, 0xA6, 0x4B, 0xA7, 0x4D, 0x48, 0x4F, 0xA8);
    __EEPROM_DATA (0x50, 0x43, 0x54, 0xA9, 0xAA, 0x58, 0xE1, 0xAB);
    __EEPROM_DATA (0xAC, 0xE2, 0xAD, 0xAE, 0x20, 0xAF, 0xB0, 0xB1);
    ^^ два символа подчеркивания!!!
    Этот текст нужно включать вне какой-либо функции. »
    НО AVR-Studio просто не видит подобную запись, просто не реагирует.
    Может быть есть вариант записи?

  18. При старте проца и нарастании питания или его бросках, схема управления EEPROM-ом может закосячить байт. Закосячится естессно тот байт, на адрес которого указывает EEAR. А если в этом байте лежат флаги или другие критичные данные- получаем писец форева. Лично столкнулся с этим на Attiny 2313. При очередном включении питания устройство просто переставало функционировать. Теперь появилась фобия: нулевой байт не использую, а в конце процедур записи-чтения обнуляю EEAR. Еще включаю внутренний контроль питания.

    1. Сбои эти известны по даташиту.
      Стоит tiny13 в мышке уже несколько лет. Режим работы как раз хранится в 0-м байте eeprom. Пока ни разу не запороло. Но это и не удивительно — условия то тепличные.
      BOD активирован. Также в алгоритме раньше была программная защита от каши — если номер режима не входил в интервал рабочих, он сбрасывался на стандартный.
      В более поздних прошивках защиту выкинул, вместо нее стал кодировать режим побитно — так защита автоматом обеспечивается: какая бы там не была каша, все равно какой-нибудь режим активируется, без зависаний или остановок из-за неизвестного номера режима.
      Также экономлю ресурс eeprom, несмотря на то, что запись туда идет крайне редко: перед записью сравниваю то, что записано с тем, что пишем — если одинаково, нет смысла писать еще раз.
      Питание тоже стабильное — комп как никак.

  19. Хочу записать большой массив в EEPROM отдельно от программирования МК.\Дело в том что массив коэффициетов достаточно большой и првышает по обьему основную программу в пару раз, как минимум.
    Наконец нашел:
    Кннга Мортон Джон. Микроконтроллеры AVR. Вводной курс. 2006.
    На стр. 141 «Занести данные в EEPROM при программировании микроконтролле¬ра можно двумя способами. В программе AVR Studio перейдите к меню View -> New Memory View (AK+4) и выберите EEPROM. При этом на экране появится окно, в котором будет отображено содержимое EEPROM. Прос¬то введите значения, которые вы хотите записать в EEPROM, а при выборе программатора (например, STK500) в блоке «EEPROM» выберите пункт Current Simulator/Emulator Memory. В результате содержимое окна EEPROM будет записано в EEPROM-память микроконтроллера.

    Но у меня в AVR Studio меню View -> New Memory View (AK+4) отсутствует.
    Может кто подскажет как записать данные в EEPROM до основного программирования микроконтроллера.

    1. Создать в программе секцию .EEPROM и после нее обыными полями .db внести нужные данные. После компиляции будет не только хекс, но и .eep файл. Вот ееп это и есть чистые данные для еепромки. Можно заливать программатором.

  20. Вопрос к автору. Откопипастил приведенный в статье пример для записи в eeprom одно байта, получилось это:

    M1800: ;ПП ЗАПИСИ В ЭНЕРГОНЕЗАВИСИМУЮ ПАМЯТЬ
    ;(R17 — текущий этаж)
    LDI R16,0x00 ;задать адрес ячейки
    SBIC EECR,EEWE ;ждем разрешения на запись
    RJMP PC-1 ;
    OUT EEARL,R16 ;задаем адрес для записи
    OUT EEARH,R16 ;задаем адрес для записи
    OUT EEDR,R17 ;записываемый байт
    SBI EECR,EEMWE ;предохранитель
    SBI EECR,EERE ;собственно сама запись

    ; SBIC EECR, EEWE ; проверка окончания записи
    ; RJMP PC-1

    RET

    Вроде все просто, но при симуляции в протеусе в энергонезависимой памяти ничего не меняется. В чем причина?

      1. В железе не проверял. Пока довожу до ума алгоритм, смотрю что получается в протеусе. Вообще хочу сварганить мозги для грузового подъемника. На работе электрики делают на релюхах, а я хочу попробовать все тоже самое, только на контроллере. И вот есть у последнего преимущество, может он запомнить положение кабины в межэтажном пространстве при внезапном обрыве питания, в отличии от релейной схемы, а тут на тебе такой касяк)))…. не запоминает таки в протиусе….))) может кто нибудь что нибудь подскажет по этому вопросу?
        И еще вопрос. В какой ветке почитать про схемотехнику. Нужно пускателем двигателя управлять, а как лучше организовать никак не определюсь, то ли реле, то ли триак, или еще что нибудь… Заранее спасибо за советы.

        1. В протеусе что то отличное от «диодиком помигать» доводить до ума бессмысленно — слишком там много глюков и приколов которые могут вылезти в железе в самый неподходящий момент.

          Запоминать положение в ЕЕПРОМ занятие бредовое. По крайней мере в AVR точно — слишком уж прихотливо епромка у ней к питанию и как мы не старались сделать так, чтобы епром не убивался по непонятным причинам так и не удалось. И питание стабильное и BOD включен — ан нет, раз на раз да сбойнет за пол года-год.

          Положение кабины надо ловить по датчикам. Если непонятно где, то не все ли равно куда ехать — вверх или вниз. На первом же встречном датчике поймешь где кабина.

          Ставь реле — предсказуемей, легче проверить работоспособность. Ремонтопригодней.

          З.Ы.
          И я бы эту схему делал на на МК, а на PLC например на Omron ZEN или Direct Logic DL-05 или чем то подобном. И надежней и приколов меньше вылезет.

          1. Так я пока только АЛГОРИТМ проверяю, а не всю схему, за пределы мигания диодиков никуда и не выхожу ).
            Что касается сбоев, то если раз в полгода, то это ооочень хороший результат.
            Положение кабины ловится как ты и сказал датчиками, я предполагаю простые нажимные концевики. В схеме на простых релюхах приходится ставить концевики на каждом этаже (ну у наших электриков так заведено (я кстати конструктором числюсь и к электрике никакого отношения не имею)), а на кабине нажимную планку. В целях экономии (а это основная цель) я подумал сделать наоборот, на кабине концевик, а на этажах приварить нажимные планки и тупо считать сколько нажался концевик когда кабина идет вверх, сколько вниз.
            Промышленные контроллеры ясное дело лучший вариант, только все упирается в деньги, а они не дешевые, плюс еще по портам получается надо брать где их поболе. Я не парясь взял мегу 16ю и как раз хватило на 10тиэтажку. Кстати есть еще проблема схода кабины с концевиков при загрузке или разгрузке, тупо трос растягивается под весом, и тут наши элетрики с релюшками своими прибывают в «легком недоумении», т.к. по ихней схеме это воопсче нештатная ситуация и после такого казуса с поста управления кабину никуда не пошлешь, нужно принудительно ставить на концевик. Я то конешно предусмотрел это и сделал доводку (хорошо бы сделать плавную с ШИМом, но не силен я в схемотехнике, прогу то напишу, а вот как это все дело подключить к движуле?? Вопрос…).
            И еще вопрос. Есть посты управления. Там кнопки. При коммутации цепи в 24В кнопки эти сбоили сильно, то залипнут, то не сработают. Решили повысить напряжение до 220В, работает надежнее, а для меня засада какая то. Никак не могу выбрать схему снятия сигнала пригодного для МК с этих кнопок. Да и с концевиками такая же беда. Заранее спасибо.
            Кстати, если кому интересно могу поделиться файликами

            1. Алгоритм можно и в АВР студии отлаживать, хотя в протеусе удобней, ага.

              А если кабина будет на 3м, а твой контроллер будет думать что на 8м и поедет вниз. Вобьет в землю? А если концевик не сработает и этаж просчитается?

              Привязка координат должна быть железной, а не программной.

              Не хочешь ставить по концевику на этаж? Не проблема — поставь на кабину ЧЕТЫРЕ Концевика, а на этажах нажимные планки выдающие КОД этажа на этих концевиках.

              Чтобы кабина не сходила концевик должен быть роликовым, а упоры под него длинные, с запасом. Раз точности нет.

              Теперь по ШИМу — вам вообще пологается не колхозить (дороже выйдет, и намного), а поставить драйвер движка и им уже управлять. Т.к. мощность там порядочная все же. Ну либо на контаткорах тупо релейно щелкать, но тут о доводке придется забыть, ага.

              Чтобы кнопки на 24 вольта не глючили надо делать опторазвязки да кондеры ставить блокирующие — провода там длинные, наводки на них небалуй. Т.е. идти в сторону токового сигнала ,а не напряженческого.

              «только все упирается в деньги, а они не дешевые»
              Вообщет все упирается в человеческую жизнь тех кто на этом лифте будет ездить.

              На дешевый малопортовый ПЛК в 90% можно довесить модулей расширения. И да, по времени и трудозатратам (вы же там не за еду работаете, да?) купить готовый ПЛК будет раза в два (если не в пять) дешевле чем вы там наколхозите (тем более, судя по вопросам, опыта у вас немного), но будет в разы надежней и безопасней.

              1. Проблема в том, что в одном комменте все не напишешь, а отсюда по моему такой скептицизм))) Конечно же есть цепи безопасности, которые дублируют этажные концевики, конечно есть система резкого торможения, которая не даст кабинке упасть и отключит движулю в случае провисания троса.. и конечно роликовые концевики, и регулируемые планки можно длинные сделать (только точность остановки в полсантиматра потом как ловить )))) ) Это все механика, я в про нее и не спрашиваю.
                Идея была — повторить релейную схему на контроллере, но раз уж такой гуру как ты говорит, что не стоит городить огороды, то тогда я начинаю разочаровываться во всех этих кустарных колхозах. И для кого тогда эти гигабайты любительских сайтов, километровые портянки коментов на твоем сайте? Для любителей помигать лампочками? Но это так… отступление…)))
                По поводу кондеров и опторазвязки,на какой ветке можно схему посмотреть? Все таки ради эксперемента я думаю можно что нить помудрить, все равно дальше моих эксперементов это народное творчество никуда в массы не пойдет)

                1. «которая не даст кабинке упасть и отключит движулю в случае провисания троса..»
                  Этого мало. Представь ты едешь на лифте, вдруг у него посреди шахты внезапно открывается дверь, ты поворачиваешься, у тебя на повороте заносит поясную сумочку, дверь тут же закрывается, зажимая сумку, а тебе ремнем сумки отрывает голову :) Или открывает дверь шахты, а лифта там нет :) Хотя тут и на реле надежды нету, лучше механические блокировки.

                  Релейную схему можно повторить на контроллере, несомненно. Но если делать все правильно, со всеми защитами, чтобы не сбоило и не глючило, то выйдет дороже чем покупка готового стандартного решения. Только и всего. Что то свое имеет смысл изобретать когда нет готового решения. Для этого и мой сайт. Ну или когда ваяешь какую нибудь простую систему с низкой себестоимостью, где втыкать контроллер в за килобакс как то не рентабельно совсем. Схема управления лифтом (равно как и любое другое пром оборудование) имхо в этот ряд не входит.

                  Про гальваническую развязку я еще не писал ничего.

                  1. «Представь ты едешь на лифте» ))) так я про лифт тоже ничего не писал. На грузовых подъемниках люди не ездеют, потому как нет там поста управления внутри кабины. Двери все открываются вручную, никакой автоматики, только на дверях концевики цепи безопасности, пока двери не закроешь пост управления работать не будет. Так же и электрозащелки не дадут дверь открыть, если кабины нет на этаже, вот и вся безопасность. И неужели контроллер не сможет справиться без сбоев с за дачей, которая выполняется элементарно релейной схемой!!!???
                    По поводу цены — был опыт использования пром контроллера, который весил примерно 500 американских рублей, ну…. как то дороговато…
                    Еще хочу тебя успокоить, никуда «в массы» мой «колхоз» не пойдет, я думаю максимум чем ограничится — это опытным образцом, который как ты и предсказываешь будет работать не стабильно ))) Поэтому за совесть свою можешь быть спокоен ))), никто не пострадает))), можешь советовать в удовольствие ))).
                    Просто есть возможность поэксперементировать, почему бы и нет?
                    Вот как то так…
                    А вопрос то простой мне кажется. Всего то лишь: есть ток в цепи переменного напряжения в 220В — пусть будет лог1 на ноге контроллера, нет тока — лог0. И всё. И для безопасности с опторазвязкой. Я терминологией не владею, мне кажется это называется детектированием сети (поправь если не прав). В апноуте видел детектор перехода через ноль, который состоит из одного мегаомного резистора, но даже мои скудные познания схемотехники подсказывают, что стремновато это )))
                    Поиск в инете ничего не дает по этому вопросу, поэтому и обращаюсь.

                    1. А зачем тебе 220 в управляющей сети? 24 вольт вполне хватит. А опторазвязка на оптопаре делается. Т.е. входной сигнал зажигает в ней светодиод, а его свет открывает фототранзистор, который прижимает ногу контроллера к земле. как кнопка.

                    2. Пробовали уже 24В, почему то кнопки, которые мы используем не срабатываю, часто сбоят. Причину точно сказать не могу, может среда влияет (ставим и на улице, и в цехах повышеной влажности, а еще какой нибудь работник из шланга всю эту канитель помоет ))) ), вобщем много причин. Из опыта пришли к выводу что 220 именно для срабатывания самое надежное и простое.
                      Вот если взять PC817, у нее есть рабочее напряжение V и ток срабатывания I? Так? Значит я ставлю диодный мост (4007 подойдет?), потом конденсатор для сглаживания (номинал даже не знаю с какого боку узнать), а потом мне надо снизить напряжение и ток до V и I соответственно, так? Ток, я так думаю, надо резистором снижать, а вот что с напряжением то делать???

                    3. Ток снижать смысла нет — схема сама возьмет сколько ей надо. А напряжение можно сбить резисторным делителем.

  21. Здравсвуй DI HALT!

    Какие меры можно предпринять для защиты от покосячинга EEPROMа при снижении напряжения питания? Я так понимаю в первую очередь это монитор питания. А программно? И дадут ли эти меры 100% гарантию?

    И вот ещё что… наткнулся я на просторах интернета на сайт allelectronics.3dn.ru
    Дык вот его дизайн слизан с вашего + в разделе КНИГИ коменты к книгам тоже ващи… Короче воруют…..

  22. Здравствуйте. может я не в тему конечно но:
    у atmel есть микрухи еепрома AT24c по i2С и AT25c по SPI.
    Если кто нибудь с ними общался не подскажите различие(я имею в виду скоростные характеристики(?)). Как долго пишется байт? или массив байтов…

    Мне нужно организовать поиск байта, вот думаю сколько он будет длиться….

      1. Шина SPI в принципе является намного более быстрой чем i2c плюс там отсутствует адресация девайса, в худшем случае страничная. Так что SPI при любом раскладе быстрей.

  23. Подскажите, пожалуйста, как с помощью Ик порта или другого оборудования считать и поменять данные из EEPROM.
    КР1095ПП1, 8-разрядного микроконтроллера MC68HC05KJ1

  24. У меня небольшой трабл с синапрог…
    она почему-то не считывает и не записывает в EEPROM
    http://cs411224.userapi.com/v411224467/181d/_soCWtvxC8o.jpg
    Вот скрин, я сначала записал туда от балды намалеванную базу данных на 3 байта — нажал program в синепрог, она написала что записано 3 байта и вообще все ок, но когда нажал читать, он тоже выдал ОК, но при этом считал вон ту фигню на скрине…

    Даже программа мк когда считывает данные из ЕЕPROM, у нее этих значений нет, тоесть нули тупо, вместо данных.
    Тем не менее когда я записываю значение через свою программу, которая в МК, они записываются. и дальнейшая программа их считывает и все окай.

    Тоесть они там появляются после записи программой МК, а сина не записывает почему-то… И не читает тоже, хотя там есть данные…

    Пробовал на тини2313а и АТмега32L

    Чего не так делаю подскажите пожалуйста :(

      1. Флеш читает. Сам в шоке и не понимаю чего происходит.
        Раньше честно говоря ни когда не проверял эту функцию и с еепром не работал…
        И вот те на))

        Даж не знаю че делать :\

      2. У меня тоже при прошивке по ходу похожая проблема но не уверен .
        Может у кого будет возможность помочь заглянте в ветку чтоб не описывать снова http://forum.easyelectronics.ru/viewtopic.php?f=4&t=18119
        Не работает рабочая прошивка в Led cube 8*8*8
        Как можно проверить нормально ли зашивается и работает ЕЕPROM ?
        Программатор USBasp Sina Prog

  25. Привет, у меня вопрос: почему могут самопроизвольно меняться данный в EEPROM когда остальной код выполняется?
    Пишу в CV, вроде все нормально, по ходу работоспособность проги тестю и вдруг Бац, эта сука начинает чёрти че творить в памяти — в AVR студии смотрю, основной массив при инициализации не пишется, а в циклах на каждый шаг ячейки сами шьются…
    Кто нибудь сталкивался с таким?

    1. Бывает такая беда. У AVR вообще с EEPROM постоянно что то странное творится. Во первых данные могут хериться если запись производится на пониженном напряжении. Так что включаем BOD, чтобы на пониженном напряжении не работало вообще ничего. ВО вторых не рекомендую держать загруженными указатели еепрома и, соответственно, ничего не писать в нулевую ячейку.

  26. Доброго времени суток. Вот у меня возникла проблема с эмулятором AVR Studio 4. При использовании директивы ESEG данные не хотят попадать в память EEPROM, если убираю директиву ESEG, то всё отлично пишется в память программ. В память данных тоже писать не хочет (добавляю .org $60). Может я какую настройку пропустил?
    .eseg
    .db $FC, $60, $DA, $F2, $66, $B6, $BE, $E7
    .db $FE, $F6, $EE, $3E, $9C, $7A, $9E, $8E
    .cseg
    Заранее спасибо.

    1. Аналогичная ситуация в Atmel Studio 6.
      Самое что интересно, в окне Output пишет:
      Segment Begin End Code Data Used Size Use%
      —————————————————————
      [.cseg] 0x000000 0x00020a 482 40 522 8192 6.4%
      [.dseg] 0x000060 0x000060 0 0 0 1024 0.0%
      [.eseg] 0x000000 0x0001ff 0 37 37 512 7.2%
      Assembly complete, 0 errors. 0 warnings
      А в окне Memory в EEPROM пусто (все 0xFF).
      И при попытке считать из EEPROM, тоже читает 0xFF.
      Никакого *.eep файла или чего-то похожего в папке проекта нет.
      Подскажите, как быть?

    1. В еепром можно писать побайтно, в флеш только секторами. Еепром в десятки тысяч раз больше циклов перезаписи выдерживает, еепром требует намного меньше энергии для записи. Еепром быстрей.

  27. Добрый день, прошу помощи ситуация следующая:
    контроллер atmega8A, использую eeprom но данные не сохранаются после выключения питания.
    проверял так есть 2 кнопки, нажатие на первую записывает данные в еепром, по нажатию на вторую данные считываются и проверяются.
    проверяю так:
    1. подключаю питание — контроллер стартует
    2. жму 1-ю кнопку — данные записались
    3. жму 2-ю кнопку — данные считались, проверка данные прошла успешно
    4. выключаю питание — контроллер выключается
    5. подключаю питание — контроллер стартует
    6. жму 2-ю кнопку — данные считались, но проверка данных не прошла, считалось значение 0xff

    до этого использовал atmega16 там все работало без проблем, перешел на atmega8 и все данные перестали сохранятся после отключения питания

  28. DI HALT, подскажи пожалуйста: собираюсь использовать ЕПРОМ совместно с операционной системой (на асме, Трэшдуино, или как там ты ее называешь, а я называю DI HALT OS ;), так вот там у нас системные прерывания генерятся раз в милисекунду по таймеру, а здесь цикл записи 1.8 мс ну и чтения так-же, а стирание и запись (атомарная операция) еще дольше. Вопрос: как сделать на прерываниях? там же флаг готовности надо ждать, а сколько это по времени? ни разу просто еще ничего в епром не записывал

    1. Я бы как сделал… Завел указатель на данные которые надо записать и на количество этих данных. А дальше как с уартом. Записываем первый байт, а прерывание по ЕЕ ОК хватает второй байт и пишет уже его. И так пока все не перелопатит. А дальше ставит где-нибудь флаг ,что все ок или запускает итоговую задачу.

  29. Di как всегда на высоте уровень изложения материала… но маленькие уточняющие вопросы по теме переменная типа bit может ли храниться в eeprom ?? Просто возникла необходимость хранения кучи флагов событий…. Если нет то как отнесется компилятор к такой теме ….char eeprom PEREM….
    PEREM |=(1 << 7)|(1 << 5)|(1 << 3); побитовый доступ ???

    1. Может, но займет целый байт. Она и в памяти столько же занимает, кстати. Побитового доступа там тоже быть не может. При изменении будет перезаписан весь байт. Так что только чтение-модификация-запись.

      1. Спасибо за ответ еще одни вопросик по теме рисую прогу на управление Твердотопливного котла ….с переменным успехом …. есть куча температурных датчиков ds18b20 и необходимо записать в eeprom его ROM, но вот беда на запись типа eeprom_write_byte нет реакции уже всякими извращенными вариантами пробовал в студии место в переменной sensor [] упрямо остаются пустым … не подскажете где грабли ??
        ……
        w1_search(0xf0,&sensor_kotel);
        lcd_clear();
        dd_lcd( «СЕРИЙНЫЙ НОМЕР»,14);
        lcd_gotoxy (0,1);
        for (j=0;j<8;j++)
        {
        eeprom_write_byte(sensor[1][j],sensor_kotel[j]); /////____________?????????
        sprintf(lcd_buffer,"%02X",sensor[1][j]);
        lcd_puts(lcd_buffer);
        };
        measure(sensor_kotel);

        1. Разбирайтесь с функцией eeprom_write_byte куда она пишет и что. А то дается мне она пишет в eeprom контроллера, а не датчика. НУ и еще момент, если все же надо писать в еепром контроллера, то кто вам сказал, что это будет сделано за один такт? В симуляторе это происходит за несколько десятков тактов. Так что на следующем шаге ничего не произойдет, и на последующи и так далее, пока не поднимется флаг.

  30. Спасибо за ответ я знаю что запись в eeprom медленная и таки да запись ведется в eeprom контроллера ….. но в данном цикле запись не происходила… вывел запись в eeprom из цикла и вуаля все записалось и завертелось, одно но ругательств компилятор не выдавал ни в одном ни в другом случае…. сейчас все пишется в eeprom контроллера без вопросов.

Добавить комментарий