Урок 15
Часть 3
Внутренняя энергонезависимая память EEPROM
Продолжаем работать с внутренней памятью микроконтроллера Atmega8a — EEPROM.
В части 1 и части 2 урока мы познакомились с организацией данной энергонезависимой памяти, а также записали и считали туда данные в виде однобайтной величины, а также записали двухбайтную величину.
Теперь перед нами стоит задача — программно данную 2-х-байтную величину считать, а также записать функции чтения и записи 4-байтных величин, а также ещё написать функцию чтения и записи строк.
Давайте попробуем написать функцию записи 4-х-байтных значений в память EEPROM, или двойных слов. Также в памяти все 4 байта мы обязаны хранить в обратном порядке — от младшего к старшему, так как это принято повсеместно. Также, чтобы не писать функцию полностью, мы будем обращаться к функции записи обычных 2-х байтных слов. Слово — вообще понятие абстрактное. В разных случаях оно разное. Может быть и 2х-байтным, а может и 4х. Тогда в этом случае двухбайтное значение называется полусловом. Но это не суть важно, нам нужно сохранить в энергонезависимую память именно 4х-байтное значение. Пока откроем проект Test13 — это тот проект, где мы договорились в память EEPROM именно писать. Но пока мы сюда напишем все функции, а затем перенесём в проект Test14.
Напишем функцию записи 4х-байтных значений в EEPROM в самый низ файла eeprom.c
void EEPROM_write_dword(unsigned int uiAddress, uint32_t ucData)
{
EEPROM_write_word(uiAddress, (uint16_t) ucData);
uint16_t dt = ucData>>16;
EEPROM_write_word(uiAddress+2, dt);
}
Здесь у нас происходит всё практически то же самое, что и в функции записи 2х-байтных величин, только величины двойной размерности. Второй входной параметр у нас будет 32-битный, сдвиг на 16 пунктов и и адрес увеличивается на 2, так как используем мы функцию записи 2х-байтных величин и у нас поэтому запись идёт в каждом вызове уже по 2 адресам.
Также напишем ещё функцию чтения 4х-байтной величины. То же самое пишем по аналогии с прошлой функцией чтения, но используем величины двойной размерности и функцию чтения 2х-байтных значений
uint32_t EEPROM_read_dword(unsigned int uiAddress)
{
uint32_t dt = EEPROM_read_word(uiAddress+2)*65536;
asm(«nop»);
dt += EEPROM_read_word(uiAddress);
return dt;
}
Ну и, раз так всё у нас хорошо наладилось с написанием различных функций, давайте также напишем функции и для строк.
Сначала функцию записи. Будет чуть посложнее, потому что мы ещё будем использовать не только значения но и указатели на данные значения. Но мы этого не боимся, с указателями мы уже работали, когда писали код записи строк в память DDRAM символьного дисплея в части 5 урока 12. Напишем сначала каркас функции записи строки в память EEPROM
void EEPROM_write_string(unsigned int uiAddress, char str1[])
{
}
Данная функция отличается от остальных указателем на строку во втором входном параметре.
Теперь напишем тело функции.
Добавим переменную, а затем в конечном цикле и пробежимся по адресам обычной оперативной памяти до тех пор, пока встретим ноль. Также в этом цикле мы будем встретившиеся значения писать в память EEPROM по адресу, смещённому на число n, которое будет у нас увеличиваться в цикле каждый раз на единицу. Таким образом мы перенесём строку, заканчивающуюся нулём из оперативной памяти в память EEPROM
void EEPROM_write_string(unsigned int uiAddress, char str1[])
{
wchar_t n;
for(n=0;str1[n]!='\0';n++)
EEPROM_write(uiAddress+n,str1[n]);
}
Ну и давайте также напишем функцию чтения строки из памяти EEPROM в оперативную память по адресу, находящемуся в указателе на строковую переменную (или массив символов). Также мы в этот раз не будем отслеживать окончание строки нулём, а то вдруг его там не будет, а будем в качестве второго входного параметра в функцию передавать количество байтов или символов, которое мы собираемся считать из энергонезависимой памяти. Вот каркас функции
const char* EEPROM_read_string(unsigned int uiAddress, unsigned int sz)
{
}
Здесь мы возвращаем не сами символы, а указатель на строку символов в оперативной памяти.
Теперь тело.
Создадим сначала две переменные
const char* EEPROM_read_string(unsigned int uiAddress, unsigned int sz)
{
unsigned int i;
char* str1;
Затем вот такой вот выкрутас
char* str1;
str1 = (char *) realloc(NULL,sz);
Здесь мы выделим область оперативной памяти для такого количества байтов, сктолько символов мы хотим считать из памяти EEPROM. Для этого и существует функция realloc.
Дальше опять цикл. В нём мы считываем из памяти такое же количество байтов и записываем их уже по адресам оперативной памяти, смещённым на порядковый номер байта от адреса указателя, который мы потом и возвратим
str1 = (char *) realloc(NULL,sz);
for (i=0;i<sz;i++)
str1[i] = EEPROM_read(uiAddress+i);
return str1;
}
Создадим прототипы написанных нами новых функций в eeprom.h
uint16_t EEPROM_read_word(unsigned int uiAddress); //читаем 2х-байтную величину
void EEPROM_write_dword(unsigned int uiAddress, uint32_t ucData); //пишем 4х-байтную величину
uint32_t EEPROM_read_dword(unsigned int uiAddress);//читаем 4х-байтную величину
void EEPROM_write_string(unsigned int uiAddress, char str1[]); //пишем строку
const char* EEPROM_read_string(unsigned int uiAddress, unsigned int sz); //читаем строку
Ну и теперь давайте воспользуемся в функции main() всеми возможными функциями записи в EEPROM и запишем туда различные значения по разным адресам
int main(void)
{
EEPROM_write(1, 120);
EEPROM_write_word(3, 30000);
EEPROM_write_dword(7, 0xFEDCBA98);
EEPROM_write_string(16,«Hello World!»);
while(1)
nop попробуем не использовать, должно работать и без него.
Теперь давайте соберём код и прошьём контроллер и затем считаем память EEPROM из контроллера в файл и посмотрим его
Как мы видим, всё у нас записалось. Мы не будем проверять строку по кодам символов, я думаю, там всё нормально. Мы её потом считаем функцией чтения и увидим воочию нашу строку в следующей части.
Предыдущая часть Программирование МК AVR Следующая часть
Приобрести программатор USBASP USBISP с адаптером можно здесь USBASP USBISP 3.3 с адаптером
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добрый день! Чё-то студия выдаёт ошибки на типы переменных wchar_t, uint_16_t, uint32_t. Версия студии последняя.
очепятка: uint16_t.
так тебе кто-нибудь ответил? в чём причина была?
А Вы все библиотеки в main.h подключили как у автора? Проверьте наличие библиотеки stdlib.h
у меня матюкалось потому что не было библиотек #include
#include в EEPROM.H хотя в main.h были подключены