реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Хранение integer во внутреннем EEPROM
BelTech
сообщение Feb 22 2007, 21:51
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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, не знаю.
Или может есть решение по проще?
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 22 2007, 22:00
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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;
Go to the top of the page
 
+Quote Post
BelTech
сообщение Feb 22 2007, 22:21
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
smk
сообщение Feb 22 2007, 22:40
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



В CVAVR можно объявить так переменную (а я так делал и проблем не знал):

eeprom unsigned int curr_pos;

и работать с ней как с любой другой. Единственное, что перед запичсью в eeprom выключайте прерывания. Иначе некорректно запишется.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
WHALE
сообщение Feb 22 2007, 22:46
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



Дык и обьявите ее
eeprom unsigned int curr_pos;
а дальше смотря что вам надо-если получить форматированное значение для вывода,то можно так
sprintf(lcd_buffer,"%5u",curr_pos);


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
Leen
сообщение Feb 23 2007, 03:48
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 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];
Go to the top of the page
 
+Quote Post
BelTech
сообщение Feb 23 2007, 10:43
Сообщение #7


Участник
*

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



WHALE и smk
Про такое объявление переменной я знаю,но это мне не подходит , так как curr_pos в программе постоянно меняется и если она всё время будет переписываться в EEPROMе, то его ресурс исчерпается очень быстро.

Leen
Попробовал ваш вариант, всё получилось.
Всем спасибо.
Go to the top of the page
 
+Quote Post
smk
сообщение Feb 23 2007, 10:50
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата
curr_pos в программе постоянно меняется и если она всё время будет переписываться в EEPROMе, то его ресурс исчерпается очень быстро.


Заведите промежуточную для работы, а в curr_pos храните. Надеюсь Вы не думаете, что я поступаю как Вы сказали...

Хотелось бы сравнить размер программы при использовании Вашего и моего вариантов. Из любопытства.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 23 2007, 13:40
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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]
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 23 2007, 13:59
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 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)); // загрузка
Go to the top of the page
 
+Quote Post
Alex11
сообщение Feb 23 2007, 15:18
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 106
Регистрация: 23-10-04
Из: С-Петербург
Пользователь №: 965



Для IAR выражение curr_pos = curr_pos_lsb + curr_pos_msb<<8; тоже не корректно. Так можно делать, но следует написать curr_pos = curr_pos_lsb + (unsigned int)curr_pos_msb<<8; и после этого все хорошо.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 23 2007, 22:28
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(Alex11 @ Feb 23 2007, 16:18) *
Для IAR выражение curr_pos = curr_pos_lsb + curr_pos_msb<<8; тоже не корректно. Так можно делать, но следует написать curr_pos = curr_pos_lsb + (unsigned int)curr_pos_msb<<8; и после этого все хорошо.


Почитайте ещё раз мой последний пост - там вы найдёте слово в слово то что написали вы + в примере убедитесь (если понимаете ассемблер), что IAR коректно обрабатывает строчку и без приведения типов.
Go to the top of the page
 
+Quote Post
Alex11
сообщение Feb 24 2007, 02:26
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 106
Регистрация: 23-10-04
Из: С-Петербург
Пользователь №: 965



Sorry, не доглядел. А то, что он догадывается за программиста что требуется, это, скорее, баг компилятора, чем фича.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 24 2007, 11:31
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 24 2007, 20:45
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(Сергей Борщ @ Feb 24 2007, 12:31) *
Цитата(Alex11 @ Feb 24 2007, 01:26) *

А то, что он догадывается за программиста что требуется, это, скорее, баг компилятора, чем фича.
Он не догадывается. Он скорее следует стандарту, где сказано что-то вроде такого: типы, меньшие int на время арифметических операций приводятся к int. Хотя зачем это придумали - для меня загадка.


smile.gif

Не знаю зачем. Возможно для меня. smile.gif Практически всё написанное в последнем проекте не требывало уточнений. Лишь в одном месте где по операции с несколькими указателями надо было получить данные расположенные во флэш - пришлось явно указывать.

Вообще, в этом смысле Си мне очень понравился. Практически никаких ограничений. А я уже вполне взрослый чтобы понимать что пишу. smile.gif

Например в паскале не пролез бы оператор
i = c + '0'; или i = c-'A';
а он очень нагляден и смысл его очевиден.
То же и с указателями. Так например я ввожу данные побайтно, а потом интерпретирую их как структуры. Конечно в паскале есть нетипизированные указатели, но работать с ними сложнее.
Ну и т.д. и т.п.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th June 2025 - 23:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.06852 секунд с 7
ELECTRONIX ©2004-2016