|
|
  |
проблема с вычислениями, WinAVR |
|
|
|
Jul 22 2010, 08:20
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
я в шоке! пишу: Код #define MAX_PHASE 9500UL #define TDIV 8 #define CONCAT(x,y) x ## y #define DIVISOR(x) CONCAT(TIMER_CLK_DIV_,x) #define PRESCALER DIVISOR(TDIV) #define MAX_OCR (((F_CPU * (MAX_PHASE/TDIV) / 1000000))) #define TCNT_INIT ((UINT16_MAX + 1UL)- MAX_OCR) вроде бы все верно (на странно расставленные скобки в MAX_OCR не обращайте внимания - это я от безысходности расставлял их). однако следующая строка Код printf_P(PSTR("SI:%u;%u;%u\n"),200,MAX_OCR,TCNT_INIT); выводит в консоль Цитата SI:200;242;65294 ума не приложу, в чем дело! F_CPU у меня 11059200UL, ожидаю, что MAX_OCR будет тринадцать тысяч с хвостиком - ан нет что не так?!
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jul 22 2010, 09:43
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(dimka76 @ Jul 22 2010, 12:27)  Код #define CONCAT(x,y) (x ## y) и что? ничего не понимаю... понятно, что происходит переполнение вычислений, НО ПОЧЕМУ? эффект сохраняется даже если я делаю так: (F_CPU * MAX_PHASE / TDIV / 1000000ULL) то есть делаю константу 1000000 типа unsigned long long - по идее ведь все вычисления теперь должны вестись в размерах этого типа и никакого переполнения быть не может... зато вот так все работает верно: (F_CPU / TDIV /1000 * MAX_PHASE / 1000) и вот так тоже работает ((unsigned long long)F_CPU / TDIV * MAX_PHASE / 1000000UL)че за хрень?
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jul 22 2010, 09:49
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(ARV @ Jul 22 2010, 12:20)  Код #define MAX_PHASE 9500UL #define TDIV 8 #define CONCAT(x,y) x ## y #define DIVISOR(x) CONCAT(TIMER_CLK_DIV_,x) #define PRESCALER DIVISOR(TDIV) #define MAX_OCR (((F_CPU * (MAX_PHASE/TDIV) / 1000000))) #define TCNT_INIT ((UINT16_MAX + 1UL)- MAX_OCR) вроде бы все верно (на странно расставленные скобки в MAX_OCR не обращайте внимания - это я от безысходности расставлял их). однако следующая строка Код printf_P(PSTR("SI:%u;%u;%u\n"),200,MAX_OCR,TCNT_INIT); выводит в консоль ума не приложу, в чем дело! F_CPU у меня 11059200UL, ожидаю, что MAX_OCR будет тринадцать тысяч с хвостиком - ан нет что не так?! MAX_OCR = 11059200 * (9500UL / 8) / 1000000 = 13127270400UL / 1000000 Дальше все зависит от того, что такое UL. Подозреваю, что это uint32_t, тогда 13127270400UL = 0x0E724000 и вы получаете 242 в результате... Скорее всего поможет ULL...
|
|
|
|
|
Jul 22 2010, 09:50
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
и вот так тоже работает Код #define MAX_PHASE 9500ULL ......... #define MAX_OCR (F_CPU * MAX_PHASE / TDIV / 1000000UL) то есть получается, что если тип константы задан для числителя выражения - все вычисляется верно, а если для знаменателя - то нет  а я был уверен, что ВСЕ операнды в выражении приводятся к самому "длинному" или самому многоразрядному типу, встреченному среди них... я не прав или это GCC подкачало?
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jul 25 2010, 10:25
|
Группа: Участник
Сообщений: 8
Регистрация: 6-03-06
Из: Новосибирск
Пользователь №: 15 027

|
Цитата(ARV @ Jul 22 2010, 15:20)  я в шоке! что не так?! Почему? Что написано, то и получено! Код printf_P(PSTR("SI:%u;%u;%u\n"),200,MAX_OCR,TCNT_INIT); Попробуй так Код printf_P(PSTR("SI:%u;%ul;%ul\n"),200,(unsigned long)MAX_OCR,(unsigned long)TCNT_INIT);
Сообщение отредактировал Jat - Jul 25 2010, 10:25
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|