|
Хранение integer во внутреннем EEPROM |
|
|
|
Feb 22 2007, 21:51
|
Участник

Группа: Участник
Сообщений: 26
Регистрация: 8-12-06
Пользователь №: 23 269

|
Проблема в следующем. Есть переменная типа integer .Например unsigned int current_position=50000. По ходу программы она меняется и при выключении устройства надо сохранить эту переменную во внутреннем EEPROM. Но так как ячейки байтовые , то как я понимаю эту переменную надо разделить на 2 по 8 бит и записать по двум адресам.
С этим вот проблем вроде нет.Делаю так:
#define LOW(int) (unsigned char)(*((char*)&(int)+0)) //returns lowbyte #define HIGH(int) (unsigned char)(*((char*)&(int)+1)) //returns highbyte
unsigned int current_position=50000; unsigned char current_position_msb; //highbyte unsigned char current_position_lsb; //lowbyte
current_position_msb=HIGH(current_position); // возвращает 195 current_position_lsb=LOW(currentr_position); // возвращает 80 И эти значения пишу в EEPROM.
При включении надо восстановить эту переменную. Читаю current_position_msb и current_position_lsb,но как соеденить их в Integer,чтобы получилось current_position=50000, не знаю. Или может есть решение по проще?
|
|
|
|
|
Feb 22 2007, 22:00
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(BelTech @ Feb 22 2007, 22:51)  Проблема в следующем. Есть переменная типа integer .Например unsigned int current_position=50000. По ходу программы она меняется и при выключении устройства надо сохранить эту переменную во внутреннем EEPROM. Но так как ячейки байтовые , то как я понимаю эту переменную надо разделить на 2 по 8 бит и записать по двум адресам.
С этим вот проблем вроде нет.Делаю так:
#define LOW(int) (unsigned char)(*((char*)&(int)+0)) //returns lowbyte #define HIGH(int) (unsigned char)(*((char*)&(int)+1)) //returns highbyte
unsigned int current_position=50000; unsigned char current_position_msb; //highbyte unsigned char current_position_lsb; //lowbyte
current_position_msb=HIGH(current_position); // возвращает 195 current_position_lsb=LOW(currentr_position); // возвращает 80 И эти значения пишу в EEPROM.
При включении надо восстановить эту переменную. Читаю current_position_msb и current_position_lsb,но как соеденить их в Integer,чтобы получилось current_position=50000, не знаю. Или может есть решение по проще? В IARе к примеру это всё - лишнее. достаточно переменную объявить так, к примеру, и работать. int16_t __eeprom eMinX = CLASTER_X*LENGTH_X; если так как вы делаете, то достаточно сделать так current_position = current_position_lsb + current_position_msb<<8;
|
|
|
|
|
Feb 22 2007, 22:21
|
Участник

Группа: Участник
Сообщений: 26
Регистрация: 8-12-06
Пользователь №: 23 269

|
Я работаю в Codevision и попробовав: unsigned int curr_pos; unsigned char curr_pos_msb=195; unsigned char curr_pos_lsb=80; curr_pos = curr_pos_lsb + curr_pos_msb<<8;
...получил curr_pos = 0. Для вывода результата использую следующее sprintf(lcd_buffer,"%i",curr_pos); wrs(lcd_buffer,color); // вывести на жки lcd_buffer
|
|
|
|
|
Feb 23 2007, 03:48
|
Частый гость
 
Группа: Свой
Сообщений: 172
Регистрация: 5-08-06
Из: Владивосток
Пользователь №: 19 343

|
Довольно некорректно, промежду прочим. Цитата unsigned char curr_pos_msb=195; unsigned char curr_pos_lsb=80; curr_pos = curr_pos_lsb + curr_pos_msb<<8; Потому чта операции будут выполнены в таком порядке: сдвиг char'овой curr_pos_msb на 8 бит влево (при этом она ессно обнулится); суммирование curr_pos_lsb и предыд. строки; копирование в curr_pos; Лучше, IMHO, сделать так: Код unsigned char c_curr_pos[2]; unsigned int curr_pos; // прямое копирование - из int в char memcpy(c_curr_pos, &curr_pos, 2); // обратное копирование - из char в int memcpy(&curr_pos, c_curr_pos, 2); Указатель с char не беру, ибо он объявлен как массив, что есть тот же указатель. Если это будут 2 объявленные последовательно переменные, тогда первую разадресуйте. Или ручками: Код // прямое c_curr_pos[0] = (curr_pos>>8)&0xFF;// msb c_curr_pos[1] = curr_pos&0xFF;// lsb // обратное curr_pos = c_curr_pos[0]; curr_pos <<= 8;// здесь мы двигаем число в inte, поэтому значение не умрет, как в chare curr_pos |= c_curr_pos[1];
|
|
|
|
|
Feb 23 2007, 10:43
|
Участник

Группа: Участник
Сообщений: 26
Регистрация: 8-12-06
Пользователь №: 23 269

|
WHALE и smk Про такое объявление переменной я знаю,но это мне не подходит , так как curr_pos в программе постоянно меняется и если она всё время будет переписываться в EEPROMе, то его ресурс исчерпается очень быстро.
Leen Попробовал ваш вариант, всё получилось. Всем спасибо.
|
|
|
|
|
Feb 23 2007, 10:50
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Цитата curr_pos в программе постоянно меняется и если она всё время будет переписываться в EEPROMе, то его ресурс исчерпается очень быстро. Заведите промежуточную для работы, а в curr_pos храните. Надеюсь Вы не думаете, что я поступаю как Вы сказали... Хотелось бы сравнить размер программы при использовании Вашего и моего вариантов. Из любопытства.
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Feb 23 2007, 13:40
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Leen @ Feb 23 2007, 04:48)  Довольно некорректно, промежду прочим. Цитата unsigned char curr_pos_msb=195; unsigned char curr_pos_lsb=80; curr_pos = curr_pos_lsb + curr_pos_msb<<8; Потому чта операции будут выполнены в таком порядке: сдвиг char'овой curr_pos_msb на 8 бит влево (при этом она ессно обнулится); суммирование curr_pos_lsb и предыд. строки; копирование в curr_pos; В каком бы порядке не была бы выполнена данная операция - на IAR результат был бы правильным. Более того никаких сдвигов тут вообще бы не наблюдалось а было бы две операции присваивания. Таким образом некорректность только компилятора Си от CV. Возможно можно вылечить таким образом curr_pos = curr_pos_lsb + (unsigned int)curr_pos_msb<<8; Для примера приведу свой код Код [font=Times New Roman] 333 LenPack485 = c; // ╧юьхёЄшЄ№ ьы. срщЄ \ ??rxint_2: \ 000000C0 8302 STD Z+2, R16 \ 000000C2 8353 STD Z+3, R21 334 Stat485++; // ╤ыхфє■∙шщ ¤Єря \ ??rxint_9: \ 000000C4 8106 LDD R16, Z+6 \ 000000C6 9503 INC R16 \ ??rxint_10: \ 000000C8 8306 STD Z+6, R16 \ 000000CA C4A8 RJMP ??rxint_8 335 break; 336 case 2: // ╫Єхэшх фышэ√ фрээ√ї 337 LenPack485 += c<<8; // ╧юьхёЄшЄ№ ёЄ. срщЄ \ ??rxint_3: \ 000000CC 8113 LDD R17, Z+3 \ 000000CE 0F10 ADD R17, R16 \ 000000D0 8313 STD Z+3, R17 338 Stat485++; // ╤ыхфє■∙шщ ¤Єря \ 000000D2 8106 LDD R16, Z+6 \ 000000D4 9503 INC R16 \ 000000D6 8306 STD Z+6, R16 [/font][font=System]
|
|
|
|
|
Feb 23 2007, 13:59
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Один из вариантов: Код typedef unsigned char U8;
union tagDummyUnion { int i; U8 b0; U8 b1; } DummyUnion;
DummyUnion MyVar;
MyVar.b0 = 80; MyVar.b1 = 195; printf("int value = %d\n", MyVar.i); Еще один вариант. Пишем функции сохранения и восстановления массива в/из eeprom. Код StroreToEeprom(U8 eeAddr, U8 *pData, U8 size) { while( size-- ) __eeprom_store_byte( eeAddr++, *pData++); // <- подставить то что вам предоставляет CV }
LoadFromEeprom(U8 eeAddr, U8 *pData, U8 size) { while( size--) __eeprom_load_byte( eeAddr++, *pData++); } Далее пользовать это дело так: Код int MyVar;
StoreToEeprom( <ваш адрес>, (U8 *)&MyVar, sizeof(MyVar)); // сохранение LoadFromEeprom( <ваш адрес>, (U8 *)&MyVar, sizeof(MyVar)); // загрузка
|
|
|
|
|
Feb 24 2007, 11:31
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Alex11 @ Feb 24 2007, 01:26)  А то, что он догадывается за программиста что требуется, это, скорее, баг компилятора, чем фича. Он не догадывается. Он скорее следует стандарту, где сказано что-то вроде такого: типы, меньшие int на время арифметических операций приводятся к int. Хотя зачем это придумали - для меня загадка.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 24 2007, 20:45
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Сергей Борщ @ Feb 24 2007, 12:31)  Цитата(Alex11 @ Feb 24 2007, 01:26)  А то, что он догадывается за программиста что требуется, это, скорее, баг компилятора, чем фича.
Он не догадывается. Он скорее следует стандарту, где сказано что-то вроде такого: типы, меньшие int на время арифметических операций приводятся к int. Хотя зачем это придумали - для меня загадка. Не знаю зачем. Возможно для меня.  Практически всё написанное в последнем проекте не требывало уточнений. Лишь в одном месте где по операции с несколькими указателями надо было получить данные расположенные во флэш - пришлось явно указывать. Вообще, в этом смысле Си мне очень понравился. Практически никаких ограничений. А я уже вполне взрослый чтобы понимать что пишу. Например в паскале не пролез бы оператор i = c + '0'; или i = c-'A'; а он очень нагляден и смысл его очевиден. То же и с указателями. Так например я ввожу данные побайтно, а потом интерпретирую их как структуры. Конечно в паскале есть нетипизированные указатели, но работать с ними сложнее. Ну и т.д. и т.п.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|