Отговори на тема  [ 20 мнения ]  Отиди на страница 1, 2  Следваща
MCC18 constants declaration 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение MCC18 constants declaration
Подразни ме следната недомислица в MCC18 3.12 на Microchip:
Код:
const float Pi = 22.0/7.0;
const float Pi2 = Pi * Pi;

const float cf_var1 = 68.0;
const float cf_var2 = 12.0;
const float cf_var3 = ( cf_var2 / ( cf_var1 + cf_var2 ) );

void main(void) {
float f_var;
   while( 1 ) {
      f_var = cf_var3 / Pi2;
   }
}


Горния код не иска да се компилира, плюе се следното съобщение:

Цитат:
Error [1214] constant expression expected in initializer


Обаче, ако се напише така:
Код:
void main(void) {
const float Pi = 22/7;
const float Pi2 = Pi * Pi;

const float cf_var1 = 68.0;
const float cf_var2 = 12.0;
const float cf_var3 = ( cf_var2 / ( cf_var1 + cf_var2 ) );

float f_var;
   while( 1 ) {
      f_var = cf_var3 / Pi2;
   }
}

се компилира, само че излиза, че трябва константите да ги декларирам във всяка подпрограма, където ще се използват.

Някой да е заобикалял този проблем ? С #define също не става, иска се непременно числена стойност.

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Пет Юли 06, 2007 9:20 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Що не ги сметнеш е елката :D


Пет Юли 06, 2007 10:33 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение 
HCL написа:
Що не ги сметнеш е елката :D

Мразим да смятаме :D Кода е примерен, ако са по сложни изразите и се налага да правиш промени в коефициентите става една ...

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Пет Юли 06, 2007 10:42 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
само за информация, в Keil проблемьт го няма.


Пет Юли 06, 2007 11:31 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение 
HCL написа:
само за информация, в Keil проблемьт го няма.

Това си е бъг в MCC18 :D , няма как да го има и при Keil.

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Пет Юли 06, 2007 11:41 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 24, 2005 11:41 pm
Мнения: 1049
Местоположение: Pz
Мнение 
Е така става:
Код:
const float Pi, cf_var1, cf_var2;

#define Pi  22.0/7.0
const float Pi2 = (Pi * Pi);

#define cf_var1  68.0
#define cf_var2  12.0
const float cf_var3 = ( cf_var2 / ( cf_var1 + cf_var2 ) );

Ако Pi, cf_var1 и cf_var2 няма да ги ползваш в кода, може да не ги дефинираш като "const float"


Съб Юли 07, 2007 12:08 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Ами аз по принцип на всичко де що е 8-16 бита константите гледам да ги правя с #define. От опит знам, че голямо количество от компилаторите за "малки" контролери се посират в такива ситуации.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Съб Юли 07, 2007 3:05 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Яну 19, 2007 9:16 am
Мнения: 1063
Местоположение: путинофили: "иди н***й"
Мнение 
никога в никой компилатор не съм ползвал "const" за деклариране на константи - само #define

това не виждам причина да не работи:
Цитат:
#define Pi ((float)(22.0/7.0))
#define Pi2 ((float)(Pi * Pi))

#define cf_var1 ((float)68.0)
#define cf_var2 ((float)12.0)
#define cf_var3 ((float)cf_var2/(cf_var1+cf_var2))


по-принцип "const" може да има различни интерпретации/значения на различните компилатори ...


Съб Юли 07, 2007 8:22 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение 
Проблема е ясен: на дадено място в програмата няма проблеми с изчисляването на константен израз, на друго място има. #define не ги харесвам, защото често се бъркаш с какъв точно тип данни работиш. Лошото е, че и с #define не може да изчисли израза, ако декларирам константа-променлива на глобално ниво в рамките на един файл. Много малко съм използвал MCC18, мислех си, че е добър, но се оказа, че има много гювеч по него.

В тоя ред мисли, да задам още една гатанка ( за мен ): как мога, в Ц програма за МЦЦ18, да си декларирам unsigned int променлива, която променлива да разположа на адреса на ADRESH:ADRESL ? Целта ми е да имам максимално бърз достъп до тези клетки, без да ми се налага да правя от два 8-битови регистъра една 16-битова unsigned int променлива [ unsigned int res16 = ((unsigned int)(ADRESH<<8 )) | ADRESL ]

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Съб Юли 07, 2007 11:56 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Яну 19, 2007 9:16 am
Мнения: 1063
Местоположение: путинофили: "иди н***й"
Мнение 
¶ написа:
Проблема е ясен: на дадено място в програмата няма проблеми с изчисляването на константен израз, на друго място има. #define не ги харесвам, защото често се бъркаш с какъв точно тип данни работиш. Лошото е, че и с #define не може да изчисли израза, ако декларирам константа-променлива на глобално ниво в рамките на един файл. Много малко съм използвал MCC18, мислех си, че е добър, но се оказа, че има много гювеч по него.

В тоя ред мисли, да задам още една гатанка ( за мен ): как мога, в Ц програма за МЦЦ18, да си декларирам unsigned int променлива, която променлива да разположа на адреса на ADRESH:ADRESL ? Целта ми е да имам максимално бърз достъп до тези клетки, без да ми се налага да правя от два 8-битови регистъра една 16-битова unsigned int променлива [ unsigned int res16 = ((unsigned int)(ADRESH<<8 )) | ADRESL ]


аз в #define винаги указвам типа който да се връща, и всичко е в () за всеки случай ... при смятането на изрази винаги указвам типа на резултата (за всеки случай :))

