|
Вычисляемая константа в PCW, как? |
|
|
|
Feb 25 2009, 11:21
|

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

|
Возникло желание "попросить" компилятор (PCW) при компиляции рассчитать значение константы (на этапе отладки устройства приходится часто подбирать значение). Пытаюсь вставить такое: Код const unsigned int16 VoltageMax = 2.5/(4.18/1024); Ругается. Приходится вручную подставлять 612. Если не указываю, что это константа, компилятор напихивает библиотек и прошивка "раздувается". Что я не так делаю?
--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
|
|
|
|
|
Feb 25 2009, 11:31
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 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 =)
|
|
|
|
|
Feb 25 2009, 11:37
|
;
     
Группа: Участник
Сообщений: 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;
|
|
|
|
|
Feb 25 2009, 11:53
|

Местный
  
Группа: Свой
Сообщений: 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); Остановился на этом варианте. Хоть он и "самый длинный", но с учетом того, что я только осваиваю компилятор, он самый наглядный. Хотя и другие варианты откомпилировались без ругани. Интересно, почему писатели юзер мануала не предположили, что кто-то захочет такое вставить в свою программу.. Спасибо большое всем.
--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
|
|
|
|
|
Feb 25 2009, 13:07
|

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

|
Цитата(MrYuran @ Feb 25 2009, 14:58)  Вообще константа отличается от дефайна тем, что она располагается в памяти (ОЗУ или во флеши) и программа по мере надобности к ней обращается. Дефайн подставляется по месту на этапе компиляции препроцессором. Сейчас пытался дефайном вставить - ругается, зараза.. Сам дефайн "съедает". А вот потом присвоить переменным не выходит. ОЗУ тратить не хочется..
--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
|
|
|
|
|
Feb 25 2009, 13:28
|

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

|
Цитата(Eddy71 @ Feb 25 2009, 16:07)  Сейчас пытался дефайном вставить - ругается, зараза.. А ругается-то как? Error - это ругается. А Warning - это просто предупреждает, что, мол, имеете право, но возможны проблемы... Лучше выкладывайте, как ругается и на что, показательней будет
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 25 2009, 14:22
|

Местный
  
Группа: Свой
Сообщений: 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% Непонятно..
--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
|
|
|
|
|
Feb 25 2009, 14:30
|
;
     
Группа: Участник
Сообщений: 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; типотак
|
|
|
|
|
Feb 25 2009, 15:00
|

Местный
  
Группа: Свой
Сообщений: 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); Оказалось самым правильным.
Сообщение отредактировал Eddy71 - Feb 25 2009, 15:10
--------------------
«Чтобы что-то изобрести, вам потребуется хорошее воображение и куча мусора» /Томас Эдисон/
|
|
|
|
|
Feb 25 2009, 15:33
|
    
Группа: Свой
Сообщений: 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;
|
|
|
|
|
Feb 25 2009, 22:37
|

неотягощённый злом
     
Группа: Свой
Сообщений: 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 заглавными буквами, всё остальное строчными.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 26 2009, 09:53
|

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

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