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

 
 
> Вычисляемая константа в PCW, как?
Eddy71
сообщение Feb 25 2009, 11:21
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 224
Регистрация: 23-11-08
Из: Украина, Луганск
Пользователь №: 41 879



Возникло желание "попросить" компилятор (PCW) при компиляции рассчитать значение константы (на этапе отладки устройства приходится часто подбирать значение). Пытаюсь вставить такое:
Код
const unsigned int16 VoltageMax = 2.5/(4.18/1024);

Ругается. Приходится вручную подставлять 612.
Если не указываю, что это константа, компилятор напихивает библиотек и прошивка "раздувается".
Что я не так делаю?


--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
_Pasha
сообщение Feb 25 2009, 11:27
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Eddy71 @ Feb 25 2009, 15:21) *
Что я не так делаю?


#define VoltageMax  (2.5/(4.18/1024))
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 25 2009, 11:31
Сообщение #3


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Eddy71 @ Feb 25 2009, 14:21) *
Код
const unsigned int16 VoltageMax = 2.5/(4.18/1024);

Ругается.

Логичнее было бы VoltageMax = 1024 * 2.5/4.18
Но, учитывая unsigned int16, окончательный вариант будет
const unsigned int16 VoltageMax = (unsigned int16)(1024 * 2.5/4.18);


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 25 2009, 11:37
Сообщение #4


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(_Pasha @ Feb 25 2009, 15:27) *
#define VoltageMax  (2.5/(4.18/1024))


бр-р


пример

Код
#define VoltageMax  (2.5/(4.18/1024))

// тра-та-та

volatile int16 VV = VoltageMax;
Go to the top of the page
 
+Quote Post
Eddy71
сообщение Feb 25 2009, 11:53
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 224
Регистрация: 23-11-08
Из: Украина, Луганск
Пользователь №: 41 879



Цитата(MrYuran @ Feb 25 2009, 15:31) *
Логичнее было бы VoltageMax = 1024 * 2.5/4.18
Но, учитывая unsigned int16, окончательный вариант будет
const unsigned int16 VoltageMax = (unsigned int16)(1024 * 2.5/4.18);

Остановился на этом варианте. Хоть он и "самый длинный", но с учетом того, что я только осваиваю компилятор, он самый наглядный. Хотя и другие варианты откомпилировались без ругани. Интересно, почему писатели юзер мануала не предположили, что кто-то захочет такое вставить в свою программу..
Спасибо большое всем. smile.gif


--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 25 2009, 11:58
Сообщение #6


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Вообще константа отличается от дефайна тем, что она располагается в памяти (ОЗУ или во флеши) и программа по мере надобности к ней обращается.
Дефайн подставляется по месту на этапе компиляции препроцессором.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Eddy71
сообщение Feb 25 2009, 13:07
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 224
Регистрация: 23-11-08
Из: Украина, Луганск
Пользователь №: 41 879



Цитата(MrYuran @ Feb 25 2009, 14:58) *
Вообще константа отличается от дефайна тем, что она располагается в памяти (ОЗУ или во флеши) и программа по мере надобности к ней обращается.
Дефайн подставляется по месту на этапе компиляции препроцессором.

Сейчас пытался дефайном вставить - ругается, зараза..
Сам дефайн "съедает". А вот потом присвоить переменным не выходит.
ОЗУ тратить не хочется..


--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 25 2009, 13:28
Сообщение #8


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Eddy71 @ Feb 25 2009, 16:07) *
Сейчас пытался дефайном вставить - ругается, зараза..

А ругается-то как?

Error - это ругается.
А Warning - это просто предупреждает, что, мол, имеете право, но возможны проблемы...

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


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Eddy71
сообщение Feb 25 2009, 14:22
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 224
Регистрация: 23-11-08
Из: Украина, Луганск
Пользователь №: 41 879



