PIC мк. Эксперимент №12. Работа с EEPROM.

Задача: Запись и чтение из внутренней энергонезависимой памяти EEPROM

Исходный материал: PIC16f628a и простенькая devboard.

Микроконтроллер PIC16f628a имеет на борту 128 байт EEPROM, не шибко много, но что есть то есть. Обычно в компиляторах уже есть встроенные функции записи/чтения из памяти, Hi-tech PICC не исключение, но здесь я приведу разработку своих функций с нуля. Начнем с регистра EECON1:

ee

EEPGD – В микроконтроллере PIC16f628a не используется
WRERR – флаг ошибки
• 1 – операция записи прервана
• 0 – операция записи прошла успешно
WREN – Разрешение записи в EEPROM
• 1 – Операция записи разрешена
• 0 – Операция записи запрещена
WR – Контрольный бит записи
• 1 – Инициализация записи
• 0 – Запись завершена
RD – Контрольный бит чтения
• 1 – Инициализация чтения
• 0 – Чтение завершено

*Биты WR и WD нужно устанавливать только в “1”, сброс в низкое логическое состояние происходит автоматически, после завершения операции

Кроме этого есть еще вспомогательные регистры:

  1. Регистр EEDATA – 8 битный регистр, служит буфером, куда помещаются данные при чтении/записи.
  2. Регистр EEADR – 7 битный регистр, указывающий адрес куда будет производится запись или адрес, откуда нужно прочитать данные.
  3. Программный регистр EECON2 – регистр использующийся исключительно для операции запись в EEPROM, для успешной операции записи необходимо последовательно записывать в этот регистр следующее выражение:
EECON2=0x55;

EECON2=0xAA;

Да, еще, для EEPROM также может генерироваться прерывание – флаг EEIF устанавливается при успешной операции записи.

Порядок чтения из EEPROM:

  1. Запись нужного адреса в регистр EEADR.
  2. Установка бита RD в “1”.
  3. Данные сохранены в регистре EEDAT и готовы для использования.

Порядок записи в EEPROM:

  1. Запись нужного адреса в регистр EEADR.
  2. Запись данных в регистр EEDAT.
  3. Установка WREN в “1”.
  4. Запись в регистр EECON2 0x55 и 0хАА.
  5. Установка бита WR в “1”.

Также в даташите сильно просят отключать на время записи прерывания, вот в принципе и все. Уже можно работать с EEPROM.

Код -пример работы:


#include <htc.h>
#define _XTAL_FREQ 4000000

__CONFIG(MCLRDIS & UNPROTECT & WDTDIS & LVPDIS & HS);
unsigned char eeprom_read_my(unsigned char adres);                       // инициализация операции чтения
unsigned char eeprom_write_my(unsigned char data, unsigned char adres);  // инициализцация операции записи

void main() {
 unsigned char temp=0;
 CMCON = 0x07;               // Выключаем компараторы
 TRISA = 0xFF;
 TRISB = 0x00;
 temp = eeprom_read_my(0x07); // Читаем нужный адрес

 for (;;) {
    PORTB = temp;                // Присваиваем порту Б значение из EEPROM
            if (!RA1) {
                      __delay_ms(100);
                             if (!RA1) {
                                       if (temp < 240) {                    // Пишем в память значения от 16 до 240, с шагом 16
                                                       temp = temp + 16;
                                                       eeprom_write_my(temp, 0x07);
                                                       } else {
                                                               temp = 16;
                                                               eeprom_write_my(temp, 0x07);
                                                               }
                                       }
                      }

            }

 }

unsigned char eeprom_read_my(unsigned char adres) {
                                                 EEADR = adres;
                                                 RD = 1;
                                                 return EEDATA;

}

unsigned char eeprom_write_my(unsigned char data, unsigned char adres) {
 GIE=0;
 EEADR=adres;
 EEDATA=data;
 WREN=1;
 EECON2=0x55;
 EECON2=0xAA;
 WR=1;
 GIE=1;

}

Видео с примером работы кода на devboard:

Ну и до кучи фото с состоянием порта B:

fotka

А также состояние EEPROM в этот момент:

eeprom status

По адресу 0х07 записано число 0х50 = 0b01010000 (B4 = 1 и B6 = 1 на прошлой картинке).

Исходники на репе здесь.

PIC мк. Эксперимент №12. Работа с EEPROM.: 21 комментарий

  1. Здравствуйте . Много узнал на этом . Спасибо . Не могу разобраться с eeprom . Не подскажите как прочитать из памяти фразу целиком (пытаюсь сделать усилитель с темброблоком и lcd ) ? eeprom_read_my(0x07) это значение одного регистра , а как прочитать , скажем , подряд несколько адресов .
    там записана фраза “Громкость” .У меня получается только “Г” вывести __EEPROM_DATA(1,0xa1,0x70,0x6f,0xbc,0xba,0x6f,0x63);
    __EEPROM_DATA(0xbf,0xc4,2

  2. Спасибо за ответ . Да я уже приблизительно в эту сторону и думал (я очень не давно занимаюсь программированием , да и микроконтроллерами тоже ) , но не знаю как правильно написать его . Если не затруднит можете пример привести . Чую где-то рядом топчусь , но пока не одолел . Спасибо .

  3. Уважаемый sarge!
    С большим интересом прорабатываю Ваши статьи. С Вашей легкой руки начал осваивать Си и уже кое-что получается. Еще раз хочу поблагодарить Вас за публикации!
    Возникла потребность использовать память EEPROM, в статье процесс хорошо расписан. Одно не смог осилить. Мне нужно на этапе прошивки МК заложить в EEPROM начальную информацию. Как это делается в ассеблере, я знаю. А вот как сделать это на Си, что-то запутался. Уж больно не хочется программировать кристалл по частям: основной код – на Си, а начальные данные EEPROM – на ASM. Понимаю, что задачка из “школьных”, но в Сети подсказок, увы, не нашел. Не так уж много статей по PIC на Си. Подскажите, пожалуйста.

    • Доброго времени суток, использовать еепром на си очень просто:

      eeprom_write(0x04, temp); — записали значение переменной temp по адресу 0x04

      temp = eeprom_read(0x04); — считали значение из адреса 0x04 в переменную temp

      • Это понятно, я хотел спросить о другом.
        В ASM могут присутствовать строки записи информации в EEPROM на этапе программирования, типа:
        Org 0x2100; (адрес EEPROM)
        DE 0x37, 0x7D, 0x00, 0x00, 0x02, 0x00, 0x00; (байты данных для программирования)
        Пытаюсь найти их аналог для программы на Си. Метод научно-исследовательского тыка тоже не помог – компилятор ругается. Можно, конечно, залить в кристалл только программу, а потом отдельно и начальную информацию EEPROM, но уж больно коряво это выглядит.

        • А, понял, но не сталкивался с таким вопросом никогда.
          Я бы наверное либо по старту писал либо просто еепром один раз прошил заранее отдельно

          • Ура! Решение найдено!
            Нужно вставить строку (строки):
            __EEPROM_DATA (0,1,2,3,4,5,6,7); // в скобках – записываемые данные
            Строк может быть несколько, данные будут записываться последовательно, а не накладываться. Саму строку рекомендуют располагать до объявления глобальных переменных, логично после строки с __CONFIG( ).
            А вот смещать адрес данных в EEPROM – надо писать макросы на ASM, несколько хлопотно. Проще указать для начальных ячеек значения 0xFF. Проверено на HI_TECH_Software v 9.71a – работает!

  4. А можно ли привести код-пример такой же программы только в программе MPLAB IDE и для микроконтроллера pic16f873?

      • Вы наверное не поняли вопроса) Не могли бы Вы составить такую же программу и написать ее в МPLAB IDE для pic16f873 и выложить сюда?) Просто очень нужна помощь, а времени разбираться нету((

  5. Уведомление: Pic Lab, PIC16, Experiment #12, EEPROM | diymicro.org

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.