Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Ошибка в AVR Studio4
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Wild007
Подскажите пожалуйста!!! Уже час не могу создать MACRO.
Привожу отрывок:
. . . .
.EQU TTT=4100/1000000
LDI r17,0x100-(TTT*20000000/1024)
. . . . .
выдает "error: Operand(s) out of range in 'ldi r17,0x100'"
Считаю на калькуляторе -- значение в скобках =0x50.
В чем проблема? (цифры приведены так как они передаются в MACROS по параметрам и просьба их не обсуждать)
TriD
HEX обозначается как $100
arttab
Цитата
4100/1000000


Равно 0, а не 0,0041. и ругается он скорее на такую операцию.
попробуйте так:
.EQU TTT=4100
LDI r17,0x100-(TTT*20/1024)
для ТТТ <= 5120
Wild007
Цитата(TriD @ Oct 30 2006, 11:08) *
HEX обозначается как $100

Не имеет значения Studio понимает любой вариант
Wild007
конструкция:
.EQU TTT=0.0041
LDI r17,$100-(TTT*20000000/1024);
выдает ошибку
а конструкция:
LDI r17,$100-(0.0041*20000000/1024);
нет
20000000 -- частота кварца
4100 -- время в мкс
передаются как параметры и не хотелось их менять, т.к. они уже мспользуются в других местах
arttab
а мой вариант?
Wild007
Цитата(arttab @ Oct 30 2006, 11:12) *
Цитата
4100/1000000


Равно 0, а не 0,0041. и ругается он скорее на такую операцию.
попробуйте так:
.EQU TTT=4100
LDI r17,0x100-(TTT*20/1024)
для ТТТ <= 5120


Работает, но, как я писал 20000000 это параметр ккоторый не хотелось бы менять
arttab
.EQU TTT=0.0041*20000000
LDI r17,0x100-(TTT/1024)
так устроит?
Похоже на ограничение студии
Wild007
Цитата(arttab @ Oct 30 2006, 11:41) *
.EQU TTT=0.0041*20000000
LDI r17,0x100-(TTT/1024)
так устроит?
Похоже на ограничение студии


Да. так работает (проверил со строкой в MACROSe) большое спасибо. Но конечно странное ограничение. Интересно с какого значения оно проявляется? Найду время -- проверю.
arttab
Думаю что с <1
GinRider
Думаю, что компилятор автоматически использует INT, если его принудительно не пнуть, как во втором примере. Должен быть какой-то идентификатор, чтобы подсказать тип константы. Сталкивался с подобным на старых компиляторах для x51.
Yura_K
Если использовать ассемблер первой версии (avrasm), то константы в директивах 32 бита целые, а если второй (avrasm2), то 64 бита с плавающей точкой. Из справки к AVR Studio:
Код
The Assembler incorporates constant expressions. Expressions can consist of operands, operators and functions. All expressions are internally 32 bits in AVRASM, and 64 bits in AVRASM2.
Operands
The following operands can be used:
User defined labels which are given the value of the location counter at the place they appear.
User defined variables defined by the SET directive
User defined constants defined by the EQU directive
Integer constants: constants can be given in several formats, including
Decimal (default): 10, 255
Hexadecimal (two notations): 0x0a, $0a, 0xff, $ff
Binary: 0b00001010, 0b11111111
Octal (leading zero): 010, 077
PC - the current value of the Program memory location counter
Floating point constants - AVRASM2 only.
Wild007
Цитата(GinRider @ Oct 30 2006, 14:47) *
Думаю, что компилятор автоматически использует INT, если его принудительно не пнуть, как во втором примере. Должен быть какой-то идентификатор, чтобы подсказать тип константы. Сталкивался с подобным на старых компиляторах для x51.

Но, ИМХО, значение в формуле 0x100-(TTT*20000000/1024) должен вычислять препроцессор, т.к. в ней используется различное представления чисел?
Andreas1
У меня не получалось назначить через .EQU нецелое, поэтому пользуюсь
#define - именно здесь можно использовать вещественные числа
Wild007
Решил проверить коректность работы компилятора, создал такую последователность команд:

.EQU A=4100
.EQU B=1000000
.EQU C=20000000
.EQU D=1024

LDI R18,low($100-(A/B*C/D));
LDI R19,high($100-(A/B*C/D))
;в результате R18=0x00 R19=0x01

LDI R18,low($100-(C/D*A/B));
LDI R19,high($100-(C/D*A/B))
;в результате R18=0xB0 R19=0x00 этот результат соответствует вычислению "в столбик" и можно заменить на строку
LDI R18,$100-(C/D*A/B);
без вылета в ERROR

LDI R18,low($100-((A/B)*(C/D)));
LDI R19,high($100-((A/B)*(C/D)))
;в результате R18=0x00 R19=0x01

LDI R18,low($100-((C/D)*(A/B)));
LDI R19,high($100-((C/D)*(A/B)))
;в результате R18=0x00 R19=0x01

Почему 2*3=6,а 3*2=5 sad.gif ?????????????????
Механизм получения правильного результата мне пока не ясен, может кто объяснит юзьверю smile.gif ?
xemul
Выражение
Цитата
(A/B*C/D)

вычисляется препроцессором слева направо как целочисленное, и с указанными значениями
A/B = 0 без вариантов.
К сожалению, Вам придется самому следить за переполнением и потерей точности в таких выражениях.
Выражение (A*С/B/D) не приведет ни к потере точности, ни к переполнению.

Занятно:
Код
.EQU A=4100.0
.EQU B=1000000
.EQU C=20000000
.EQU D=1024

    LDI R18,low($100-INT(4100.0/B*C/D))
    LDI R19,high($100-INT(A/B*C/D))

в R18 получим 0xb0 - правильно, а в R19 0x01 - неправильно.
Таки косячок имеется.
Gennadiy_
Я писал так:

Код
.equ    quant=(CK/64)/256
.equ    Hquant=(CK/256)*60*60
.equ    Mquant=(CK/256)*60
.equ    Squant=(CK/256)
;Время   =((((((часы*60)+минуты)*60)+секунды)*CK)/64)/256
;максимальное время 19ч 5мин 19 сек <<=  считает с ошибкой


.set    hour    =3
.set    min    =0
.set    sec    =0
.equ    1_Time    =((hour*Hquant)+(min*Mquant)+(sec*Squant))/64

.set    hour    =0
.set    min    =20
.set    sec    =0
.equ    2_Time    =((hour*Hquant)+(min*Mquant)+(sec*Squant))/64


И параметры вычислялись с ошибкой, но поскольку это только время нахождения в разных режимах, некритичное, я забил на это.
Wild007
Даа, проверять, проверять и еще раз проврять... (сказал отладчик smile.gif ).
Может письмо Atmely наскрябать, чтобы препроцесор апгрейдил? Ведь при вычислении формулы РС безразлично в коком виде представлены числа, а при подстановке в реал можно ограничиваться и целочисленными значениями. Или добваить директиву препроцесора.
IgorKossak
Цитата(xemul @ Oct 31 2006, 17:11) *
Выражение
Цитата
(A/B*C/D)

вычисляется препроцессором слева направо как целочисленное, и с указанными значениями
A/B = 0 без вариантов.
К сожалению, Вам придется самому следить за переполнением и потерей точности в таких выражениях.
Выражение (A*С/B/D) не приведет ни к потере точности, ни к переполнению.

Занятно:
Код
.EQU A=4100.0
.EQU B=1000000
.EQU C=20000000
.EQU D=1024

    LDI R18,low($100-INT(4100.0/B*C/D))
    LDI R19,high($100-INT(A/B*C/D))

в R18 получим 0xb0 - правильно, а в R19 0x01 - неправильно.
Таки косячок имеется.

А если так сделать?
Код
.EQU A=4100.0
.EQU B=1000000.0
.EQU C=20000000.0
.EQU D=1024.0

    LDI R18,low($100-INT(4100.0/B*C/D))
    LDI R19,high($100-INT(A/B*C/D))
Wild007
Проверил в Студии:

.EQU A=4100.0
.EQU B=1000000.0
.EQU C=20000000.0
.EQU D=1024.0
LDI R18,low($100-int(A/B*C/D));
LDI R19,high($100-int(A/B*C/D))
;R18=0x00 R19=0x01 -- это не правильно

LDI R18,low($100-(C/D*A/B));
LDI R19,high($100-(C/D*A/B))
;R18=0xB0 R19=0x00 -- это правильно
Andreas1
А чем не нравится так
#define A 4100.0
#define B 1000000.0
#define C 20000000.0
#define D 1024.0
LDI R18,low($100-int(A/B*C/D));
LDI R19,high($100-int(A/B*C/D))

В отладчике получается
;R18=0xB0 R19=0x00
Wild007
Цитата(Andreas1 @ Nov 1 2006, 12:06) *
А чем не нравится так
#define A 4100.0
#define B 1000000.0
#define C 20000000.0
#define D 1024.0
LDI R18,low($100-int(A/B*C/D));
LDI R19,high($100-int(A/B*C/D))

В отладчике получается
;R18=0xB0 R19=0x00


Это все хорошо, но А,C и D это параметры которые передаются в MACROS, а EQU здесь применено для упрощения.
Andreas1
Цитата
Это все хорошо, но А,C и D это параметры которые передаются в MACROS, а EQU здесь применено для упрощения.

Не понял.
.EQU задает только целые
#define можно задать целые и дробные
умножение и деление дает тип результата по операндам.
Или проблема в том, что в макрос не передается вещественное??
Wild007
.MACRO DELAYMKS ;
.....
LDI R18,$100-(@0/1000000*@1/@2)
.......
.ENDM

в теле основной программы:

.EQU F_cry=20000000
.....
DELAYMKS 4100,F_cry,1024
......

примерно так.
Andreas1
Ну тогда так

.MACRO DELAYMKS ;
.....
LDI R18,$100-INT(@0/1000000*@1/@2)
.......
.ENDM

в теле основной программы:

#define F_cry 20000000.0
.....
DELAYMKS 4100.0,F_cry,1024.0

Если работает, поробовать убрать .0 в вызове
xemul
Цитата(IgorKossak @ Nov 1 2006, 11:20) *
Цитата(xemul @ Oct 31 2006, 17:11) *

Выражение
Цитата
(A/B*C/D)

вычисляется препроцессором слева направо как целочисленное, и с указанными значениями
A/B = 0 без вариантов.
К сожалению, Вам придется самому следить за переполнением и потерей точности в таких выражениях.
Выражение (A*С/B/D) не приведет ни к потере точности, ни к переполнению.

Занятно:
Код
.EQU A=4100.0
.EQU B=1000000
.EQU C=20000000
.EQU D=1024

    LDI R18,low($100-INT(4100.0/B*C/D))
    LDI R19,high($100-INT(A/B*C/D))

в R18 получим 0xb0 - правильно, а в R19 0x01 - неправильно.
Таки косячок имеется.

А если так сделать?
Код
.EQU A=4100.0
.EQU B=1000000.0
.EQU C=20000000.0
.EQU D=1024.0

    LDI R18,low($100-INT(4100.0/B*C/D))
    LDI R19,high($100-INT(A/B*C/D))


Не, это я протормозилsmile.gif. Как уже указал Andreas1, вещественные константы можно определить только через #define.
Более занятно, что при
Код
#define A 4100
#define B 1000000.0
#define C 20000000
#define D 1024

INT(A/B*C/D) = 0x50
а при
Код
#define A 4100
#define B 1000000
#define C 20000000.0
#define D 1024

INT(A/B*C/D) = 0x00
Т.е. похоже, что тип результата препроцессор полагает целым, и только когда уткнется в вещественное число, конвертит текущий результат в вещественный формат. Неаккуратненькоsad.gif.
Wild007
.MACRO DELAYMKS ;
.....
LDI R18,$100-INT(@0/1000000*@1/@2)
.......
.ENDM

в теле основной программы:

#define F_cry 20000000.0
.....
DELAYMKS 4100.0,F_cry,1024.0

Выдает ошибку

.MACRO DELAYMKS ;
.....
LDI R18,$100-INT(@0/MIL*@1/@2)
.......
.ENDM

в теле основной программы:

#define MIL 1000000.0
.....
DELAYMKS 4100.0,F_cry,1024.0
работает правильно, даже если
.EQU F_CRY=20000000

Получается для коректной работы и уменьшения времени на отладку надо все заранее объявлять ВСЕ константы через #define
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.