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.: 20 комментариев

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

    Ответить

    sarge Ответил:

    Добрый день,

    Почему не читаете значения в цикле? Организовали цикл и считывайте хоть всю EEPROM.

    Ответить

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

    Ответить

    sarge Ответил:

    так а че тут показывать то:

    for (unsigned char temp = eeprom_reg_first; temp &lt;=eeprom_reg_last)
    {
    read_value[temp] = eeprom_read(temp);
    }
    

    Ответить

    Костя Ответил:

    спасибо за совет . вроде работает .
    вот так вышло
    for(i = 0; i < 8; i++) {
    addr = EEPROM_READ(0x00+i); } читать – читает ,а как вывести прочитанное на lcd в одну строку ? тоже циклом ?

    Ответить

    Костя Ответил:

    все получилось .спасибо .на очереди i2c .

    Ответить

    sarge Ответил:

    Хорошо, что получилось :)

    Ответить

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

    Ответить

    sarge Ответил:

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

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

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

    Ответить

    Paulwasw Ответил:

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

    Ответить

    sarge Ответил:

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

    Ответить

    Paulwasw Ответил:

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

    Ответить

    sarge Ответил:

    Спасибо, что отписались :)

    Ответить

    il86md Ответил:

    А какое время требуется для того чтобы записать данные в ячейку? Тоесть для перезаписи в туже ячейку требуется несколько милисек… может я чтото делаю не поравильно? Почему так долго?

    Ответить

    sarge Ответил:

    Длительность цикла записи/стирания от 4 до 8 мс по даташиту.

    Ответить

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

    Ответить

    sarge Ответил:

    Если сделаете код, то я добавлю пример. Какая разница в какой IDE код?

    Ответить

    Student4596 Ответил:

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

    Ответить

    sarge Ответил:

    Ну значит вы обращаетесь не по адресу, у меня времени этим заниматься тоже нет.

    Ответить

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

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

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">