sonycman 0 15 апреля, 2008 Опубликовано 15 апреля, 2008 · Жалоба Имеется IAR 5.10 и проект на С для ATmega88. Исходник (кусок): #define QUARTZ 10000000 #define CLOCK QUARTZ/1000000 #define Wait(mks) __delay_cycles(mks*CLOCK) Wait(480); При компиляции идут предупреждения на строку с функцией о выходе значения за пределы диапазона. Но ведь итоговое значение равно 4800, а параметр __delay_cycles есть unsigned long! Если CLOCK жестко приравнять к 10, то все нормально. Но если ее приравнять к 100, то получаем ту-же ошибку out of range плюс еще и о смене знака... :-( Получается, что компилятор работает с 16-ти битными данными? Как это побороть? И почему не работает вышеприведенный пример? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 18 15 апреля, 2008 Опубликовано 15 апреля, 2008 (изменено) · Жалоба параметр __delay_cycles есть unsigned long! Точно? А может всё-таки uint? Как это побороть? И почему не работает вышеприведенный пример? Я бы попробовал для начала явное приведение типа, типа: #define Wait(mks) __delay_cycles((unsigned long)(mks*CLOCK)) А вообще изврат по-моему, отдавать паузы на откуп компилятору... Я бы не рискнул. Изменено 15 апреля, 2008 пользователем MrYuran Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladimirYU 0 15 апреля, 2008 Опубликовано 15 апреля, 2008 · Жалоба Имеется IAR 5.10 и проект на С для ATmega88. Исходник (кусок): #define QUARTZ 10000000UL #define CLOCK QUARTZ/1000000 #define Wait(mks) __delay_cycles(mks*CLOCK) Wait(480); Добавьте UL Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
YAM 0 15 апреля, 2008 Опубликовано 15 апреля, 2008 · Жалоба Всегда делаю так: #define OS_FSYS_MHZ 7.3728 // Системная частота [MHz] #define DelayUs(us) __delay_cycles((u32)((us) * OS_FSYS_MHZ)) да, u32 - это unsigned long Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 15 апреля, 2008 Опубликовано 15 апреля, 2008 · Жалоба По умолчанию (без явного объявления) к переменным и константам применяется тип int (signed int). Поскольку в стандарте Си размерность типов переменных явно не определена (определены только диапазоны в limits.h), то для надежности на 8-ми/16-и битных платформах нужно явно указывать тип больших по величине констант, добавляя к числу суффикс. L - signed long (например, 100000L) UL - unsigned long (например, 7372800UL) f - float (например, 3.14159f). Кстати, без суффикса f константа 7.3728 в примере выше #define OS_FSYS_MHZ 7.3728 // Системная частота [MHz] может легко стать 64-и разрядной double, в зависимости от настроек проекта и/или если препроцессор посчитает это нужным. Опять же, может я конечно и ошибаюсь, но по-моему препроцессор вычисляет только целочисленные выражения в макросах. Так что макрос типа #define XMIN 1.2345 #define XMAX 2.3456 #define YMIN 3.456 #define YMAX 4.5678 #define LINE(x) ((YMAX-YMIN)/(XMAX-XMIN)*(x-XMIN)+YMIN) при подстановке в операцию y=LINE(x); даст только лишь удобство написания, но скорость вычисления не уменьшит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
YAM 0 15 апреля, 2008 Опубликовано 15 апреля, 2008 · Жалоба Вы ошибаетесь. Ведь это так легко проверить. ;) А результат операции y=LINE(x); будет зависеть от типа y... Кроме того вот так: y=LINE(2.71828) увеличит и значительно ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 15 апреля, 2008 Опубликовано 15 апреля, 2008 · Жалоба Вы ошибаетесь. Ведь это так легко проверить. ;)Неудачный пример. Согласен :) Только подставить константы в выражение должен любой препроцессор, а вот вычислить константное выражение и подставить его значение - нет. Это уже задача оптимизации компилятора. Кроме того вот так: y=LINE(2.71828) увеличит и значительно ;)Увеличит? :07: Вы наверное хотели написать "уменьшит"? Потому, что такой оператор должен сводиться к банальной загрузке константы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 16 апреля, 2008 Опубликовано 16 апреля, 2008 · Жалоба Добавьте UL Спасибо, добавил, ошибки исчезли, но величина задержки всё равно вычисляется неправильно. Вот как это выглядит: #define QUARTZ 10000000UL //Crystal quartz frequency #define CLOCKS QUARTZ/1000000UL //tacts in microsecond void SomeFunc(void) { volatile unsigned long a = 480 * CLOCKS; } Так вот, при просмотре отладчиком полученного кода, значение а получается равным 0x0001f9, то есть 505, когда должно быть 4800... Чёрт, что за глупости :smile3046: Причём значения до 420 * CLOCKS обсчитываются правильно, а чуть побольше и пошла бредятина... Всё, разобрался. Оказывается эта, извиняюсь за выражение, "тупая скотина" в лице препроцессора или компилятора не вычисляет значение CLOCK, а просто тупо подставляет строку в нужное место. Например, вышеприведённое выражение принимает вид: volatile unsigned long a = 480 * QUARTZ / CLOCKS а потом уже компилятор пыжится посчитать: volatile unsigned long a = 480 * 10000000 / 1000000 Естественно, после умножения идёт переполнение за 32 бита, и делению подлежат уже жалкие останки гигантской цифры... :07: Пришлось поставить скобки, теперь вроде всё нормально: #define QUARTZ 10000000UL //Crystal quartz frequency #define CLOCKS (QUARTZ/1000000) //tacts in microsecond #define Wait(mksec) __delay_cycles(mksec*CLOCKS) Wait(480); На первый взгляд, какого чёрта делают скобки в таком простом выражении? Ну вот откуда знаешь поначалу такие неявные мелочи? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 18 16 апреля, 2008 Опубликовано 16 апреля, 2008 (изменено) · Жалоба #define QUARTZ 10000000UL //Crystal quartz frequency #define CLOCKS QUARTZ/1000000UL //tacts in microsecond А если предположить, что вместо CLOCKS (как бы 10) препроцессор подставляет QUARTZ/1000000UL? Что получается? Правильно, volatile unsigned long a = 480 * QUARTZ/1000000UL; Теперь попробуем умножить 480 на 10000000UL... так... умножаем... опа! 0х11E1A3000 А теперь считаем количество разрядов... Идея понятна? Я тут вот ещё добавлю: лучше тогда уж флот использовать, может не так точно (а надо ли), зато переполнения не будет. Да и вообще поаккуратнее с дефайнами Изменено 16 апреля, 2008 пользователем MrYuran Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 16 апреля, 2008 Опубликовано 16 апреля, 2008 · Жалоба А если предположить, что вместо CLOCKS (как бы 10) препроцессор подставляет QUARTZ/1000000UL? Что получается? Правильно, volatile unsigned long a = 480 * QUARTZ/1000000UL; Теперь попробуем умножить 480 на 10000000UL... так... умножаем... опа! 0х11E1A3000 А теперь считаем количество разрядов... Идея понятна? Спасибо за помощь, я уже сам допёр :) ЗЫ: хороший форум, всегда помогут добрые люди! :a14: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
YAM 0 16 апреля, 2008 Опубликовано 16 апреля, 2008 · Жалоба 2 rezident Вы писали: "даст только лишь удобство написания, но скорость вычисления не уменьшит.". Я и написал, что увеличит в плане скорости вычисления... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 16 апреля, 2008 Опубликовано 16 апреля, 2008 · Жалоба не вычисляет значение CLOCK, а просто тупо подставляет строку в нужное место. и не будет. препроцессор не знает ничего ни об языке С, ни о формате файлов, которые он обрабатывает; его единственная задача - разворачивать макросы в строки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 18 16 апреля, 2008 Опубликовано 16 апреля, 2008 · Жалоба Мне тут ещё в голову пришло... Всегда думал : по кой в дефайнах скобочки ставить? А вот ведь... наглядный пример! #define CLOCKS (QUARTZ/1000000UL) вроде то же самое, а на самом деле - одним глюком меньше Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться