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

 
 
 
Reply to this topicStart new topic
> проблема с вычислениями, WinAVR
ARV
сообщение Jul 22 2010, 08:20
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 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 будет тринадцать тысяч с хвостиком - ан нет sad.gif

что не так?!


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
dimka76
сообщение Jul 22 2010, 08:27
Сообщение #2


developer
****

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



Код
#define CONCAT(x,y)      (x ## y)


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
ARV
сообщение Jul 22 2010, 09:43
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 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)

че за хрень?


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jul 22 2010, 09:49
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 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 будет тринадцать тысяч с хвостиком - ан нет sad.gif

что не так?!


MAX_OCR = 11059200 * (9500UL / 8) / 1000000 = 13127270400UL / 1000000
Дальше все зависит от того, что такое UL. Подозреваю, что это uint32_t, тогда 13127270400UL = 0x0E724000 и вы получаете 242 в результате...

Скорее всего поможет ULL...
Go to the top of the page
 
+Quote Post
ARV
сообщение Jul 22 2010, 09:50
Сообщение #5


Профессионал
*****

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



и вот так тоже работает sad.gif
Код
#define MAX_PHASE        9500ULL
.........
#define MAX_OCR            (F_CPU * MAX_PHASE / TDIV / 1000000UL)
то есть получается, что если тип константы задан для числителя выражения - все вычисляется верно, а если для знаменателя - то нет sad.gif а я был уверен, что ВСЕ операнды в выражении приводятся к самому "длинному" или самому многоразрядному типу, встреченному среди них...

я не прав или это GCC подкачало?


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jul 22 2010, 09:51
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(ARV @ Jul 22 2010, 13:43) *
эффект сохраняется даже если я делаю так:(F_CPU * MAX_PHASE / TDIV / 1000000ULL) то есть делаю константу 1000000 типа unsigned long long - по идее ведь все вычисления теперь должны вестись в размерах этого типа ...

Это не так - типы приводятся в каждой операции отдельно. В размерности ULL идет только последнее деление, а предыдущие операции - в размерности UL (давай переполнение)
Go to the top of the page
 
+Quote Post
ARV
сообщение Jul 22 2010, 10:32
Сообщение #7


Профессионал
*****

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



Цитата(Непомнящий Евгений @ Jul 22 2010, 13:51) *
Это не так - типы приводятся в каждой операции отдельно. В размерности ULL идет только последнее деление, а предыдущие операции - в размерности UL (давай переполнение)
гм... был уверен, что приведение типов операндов делается для всего выражения...
тем более для равноприоритетных операций...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Jat
сообщение Jul 25 2010, 10:25
Сообщение #8





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

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

 


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


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