Димон Безпарольный 2 9 января, 2015 Опубликовано 9 января, 2015 (изменено) · Жалоба Первый вариант - разложить на байты и воспользоваться своим простым алгоритмом записи: 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); Пока не работает. Разбираюсь. Изменено 9 января, 2015 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 9 января, 2015 Опубликовано 9 января, 2015 · Жалоба Первый вариант - разложить на байты и воспользоваться своим простым алгоритмом записи: С успехом работает на компьютерном компиляторе С-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); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 9 января, 2015 Опубликовано 9 января, 2015 (изменено) · Жалоба Нужно тип приводить: 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 я где - то ошибся. Не работает. Изменено 9 января, 2015 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 9 января, 2015 Опубликовано 9 января, 2015 · Жалоба Мне необходимо иметь во флэш - памятиДля начала вам нужно понять, что ЭСПЗУ (eeprom) и флеш - две совершенно разные вещи. функциями eeprom_write_xxxx() вы пишете в ЭСПЗУ. Функция записи требует в качестве адреса указатель на uint32_t. А у меня K объявлена как charТогда зачем вы для байта используете функцию eeprom_write_dword()? Почитайте документацию чуть дальше и возьмите для этого байта функцию, предназначенную для записи байта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 9 января, 2015 Опубликовано 9 января, 2015 · Жалоба Для начала вам нужно понять, что ЭСПЗУ (eeprom) и флеш - две совершенно разные вещи. функциями eeprom_write_xxxx() вы пишете в ЭСПЗУ. Тогда зачем вы для байта используете функцию eeprom_write_dword()? Почитайте документацию чуть дальше и возьмите для этого байта функцию, предназначенную для записи байта. Я знаю что такое EEPROM и какого она размера. Вы не поняли. Я пишу dword массив частот. А вот их количество умещается в байт. Он тоже должен хранится в EEPROM. Этот же байт служит для вычисления адреса первой свободной ячейки, т.е. куда будет писаться следующее значение dword. Получается что для записи в качестве адреса должно использоваться значение типа char, а функция требует указатель на uint32_t. Я запутался в приведении. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 9 января, 2015 Опубликовано 9 января, 2015 · Жалоба А вот их количество умещается в байт. Он тоже должен хранится в 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); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 9 января, 2015 Опубликовано 9 января, 2015 · Жалоба есть функция записи байта 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); Но это не работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 9 января, 2015 Опубликовано 9 января, 2015 · Жалоба Я в курсе. И она работает исправно. Но, прочитав этот байт индекса я должен его подставить в функцию чтения / записи 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); // обновить число частот в таблице Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 10 января, 2015 Опубликовано 10 января, 2015 · Жалоба Заработало! Вот решил немного прибраться - получил по полной. Написал код: //Чтение числа частот в памяти 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);//Чтение числа частот в памяти Придется пока оставить как есть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 10 января, 2015 Опубликовано 10 января, 2015 · Жалоба Вот тут и начинаются проблемы, поскольку эта функция требует в качестве адреса указатель на 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]); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 12 января, 2015 Опубликовано 12 января, 2015 · Жалоба Получил сообщение: 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);//Чтение числа частот в памяти А это последствие того же - собирайте весь проект либо как С либо как С++, но не как помесь того и другого. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 12 января, 2015 Опубликовано 12 января, 2015 (изменено) · Жалоба Это значит, что вы зачем то свой С исходник скормили С++ компилятору А это последствие того же - собирайте весь проект либо как С либо как С++, но не как помесь того и другого. Я работаю в AvrStudio. В настройках упоминания о С++ не нашел. Впрочем, это уже не актуально. Базу я уже построил и она исправно работает. Спасибо PSL и всем ответившим. Удачи в новом году. Изменено 12 января, 2015 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться