Перейти к содержанию
    

Как записать long int во флэш?

Первый вариант - разложить на байты и воспользоваться своим простым алгоритмом записи:

 

unsigned char t1, t2, t3, t4;

unsigned long int F, Freq = 103500;

t1= (Freq);

t2= (Freq>>8);

t3= (Freq>>16);

t4= (Freq>>24);

 

F = (t4<<24)|(t3<<16)|(t2<<8)|t1;

 

t1 = sizeof(F);

printf("\n%li",F);

 

С успехом работает на компьютерном компиляторе С-Free(он 32-х разрядный), но нихрена не работает в AvrStudio, выдавая ошибку в строке F = (t4<<24)|(t3<<16)|(t2<<8)|t1;: ../main.c:84: warning: left shift count >= width of type. Подозреваю что это из - за разрядности.

 

Второй вариант - воспользоваться стандартными средствами:

void eeprom_write_dword ( uint32_t *addr , uint32_t value )

Но я не пойму что такое uint32_t *addr. По идее это должен быть адрес флэш, куда я пишу эти 4 байта. Тогда почему он 4-разрядный?

 

Третий вариант - найти в памяти адрес это переменной и побайтово записать во флэш. Но я не знаю как это сделать. Помогите советом.

 

Сделал так:

char K;

K = eeprom_read_byte ((uint8_t*) 0xff0);

eeprom_write_dword ((uint32_t*)&K,Freq);

K=K+4;

eeprom_write_byte ((uint8_t*)0xff0,K);

 

Пока не работает. Разбираюсь.

Изменено пользователем Димон Безпарольный

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первый вариант - разложить на байты и воспользоваться своим простым алгоритмом записи:

 

 

 

С успехом работает на компьютерном компиляторе С-Free(он 32-х разрядный), но нихрена не работает в AvrStudio, выдавая ошибку в строке F = (t4<<24)|(t3<<16)|(t2<<8)|t1;: ../main.c:84: warning: left shift count >= width of type. Подозреваю что это из - за разрядности.

 

Второй вариант - воспользоваться стандартными средствами:

 

Но я не пойму что такое uint32_t *addr. По идее это должен быть адрес флэш, куда я пишу эти 4 байта. Тогда почему он 4-разрядный?

 

Третий вариант - найти в памяти адрес это переменной и побайтово записать во флэш. Но я не знаю как это сделать. Помогите советом.

 

Сделал так:

 

 

Пока не работает. Разбираюсь.

Нужно тип приводить:

F = ((uint32_t)t4<<24)|((uint32_t)t3<<16)|((uint32_t)t2<<8)|(uint32_t)t1;

В противном случае сдвиг не имеет смысла.

При помощи eeprom_write_dword ( uint32_t *addr , uint32_t value ) вы пишите 32 разрядное значение, соответственно адрес по которому это значение пишется должен быть указателем на 32битную величину.

Для записи unsigned long нужно использовать eeprom_write_dword:

#define K_EEPROM_ADDRESS 0x00
uint32_t K;
// запись
eeprom_write_dword((uint32_t*)K_EEPROM_ADDRESS,K);
// чтение
K=eeprom_read_dword((uint32_t*)K_EEPROM_ADDRESS);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно тип приводить:

F = ((uint32_t)t4<<24)|((uint32_t)t3<<16)|((uint32_t)t2<<8)|(uint32_t)t1;

В противном случае сдвиг не имеет смысла.

Исчерпывающе. Спасибо. Первый вариант работает.

 

При помощи eeprom_write_dword ( uint32_t *addr , uint32_t value ) вы пишите 32 разрядное значение, соответственно адрес по которому это значение пишется должен быть указателем на 32битную величину.

Для записи unsigned long нужно использовать eeprom_write_dword:

#define K_EEPROM_ADDRESS 0x00
uint32_t K;
// запись
eeprom_write_dword((uint32_t*)K_EEPROM_ADDRESS,K);
// чтение
K=eeprom_read_dword((uint32_t*)K_EEPROM_ADDRESS);

Мне необходимо иметь во флэш - памяти не только массив uint32_t значений, но и индекс(количество значений). По нему я вычисляю адрес первой свободной ячейки: K=K+4; Значение это байтовое и пишется во флэш по адресу 0xff0. Вот тут я и запутался. Функция записи требует в качестве адреса указатель на uint32_t. А у меня K объявлена как char. И похоже что в (uint32_t*)&K я где - то ошибся. Не работает.

Изменено пользователем Димон Безпарольный

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне необходимо иметь во флэш - памяти
Для начала вам нужно понять, что ЭСПЗУ (eeprom) и флеш - две совершенно разные вещи. функциями eeprom_write_xxxx() вы пишете в ЭСПЗУ.

Функция записи требует в качестве адреса указатель на uint32_t. А у меня K объявлена как char
Тогда зачем вы для байта используете функцию eeprom_write_dword()? Почитайте документацию чуть дальше и возьмите для этого байта функцию, предназначенную для записи байта.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для начала вам нужно понять, что ЭСПЗУ (eeprom) и флеш - две совершенно разные вещи. функциями eeprom_write_xxxx() вы пишете в ЭСПЗУ.

Тогда зачем вы для байта используете функцию eeprom_write_dword()? Почитайте документацию чуть дальше и возьмите для этого байта функцию, предназначенную для записи байта.

Я знаю что такое EEPROM и какого она размера. Вы не поняли. Я пишу dword массив частот. А вот их количество умещается в байт. Он тоже должен хранится в EEPROM. Этот же байт служит для вычисления адреса первой свободной ячейки, т.е. куда будет писаться следующее значение dword. Получается что для записи в качестве адреса должно использоваться значение типа char, а функция требует указатель на uint32_t. Я запутался в приведении.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот их количество умещается в байт. Он тоже должен хранится в EEPROM.

есть функция записи байта eeprom_write_byte

 

#define INDEX_EEPROM_ADDRESS 0xFF0

uint8_t index;

// запись
eeprom_write_byte((uint8_t*) INDEX_EEPROM_ADDRESS, index);
// чтение
index=eeprom_read_byte((uint8_t*) INDEX_EEPROM_ADDRESS);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

есть функция записи байта eeprom_write_byte

 

#define INDEX_EEPROM_ADDRESS 0xFF0

uint8_t index;

// запись
eeprom_write_byte((uint8_t*) INDEX_EEPROM_ADDRESS, index);
// чтение
index=eeprom_read_byte((uint8_t*) INDEX_EEPROM_ADDRESS);

Я в курсе. И она работает исправно. Но, прочитав этот байт индекса я должен его подставить в функцию чтения / записи dword. Вот тут и начинаются проблемы, поскольку эта функция требует в качестве адреса указатель на uint32_t. Я делал так: P = eeprom_read_dword ((uint32_t *)&J); Но это не работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я в курсе. И она работает исправно. Но, прочитав этот байт индекса я должен его подставить в функцию чтения / записи dword. Вот тут и начинаются проблемы, поскольку эта функция требует в качестве адреса указатель на uint32_t. Я делал так: P = eeprom_read_dword ((uint32_t *)&J); Но это не работает.

Непонятно, что вы пытаетесь сделать. Небольшой пример

#define FREQ_START_ADDR 0x000
#define FREQ_CNT_ADDR 0xFF0
#define FREQ_CNT_MAX       16

uint8_t cnt;
uint32_t freq[16];

// чтение таблицы частот
cnt=eeprom_read_byte((uint8_t*) INDEX_FREQ_ADDR); // число частот в таблице

{
  uint8_t i;
  uint32_t* ptr=(uint32_t*)FREQ_START_ADDR;
  for(i=0;i<cnt;i++;){
    freq[i]=eeprom_read_dword(ptr++);  
  }
}

// добавление частоты
freq[cnt]=100500;
eeprom_write_dword((uint32_t*)(FREQ_START_ADDR+sizeof(uint32_t)*cnt), freq[cnt]); 
cnt++;
eeprom_write_byte((uint8_t*)  FREQ_CNT_ADDR, cnt); // обновить число частот в таблице

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заработало! Вот решил немного прибраться - получил по полной. Написал код:

 

//Чтение числа частот в памяти
char NumBytesRe (void) {uint8_t cnt=eeprom_read_byte((uint8_t*)0xFE0); return cnt;}

//Запись числа частот в память
void NumBytesWR (uint8_t cnt) {eeprom_write_byte((uint8_t*)0xFE0,cnt);}


//Чтение текущего выводимого канала памяти
uint8_t CurrMemChR (void) {uint8_t MEM = eeprom_read_byte((uint8_t*)0xFB0); return MEM;}
//Запись текущего выводимого канала в память
void CurrMemChWR (uint8_t MEM) {eeprom_write_byte((uint8_t*)0xFB0,MEM);}


//Чтение текущей выводимой частоты из памяти
uint32_t CurrFreqR (void) {uint32_t Fr=eeprom_read_dword ((const uint32_t *) 0xFA0); return Fr;}
//Запись текущей выводимой частоты в память
void CurrFreqWR (uint32_t Fr) {eeprom_write_dword((uint32_t*)0xFA0,Fr);}


//Чтение частоты из памяти
uint32_t FreqR (uint32_t* ADR) {uint32_t Fr=eeprom_read_dword (ADR); return Fr;}
//Запись частоты в память
void FreqWR (uint32_t* ADR, uint32_t Fr) {eeprom_write_dword(ADR,Fr);}


//Очистка индексов памяти
void MEMWipe (void) {
eeprom_write_byte((uint8_t*)0xFE0,(uint8_t)0);    //Число станций в базе
eeprom_write_byte((uint8_t*)0xFB0,(uint8_t)0);}    //Текущий выводимый канал памяти

 

Получил сообщение: cc1plus.exe: warning: command line option "-std=gnu99" is valid for C/ObjC but not for C++

Попытка использовать первую же функцию: NumBytesRe привела к ошибки: D:\8051\AVR\Projects\PriemXA6\default/../main.c:75: undefined reference to `NumBytesRe', хотя она выше места использования объявлена:

extern uint8_t NumBytesRe (void);//Чтение числа частот в памяти

Придется пока оставить как есть.

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут и начинаются проблемы, поскольку эта функция требует в качестве адреса указатель на uint32_t.
Проблемы от того, что вы не разобрались - что такое указатель и как он работает.

 

#include    <avr/eeprom.h>

typedef struct
{
    uint8_t Index;
    uint32_t Frequency[];
} table_t;


table_t EEMEM Table;

void write_next(uint32_t frequency)
{
    uint8_t Index = eeprom_read_byte(&Table.Index);
    ++Index;
    eeprom_write_dword(&Table.Frequency[Index], frequency);
    eeprom_write_byte(&Table.Index, Index);
}

uint32_t read_last()
{
    uint8_t Index = eeprom_read_byte(&Table.Index);
    return eeprom_read_dword(&Table.Frequency[Index]);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получил сообщение: cc1plus.exe: warning: command line option "-std=gnu99" is valid for C/ObjC but not for C++
Это значит, что вы зачем то свой С исходник скормили С++ компилятору

Попытка использовать первую же функцию: NumBytesRe привела к ошибки: D:\8051\AVR\Projects\PriemXA6\default/../main.c:75: undefined reference to `NumBytesRe', хотя она выше места использования объявлена:

extern uint8_t NumBytesRe (void);//Чтение числа частот в памяти

А это последствие того же - собирайте весь проект либо как С либо как С++, но не как помесь того и другого.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это значит, что вы зачем то свой С исходник скормили С++ компилятору

А это последствие того же - собирайте весь проект либо как С либо как С++, но не как помесь того и другого.

Я работаю в AvrStudio. В настройках упоминания о С++ не нашел. Впрочем, это уже не актуально. Базу я уже построил и она исправно работает.

 

Спасибо PSL и всем ответившим. Удачи в новом году.

Изменено пользователем Димон Безпарольный

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...