Цитат:
декларирам unsigned int променлива, която променлива да разположа на адреса на ADRESH:ADRESL


това много не го схванах ... може би искаш:

#define ADRES_PTR(adr) ((unsigned int *)(adr))
#define ADRES(adr) *ADRES_PTR(adr)

така с:

....
ADRES(12345) = 23456;
unsigned int temp = ADRES(12345); // temp == 23456

на адрес 12345 ще запишеш 23456 ... от това по-бързо не се сещам а и за компилатора би трябвало да е ясно какво да прави.
виж му asm кода за да прецениш !

PS: стига компилатора ти да поддържа макродефиниции :)


Нед Юли 08, 2007 5:39 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение 
С указател е ясно, че може :-), но с указателя се харчи много време, да се заредят FSRxH:FSRxL, да се извлече единия байт, после да се извлече втория. Идеята е, на адреса на 2-те 8-битови клетки за резултата от АЦП-то да разположа моя 16-битова променлива, тя ще е с директен достъп, няма да се иска превключване на банки, операндите с които ще се използва тази 16-битова променлива са също с директетн достъп, така ще стане най-бърз кода, все едно, че е на асемблер :-) Има някакви директиви, с които се твърди, че може да се направят overlay променливи, обаче като задам такава променлива да бъде в адресното пространство 0xF00-0xFFF компилатора се сърди и не иска да я възприеме. Уж 18-та серия са разширен набор от инструкции, което теоретчно ги прави доста по-бързи от 16-та, но МЦЦ18 компилатора бълва толкова код, че бързодействието на 18-та серия се губи, става като на 16-та :-)
Ето например какво излиза, когато искам да извлека резултата от АЦП-то:
Код:
unsigned int res16;
   res16 = (((unsigned int)ADRESH)<<8) | ADRESL;
  0180    50C4     MOVF 0xfc4, W, ACCESS
  0182    6E02     MOVWF 0x2, ACCESS
  0184    C002     MOVFF 0x2, 0x3
  0186    F003     NOP
  0188    6A02     CLRF 0x2, ACCESS
  018A    50C3     MOVF 0xfc3, W, ACCESS
  018C    0100     MOVLB 0
  018E    1002     IORWF 0x2, W, ACCESS
  0190    6E00     MOVWF 0, ACCESS
  0192    C003     MOVFF 0x3, 0x1
  0194    F001     NOP
  0196    C000     MOVFF 0, 0xfde
  0198    FFDE     NOP
  019A    C001     MOVFF 0x1, 0xfdd
  019C    FFDD     NOP


Това на асемблер би станало така:
Код:
movff ADRESH, res16+1
movff ADRESL, res16+0


демек 4 цикъла на асемблер, 15 цикъла на Ц :-(

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Нед Юли 08, 2007 8:53 am
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Яну 19, 2007 9:16 am
Мнения: 1063
Местоположение: путинофили: "иди н***й"
Мнение 
от пикове не разбирам :)

обаче не мога да разбера защо правиш сметките по-долу за res16 !?

Цитат:
unsigned int res16;
res16 = (((unsigned int)ADRESH)<<8) | ADRESL;


ако целта ти е:
Цитат:
movff ADRESH, res16+1
movff ADRESL, res16+0


по-добре би било:

*((unsigned char *)&res16) = ADRESL;
*(((unsigned char *)&res16)+1) = ADRESH;

не виждам причина от горните два реда компилатора да генерира нещо по-различно от
Цитат:
movff ADRESL, res16+0
movff ADRESH, res16+1


Нед Юли 08, 2007 10:00 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 24, 2005 11:41 pm
Мнения: 1049
Местоположение: Pz
Мнение 
За да стане това:
Код:
movff ADRESH, res16+1
movff ADRESL, res16+0

ползвам това:
Код:
rеs16 = (*(unsigned int *)(&ADRESL));


:partyman:


Нед Юли 08, 2007 7:14 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Аз тия работи ги правя така
Код:
#define highbyte(x) (*(((unsigned char *)&x)+1))
#define lowbyte(x) (*((unsigned char *)&x))


и после

Код:
unsigned int n;

lowbyte(n) = ADRESL;
highbyte(n) = ADRESH;


тва ме светна някой тука във форума и все него си ползвам. На пикльовския компилер си генерира точно каквото очаквам :)

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Пон Юли 09, 2007 8:15 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение 
Бахтий компилатора, шибан :-)

Ето така става най-кратко:

Код:
typedef unsigned int uint16;
#pragma udata access my_access
near uint16 ui_Uout16;
#define ui_adres16 (*(uint16 *)(&ADRESL))
....
  ui_Uout16 += ui_adres16;
....


Но въпреки всичко си избълва 2 ненужни инструкции movlb, явно за да си върже гащите :-)

Код:
  045C    010F     MOVLB 0xf ; ненужна инструкция, ui_adres16 е в access bank
  045E    50C3     MOVF 0xfc3, W, ACCESS
  0460    2602     ADDWF 0x2, F, ACCESS
  0462    010F     MOVLB 0xf ; ненужна инструкция, ui_adres16 е в access bank
  0464    50C4     MOVF 0xfc4, W, ACCESS
  0466    2203     ADDWFC 0x3, F, ACCESS


Все пак е вече приемливо, 6 инструкции, срещу 20-тина инструкции преди това.
Мерси за идеите.

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Пон Юли 09, 2007 5:23 pm
Профил WWW
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 20 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни