Урок 15
Часть 2
Внутренняя энергонезависимая память EEPROM
В прошлой части занятия мы написали две функции для работы с памятью EEPROM, практически взяв их из технической документации на контроллер. Это функция для записи данных в EEPROM, а другая — для чтения их оттуда. Одной функцией — функцией записи мы уже воспользовались.
В данной части урока мы попробуем программно прочитать данные из памяти EEPROM.
Но тут как всегда подкрадывается вопрос. Как же мы увидим эти данные? У нас же не поддерживается отладка. Ну, давайте воспользуемся интерфейсом USART и будем просматривать эти величины с помощью терминальной программы. А заодно и прошлый урок 14 закрепим.
Создадим другой проект, назовем его Test14 и перенесём в него всё полностью с Teat13, а также подключим файлы для работы с usart в дерево проекта. Также не забываем подключить библиотеку и в main.h
#include «eeprom.h»
#include «usart.h»
После написания вызова функции инициализации USART в main() файл main.c у нас будет таким
#include «main.h»
int main(void)
{
USART_Init (8);
while(1)
{
}
}
Отладочная плата у нас та же самая, только, конечно, подключим переходник USART, чтобы данным интерфейсом пользоваться
Ну, а теперь давайте попробуем считать данные из памяти EEPROM используя функцию чтения, которую мы написали в предыдущей части занятия. Так как мы писали данные по адресу 1, то его мы и попробуем прочитать. Для хранения результата создадим переменную в main.c
#include «main.h»
unsigned char dt;
Прежде, чем использовать функцию чтения, воткнём ассемблерную вставку с пустой операцией, чтобы USART смог инициализироваться, а затем уже прочитаем данные и отправим их в USART
USART_Init (8);
asm(«nop»);
dtt = EEPROM_read_word(1);
USART_Transmit(dt);
Соберем код, запустим терминальную программу, нажмем Connect и прошьём контроллер. Мы видим, что число 120 у нас передалось, то есть всё у нас считалось нормально.
Так как не всегда удобно оперировать малыми величинами, давайте ещё напишем функции чтении и записи чисел побольше — двухбайтных величин или слов. Давайте для удобства программирования также запустим ещё проект Test13 из прошлой части занятия. В нём мы будем различные данные писать в память EEPROM, а. соответственно, в проекте Test14 мы будем оттуда эти данные читать.
Зайдём в проекте Teat13 в файл eeprom.c и создадим там функцию в самом низу файла
void EEPROM_write_word(unsigned int uiAddress, uint16_t ucData)
{
}
Данная функция отличается от функции записи однобайтного числа только вторым входным аргументом — здесь будет величина целочисленная 16-байтная. И теперь, используя битовый сдвиг и функцию записи однобайтного числа, напишем код записи в память EEPROM двухбайтного числа в тело нашей новой функции. Сначала мы запишем по нужному адресу младшую часть, используя преобразование типа в однобайтную величину, тем самым отсекая старшую часть, а затем уже сдвиг и запись старшей части в следующий адрес
void EEPROM_write_word(unsigned int uiAddress, uint16_t ucData)
{
EEPROM_write(uiAddress, (unsigned char) ucData);
unsigned char dt = ucData>>8;
EEPROM_write(uiAddress+1, dt);
}
Также не забываем про прототип функции в файле eeprom.h
unsigned char EEPROM_read(unsigned int uiAddress);
void EEPROM_write_word(unsigned int uiAddress, uint16_t ucData); //пишем 2х-байтную величину
Давайте заодно сразу напишем и функцию чтения 2х-байтного числа
uint16_t EEPROM_read_word(unsigned int uiAddress)
{
uint16_t dt = EEPROM_read(uiAddress+1)*256;
asm(«nop»);
dt += EEPROM_read(uiAddress);
return dt;
}
Здесь вроде также всё понятно. Мы сначала считываем старшую часть, применяя умножение на 256, это в принципе то же самое, как если бы мы сдвинули число на 8 пунктов, и записываем его в адрес, на 1 больший, затем в соответствии с таймингами ждём 1 цикл, этого вполне хватает, как показала практика. Ну, и затем мы прибавляем к умноженной на 256 старшей части значение младшей части, считанной из обычного адреса (не увеличенного на 1) и тем самым мы получаем двухбайтовый результат из памяти EEPROM.
Ну, и также напишем прототип на функцию чтения
uint16_t EEPROM_read_word(unsigned int uiAddress) //читаем 2х-байтную величину
Теперь давайте запишем в память EEPROM какое-нибудь двухбайтное число, используя данную функцию в функции main() в файле Test13.c
int main(void)
{
EEPROM_write_word(1, 30000);
Функцию записи однобайтного числа мы пока удалим. Мы будем писать по тому же адресу 1.
Соберём проект, прошьём контроллер, не забыв выбрать заново Test13 в avrdude, затем запишем память EEPROM в файл и посмотрим его
Мы видим с вами в файле нужное число 0x7530, которое в десятичном формате и есть 30000.
То есть, у нас всё нормально в EEPROM записалось.
А читать мы будем уже в слеующей — 3 части урока.
Предыдущая часть Программирование МК AVR Следующая часть
Купить программатор можно здесь (продавец надёжный) USBASP USBISP 2.0
Смотреть ВИДЕОУРОК (нажмите на картинку)
Здравствуйте,
В eeprom 3075
А в последнем абзаце 0x7530, которое в десятичном формате и есть 30000.
На моем калькуляторе 3075=12405.
Где взяли 0x7530 ?
Спасибо за уроки
Спасибо и Вам за интерес к ресурсу!
Переверните число. Числа если правильно то хранятся сначала младшие биты, а потом более старшие.
Здравствуйте,
зачем двигать влево и вправо двухбайтовую величину, почему её нельзя просто записать как есть в двухбайтном виде?
Хоть бы проверили статью на орфографические ошибки, не первый раз натыкаюсь на них.
На самом деле я тоже не понял с представлением чисел в памяти. Что посоветуете почитать чтобы понять почему сначала младшие биты, а потом более старшие. Потому что например мне было бы удобно читать как есть число с лева на права в памяти а не на оборот.