В предыдущей части урока мы познакомились с организацией, а также с чтением и записью памяти EEPROM, создали проект и написали библиотеку для работы с EEPROM.
Теперь перейдём в файл main.c и попробуем что-нибудь записать и затем считать из памяти EEPROM.
Первым делом удалим вывод тестовых строк
LCD_String((char*)"String 1");
LCD_SetPos(2,1);
LCD_String((char*)"String 2");
LCD_SetPos(4,2);
LCD_String((char*)"String 3");
LCD_SetPos(6,3);
LCD_String((char*)"String 4");
Добавим строковый массив и несколько локальных переменных
void main()
{
char str1[21];
unsigned long i=0,j=0,dtt=0;
Сначала запишем несколько байтов в EEPROM
LCD_Init();
//Bytes
for(i=0;i<40;i++)
{
EEPROM_WriteByte(i,0x40+i);
}
Затем данные байты прочитаем и отобразим на дисплее в шестнадцатеричном виде
EEPROM_WriteByte(i,0x40+i);
}
for(j=0;j<4;j++)
{
for(i=0;i<10;i++)
{
dtt=EEPROM_ReadByte(j*10+i);
LCD_SetPos(i*2,j);
sprintf(str1,"%02X",dtt);
LCD_String(str1);
}
}
Соберём проект, прошьём контроллер и посмотрим результат на дисплее
Всё нормально пишется и читается.
Теперь давайте попробуем, сохраняются ли у нас наши данные после отключения питания и перезагрузки микроконтроллера.
Для того, чтобы это проверить, закомментируем участок кода, отвечающий за запись данных. У нас останется только код чтения из памяти
/*
for(i=0;i<40;i++)
{
EEPROM_WriteByte(i,0x40+i);
}
*/
Соберём код и прошьём контроллер. Кстати, отдельно собирать код не обязательно, можно сразу нажимать на кнопку «Run», перед заливкой прошивки проект соберётся.
И мы увидим следующий результат
Нам может показаться, что у нас EEPROM не сохраняется. На самом деле он сохраняется прекрасно, только при перепрошивке программатор его эффективно затирает.
Как же победить такой недочёт?
Заходим в свойства проекта, затем в свойства программатора и сразу же в разделе Memories To Program установим галку напротив строчки Preserve EEPROM Memory. После этого у нас появится ещё одна строка, напротив которой мы и напишем диапазон адресов нашей памяти EEPROM
Сохраним настройки проекта.
То есть, мы можем защитить от стирания программатором либо весь диапазон EEPROM, как мы сейчас и сделали, либо какую-то его часть.
Теперь раскомментируем код, где мы пишем байты в EEPROM, соберём и прошьём наш проект. Затем опять закомментируем данный участок кода и ещё раз наш проект соберём и прошьём.
Теперь мы видим, что всё у нас нормально и никакие байты не затираются при перепрошивке, то есть вся наша память EEPROM после выключения питания сохраняется. Это мы можем проверить отключив блок питания от платы и затем его снова подключив
Отлично!
Теперь попробуем поиграться с другими типами данных.
Закомментируем теперь также и код, в котором происходит считывание данных и добавим код для записи нескольких двухбайтовых слов (ну конечно же столько, сколько мы можем потом считать и уместить на нашем экране дисплея)
*/
//Words
for(i=0;i<20;i++)
{
EEPROM_WriteWord(i*2,0x30+i);
}
while(1)
Здесь мы используем соответствующую функцию и пишем по адресам, перепрыгивая через один, так как адресация побайтовая, а мы пишем сразу по 2 байта.
Добавим также код для считывания и отображения на дисплее двухбайтовых величин из памяти EEPROM
EEPROM_WriteWord(i*2,0x30+i);
}
for(j=0;j<4;j++)
{
for(i=0;i<5;i++)
{
dtt=EEPROM_ReadWord(j*10+(i*2));
LCD_SetPos(i*4,j);
sprintf(str1,"%04X",dtt);
LCD_String(str1);
}
}
На дисплее мы соответственно пишем уже в каждый четвёртый адрес, так как для отображения каждого двухбайтового слова нам требуется уже по 4 символа.
Соберём код, прошьём наш контроллер и проверим результат
Всё отлично работает.
Также, как и в случае с байтами, закомментируем код записи в память двухбайтовых слов, соберём код и прошьём контроллер.
Если у нас всё нормально сохранилось, то двигаемся дальше.
Закомментируем код считывания данных.
Теперь четырёх байтовые (32) битные данные.
Аналогично напишем сначала функцию записи данных
*/
//DWords
for(i=0;i<8;i++)
{
EEPROM_WriteDword(i*8,0x60+i);
}
while(1)
Теперь прочитаем и отобразим наши данные
EEPROM_WriteDword(i*8,0x60+i);
}
for(j=0;j<4;j++)
{
for(i=0;i<2;i++)
{
dtt=EEPROM_ReadWord(j*16+(i*8));
LCD_SetPos(i*10,j);
sprintf(str1,"%08X",dtt);
LCD_String(str1);
}
}
Соберём код, прошьём контроллер и посмотрим результат на нашем дисплее
Аналогично, как и с другими типами данных, проверим то, что данные наши сохранились.
Затем закомментируем весь код работы с двойными словами и попробуем теперь поработать со строками.
//Strings
strcpy(str1,"Hello World!!!");
EEPROM_WriteString(0x10,str1);
strcpy(str1,"EEPROM Data");
EEPROM_WriteString(0x30,str1);
strcpy(str1,"PIC16F877A");
EEPROM_WriteString(0x50,str1);
strcpy(str1,"MPLAB X");
EEPROM_WriteString(0x70,str1);
Теперь считаем все наши строки и отобразим их в желаемых местах нашего дисплея
EEPROM_WriteString(0x70,str1);
EEPROM_ReadString(0x10,str1,14);
LCD_SetPos(3,0);
LCD_String(str1);
EEPROM_ReadString(0x30,str1,11);
LCD_SetPos(4,1);
LCD_String(str1);
EEPROM_ReadString(0x50,str1,10);
LCD_SetPos(5,2);
LCD_String(str1);
EEPROM_ReadString(0x70,str1,7);
LCD_SetPos(6,3);
LCD_String(str1);
Соберём код, прошьём контроллер и посмотрим результат
Таким образом, мы с вами теперь умеем работать с памятью EEPROM нашего контроллера. Мы можем в данную память записывать и считывать данные различных типов.
Всем спасибо за внимание!
Предыдущая часть Программирование МК PIC Следующий урок
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Дисплей LCD 20×4 можно приобрести тут: Дисплей LCD 20×4
Смотреть ВИДЕОУРОК (нажмите на картинку)
нашел ошибки:
1. в EEPROM_WriteDword(i*8 — зачем 8, когда длина 4?
2. в sprintf(str1,»%08X»,dtt) — правильно %08lX, см. MPLAB® XC8 C Compiler
User’s Guide стр. 351, литера l — для вывода long integer, у вас данные 0х00000060 и вы не видите ошибку. вот если бы данными были 0x64636261, ошибка была бы видна.
3. лучше:
void EEPROM_WriteString(unsigned char addr, char* str1)
{
unsigned char n;
for(n=0; str1[n]!='\0'; n++)
EEPROM_WriteByte(addr+n,str1[n]);
EEPROM_WriteByte(addr+n,'\0');
}
void EEPROM_ReadString(unsigned char addr, char* str1)
{
unsigned char i=0;
while (str1[i] = EEPROM_ReadByte(addr+i))
i++;
}
спасибо за уроки, продолжаю изучение дальше.
смотрел дизассемблер процедур, где вы умножаете на 256 или 65536, думал, компилятор будет умножение делать, оказалось, что делает перестановку, компилятор хорошо сделан.
комментарий можно убрать после исправлений.
Здравствуйте!
Начинаю изучать программирование PIC и СИ
Иногда не понятны некоторые конструкции строк.
Подскажите зачем же умножаем на 256 и на 65536
Таким образом мы сдвигаем байт. Есть, конечно же, более правильные и оптимальные операции битовых сдвигов, но я подумал, что путём умножения будет, наоборот, более понятно и просто.