Цитата(MrYuran @ Feb 25 2009, 16:28) *
А ругается-то как?
Лучше выкладывайте, как ругается и на что, показательней будет


Вротмненоги!... Хотел показать - откомпилировалось без ошибок. Правда аномалия:
Код
const unsigned int16 ChargeMax = (unsigned int16)(1024 * 2.5/4.18);
const unsigned int16 ChargeMin = (unsigned int16)(1024 * 2.5/4.10);

после такого пишет Memory Usage: ROM38% RAM30%

А после такого варианта:
Код
#define VoltageMax  (2.5/(4.18/1024))
#define VoltageMin  (2.5/(4.10/1024))
volatile unsigned int16 ChargeMax = VoltageMax;
volatile unsigned int16 ChargeMin = VoltageMin;


Memory Usage: ROM39% RAM36%

Непонятно..


--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 25 2009, 14:30
Сообщение #10


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Eddy71 @ Feb 25 2009, 18:22) *
Непонятно..

Все просто: второй случай

volatile unsigned int16 ChargeMax = VoltageMax;


Подразумевает, что VoltageMax жрет флеш в виде непосредственного операнда либо двух байт в таблице инициализации, и ChargeMax жрет две ячейки памяти ОЗУ.

Экономия при дефайне получается, когда например

Код
int16 temp;

temp = WREG; // что-то откуда-то прочли

if(temp > VoltageMax) temp = VoltageMax;


типотак
Go to the top of the page
 
+Quote Post
Eddy71
сообщение Feb 25 2009, 15:00
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 224
Регистрация: 23-11-08
Из: Украина, Луганск
Пользователь №: 41 879



Цитата(_Pasha @ Feb 25 2009, 17:30) *
Экономия при дефайне получается, когда например
Код
int16 temp;
temp = WREG; // что-то откуда-то прочли
if(temp > VoltageMax) temp = VoltageMax;

Мне переприсваивать не надо. У меня читается АЦП
Цитата
temp = WREG; // что-то откуда-то прочли)

И затем сравнивается со значениями Max и Min. То есть с константами, которые никоим образом не меняются при работе программы.

Понимаю, что проблема яйца выеденного не стоит, тем более работают оба варианта одинаково, просто хочется разобраться с логикой работы компилятора, чтобы потом глупых вопросов не задавать.
Вот это код:
Код
#define VoltageMax  (2.5/(4.18/1024))
volatile unsigned int16 ChargeMax = VoltageMax;

преобразовался в:
Код
0160:  MOVLW  64
0161:  MOVWF  2E
0162:  MOVLW  02
0163:  MOVWF  2F

Зато в случае с константой значения выплыли только при сравнении:
Код
value>ChargeMax

превратилось в
Код
00E7:  MOVF   34,W
00E8:  SUBLW  01
00E9:  BTFSC  03.0
00EA:  GOTO   0F2
00EB:  XORLW  FF
00EC:  BTFSS  03.2
00ED:  GOTO   0C3
00EE:  MOVF   33,W
00EF:  SUBLW  64
00F0:  BTFSS  03.0
00F1:  GOTO   0C3

В предидущем случае в том же кусочку вместо movlw шли movf и размер кода рос.
Так что определение значений :
Код
const unsigned int16 ChargeMax = (unsigned int16)(1024 * 2.5/4.18);

Оказалось самым правильным. smile.gif

Сообщение отредактировал Eddy71 - Feb 25 2009, 15:10


--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
Go to the top of the page
 
+Quote Post
xemul
сообщение Feb 25 2009, 15:33
Сообщение #12



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Eddy71 @ Feb 25 2009, 17:22) *
...
Непонятно..

Вы volatile пишете осмысленно, или просто потому, что слово красивое? Уберите volatile перед ChargeMax, и (value>ChargeMax) будет нормальным образом оптимизировано. volatile - указание компилятору не оптимизировать операции с такими переменными, т.к. они могут изменяться непредсказуемым образом (н-р, в прерываниях).
На
Код
#define VoltageMax  (2.5/(4.18/1024))
#define VoltageMin  (2.5/(4.10/1024))
volatile unsigned int16 ChargeMax = VoltageMax;
volatile unsigned int16 ChargeMin = VoltageMin;

препроцессор должен выдать два предупреждения вроде "implicit conversion float to integer" (неявное преобразование плавучки в целое, которое может сопровождаться потерей точности).
На
Код
const unsigned int16 ChargeMax = (unsigned int16)(1024 * 2.5/4.18);

он так не говорит, т.к. (unsigned int16) - оператор явного преобразования типа. Компилятор понимает, что и Вы понимаете суть происходящего.
Понаблюдайте за реакцией компилятора (естесно, по очереди) на эти #define:
Код
#define VoltageMax  (unsigned int16)(2.5/(4.18/1024))   // будет 612 без предупреждения; промежуточные вычисления во float
//#define VoltageMax  (250/(418/1024))   // будет ошибка "divide by zero"; (418/1024) = 0
//#define VoltageMax  (1024*250/418)     // будет 63 вместо 612, но без предупреждения; переполнение int, 1024*250 > 32767
//#define VoltageMax  (1024L*250/418)    // будет 612 без предупреждения; промежуточные вычисления препроцессор проведет в long
unsigned int16 ChargeMax = VoltageMax;
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 25 2009, 22:37
Сообщение #13


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Привыкайте писать грамотно. Используйте препроцессор (define etc.) только там, где он необходим.
Вы программируете в первую очередь на СИ а не на языке препроцессора (условно говоря).
static const заменяет define в 90% случаев (и не занимет память как в случае без static).
Код
static const unsigned int16 CHARGE_MAX = (unsigned int16)(1024.0 * 2.5 / 4.18 + 0.5);
static const unsigned int16 CHARGE_MIN = (unsigned int16)(1024.0 * 2.5 / 4.10 + 0.5);

+0.5 для правильного округления положительных чисел до целого при отбрасывании дробной части
(int)(1.1 + 0.5) = 1
(int)(1.4 + 0.5) = 1
(int)(1.5 + 0.5) = 2
(int)(1.9 + 0.5) = 2
(int)(2.0 + 0.5) = 2

Имена констант и то что объявлено через define заглавными буквами, всё остальное строчными.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Eddy71
сообщение Feb 26 2009, 08:33
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 224
Регистрация: 23-11-08
Из: Украина, Луганск
Пользователь №: 41 879



Исчерпывающий совет. Одно не совсем понятно. Почему константу еще и static надо усугублять? Ведь константа по-определению не меняется в процессе исполнения программы..


--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 26 2009, 09:53
Сообщение #15


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Если константа объявлена как статик, то компилятор понимает что она локальна в модуле или в процедуре.
И если компилятор видит что внутри этого модуля не происходит взятие адреса этой константы, то он её не создаёт.
Т.е. не занимает под неё память (получается почти полная аналогия с define в смысле отъедания памяти).
Если объявлена просто константа типа const float f; - то она займёт память (целых 4 байта).
Вообще у static я насчитал 3 различных смысла (хотя по правде их только два):
1) для "облегчения" констант
2) для сокрытия локальных процедур и переменных в модуле (+ развязывает руки компилятору по встраиванию таких функций как inline)
3) для локальных статических переменных внутри процедур с неограниченным сроком годностиsmile.gif

Всем этим надо активно и умело пользоваться и размер Ваших программ сильно уменьшится, что Вы даже удивитесьsmile.gif
Возьмите за правило: если функция или переменная или константа не объявляется в заголоыочном файле как extern
(т.е. не используется за пределами единицы трансляции) то она должна быть static.
Помимо всего это ещё и дополнительное средство самодокументирования кода.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 24th July 2025 - 10:00
Рейтинг@Mail.ru


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