Перейти к содержанию
    

Проблемы с делением в IAR для mega168

Не могу врубится в чем проблема. IAR 5.11. ATmega168

 

В h-файле объявлены константы:

 

#define CONST1 8640

#define CONST2 720

 

 

В С-файле функция вида:

 

void func(void) {

 

static unsigned short w, x;

 

w = (unsigned short)((unsigned long)CONST1 * x / CONST2 + 1);

 

}

 

w вычисляется не верно. Проверял операцию по действиям: CONST1 * x вычисляется верно, а вот деление уже возвращает фигню. Что поразительно, начинает считать верно, когда вместо CONST2 подставляю в код ее реальное значение 720:

 

w = (unsigned short)((unsigned long)CONST1 * x / 720 + 1);

 

Это работает.

 

В чем прикол?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не могу врубится в чем проблема. IAR 5.11. ATmega168

 

В h-файле объявлены константы:

....

В чем прикол?

А "прикол" в том, что по умолчаннию константам CONST1 и CONST2 компилятором оределяется их размер как int (применительно к IAR AVR 5.11 - 4 байта). Тоесть максимальное возможное число 65535. А приведение к нужному типу происходит, когда непосредственно выполяется операция деления, как вы и указали это сделать.

Поэтому лучше привести константы к нужному размеру исходя из возможной получаемой длины результата и его знака.

Я бы указал :rolleyes: :

#define CONST1 8640UL
#define CONST2 720UL

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы указал :rolleyes: :

#define CONST1 8640UL
#define CONST2 720UL

 

Верно. Так работает. Но только есть одно Но. На самом деле моя константа определяется не числом а выражением также состоящим из констант. И как только я подставлю вычесленный результат-константу в выражение в функции - тут же облом. Но если присвоить эту коснтанту переменной, и использовать в выражении переменную - то тоже все ок.

Неужели без введения переменной нельзя обойтись.

В Выражениях с константами я уже пробовал и приведение типов делать и UL подставлять - нифига! Работает только если в лоб число - например 720UL. А в выражении забивает компилер на этот UL.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что то тут не то.

 

Куски

 

#define CONST2 720
w = (unsigned short)((unsigned long)CONST1 * x / CONST2 + 1);

 

и

 

w = (unsigned short)((unsigned long)CONST1 * x / 720 + 1);

 

должны быть абсолютно эквивалентны - транслироваться в одинаковый asm-код.

 

А судя по вашим словам это не так.

Что поразительно, начинает считать верно, когда вместо CONST2 подставляю в код ее реальное значение 720:

 

Попробуйте включить генерацию lst - файлов и сравнить результат в обоих случаях...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Верно. Так работает.

Так работает или не работает ? Вы пожалуйста определитесь ! :biggrin:

На самом деле моя константа определяется не числом а выражением также состоящим из констант.

Насколько я вижу из вашего кода, выражение о котором Вы упоминаете

w = (unsigned short)((unsigned long)CONST1 * x / CONST2 + 1);

никак не может быть константным, поскольку в нем присутвует переменная unsigned short x.

Дело в том что нужно понимать, что если выраженние состоит из констант тоесть по сути является константным для программы, то его результат получает препроцессор перед компиляцией, а когда выражение не является константным, то его результат вычисляется уже в процессе выполнения самой программы. В таких случаях, возможно даже придется подключать библиотеку математических функций. Или Вы думаете ATmega168 имеет в наборе команд ассемблера операции деления ? :biggrin:

В любом случае - определитесь для начала c выражением в котором Вы выполняеете вычисления, потом в размере и знаке каждого значения выражения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но. На самом деле моя константа определяется не числом а выражением также состоящим из констант.

1. Возможно, выражение в define при CONST2 записано не корректно. Попробуйте определить чему будет равно A=CONST2

2. Попробуйте: либо запишите

#define CONST2 ((unsigned long)(выражение))

либо

w = (unsigned short)((unsigned long)CONST1 * x / (unsigned long)CONST2 + 1);

 

P.S. Еще бывает, что выражение в дефайне не берут в скобки - тогда получаются чудеса (например, если выражение типа A + B ). Очень желательно записывать так:

#define CONST2 (выражение)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. Еще бывает, что выражение в дефайне не берут в скобки - тогда получаются чудеса (например, если выражение типа A + B ). Очень желательно записывать так:

#define CONST2 (выражение)

 

Палыч, Вы монстр! Вы точно поймали суть, хотя вопрос я изначально поставил не корректно, не указав, что в дефайне стоит выражение, а не число.

Спасибо за правильный ответ!

Я целый день тупил с этим, а все дело оказалось просто в скобках. А я-то думал, что define на этапе компиляции вычисляется, а потом подставляется в выражение. А оказалось, что он сначала подставляеся в выражение, затем расставляются приоритеты операций, и потом только вычисляется. Без скобок приоритеты-то неверно расставлялись... :-)

Спасибо. Вопрос снят!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А я-то думал, что define на этапе компиляции вычисляется, а потом подставляется в выражение.

Нет, он подставляется препроцессором перед компиляцией, причём тупо 1-в-1 , за исключением макросов с параметрами

Теперь вы знаете, зачем в дефайнах ставят скобки :rolleyes:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...