Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не могу преобразовать double в строку
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Sminder
Возникла такая проблема: для вывода на индикатор требуется строчная переменная (*char) вида
Х.ХХХ, а имеется полученная в результате вычислений переменная типа double (т.е. с плавающей запятой). Как я понял, в компиляторе WinAVR не имеется встроенных средств для преобразования чисел с плавающей запятой в строку. Пожалуйста, дайте ссылку или приведите пример такого преобразования.
beer_warrior
ftoa() по-моему нет, но ИМХО она не предусмотрена стандартом.
А чем не подходит (s)printf() ?
vooon
просмотрите stdlib.h внимательно,
я там например нашел ф-цию
extern char *dtostrf(double __val, char __width, char __prec, char *__s);


(правда это из 20070122, использую некоторые хедеры оттуда в CV...)
Sminder
Цитата(vooon @ Mar 9 2007, 00:59) *
просмотрите stdlib.h внимательно,
я там например нашел ф-цию
extern char *dtostrf(double __val, char __width, char __prec, char *__s);


Спасибо. Действительно, проглядел))

Однако, при использовании этой функции возникают некоторые проблемы. При создании пустого проекта с подключением <stdlib.h> и использовании функции dtostrf() никаких проблем не возникает. Но при использовании в готовом проекте перестает создаваться файл MyProj.elf, а следовательно и MyProj.hex и появляются ошибки:

- окно Build:

avr-gcc.exe -mmcu=atmega8 MyProj.o -o MyProj.elf
c:/program files/avr/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr4\libc.a(fixsfsi.o): In function `__fixunssfsi':
(.text.fplib+0x0): multiple definition of `__fixsfsi'
c:/program files/avr/winavr/bin/../lib/gcc/avr/4.1.1/avr4\libgcc.a(_sf_to_si.o):(.text+0x0): first defined here
c:/program files/avr/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr4\libc.a(fixsfsi.o): In function `__fixunssfsi':
(.text.fplib+0x0): multiple definition of `__fixunssfsi'
c:/program files/avr/winavr/bin/../lib/gcc/avr/4.1.1/avr4\libgcc.a(_fixunssfsi.o):(.text+0x0): first defined here
make: *** [MyProj.elf] Error 1

- окно Message:

gcc plug-in: Error: Object file not found on expected location Disk:\path\MyProj\default\MyProj.elf

Наличие этих ошибок связано непосредственно с включением функции dtostrf().
beer_warrior
Похоже на двойное включение одной и той же библиотеки в процесс линковки. Проверьте makefile и прочие установки проекта. Под студией работаете?
Sminder
Цитата(beer_warrior @ Mar 11 2007, 15:23) *
Похоже на двойное включение одной и той же библиотеки в процесс линковки. Проверьте makefile и прочие установки проекта. Под студией работаете?


Сообщения действительно говорят о множественном обьявлении функций. В стуктуре makefile я не очень разбираюсь, но содержимое файла до и после появления ошибки ничем не отличается. До использования функции dtostrf() никаких проблем не возникало, поэтому я думаю, что с установками все нормально. Использую AVR Studio 4.13 (релиз) + WinAVR за 2007 год.
У меня возникло чувство, что я неправильно вызываю функцию.
Функция объявлена в файле stdlib.h следующим образом:

extern char *dtostrf(double __val, char __width, char __prec, char *__s);

Откуда она импортируется, мне не очень понятно. Поэтому вызов я строил следующим образом:

dtostrf (MyFloatNumber, 16, 3, MyStringPointer);

Если это неправильно, подскажите пожалуйста, как оформить правильно вызов функций, обьявленных как extern.
aesok
makefile ваш, или тот что AVRStudio генерирует автоматом?

Анатолий.
beer_warrior
Цитата
Сообщения действительно говорят о множественном обьявлении функций.

Не о множественном объявлении (тогда ругнулось бы со словом declared), а о множественном линковании.

Цитата
c:/program files/avr/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr4\libc.a(fixsfsi.o): In function `__fixunssfsi':(.text.fplib+0x0): multiple definition of `__fixsfsi'c:/program files/avr/winavr/bin/../lib/gcc/avr/4.1.1/avr4\libgcc.a(_sf_to_si.o)sad.gif.text+0x0): first defined here

В первый раз - libc.a, во второй libgcc.a. Тут надо смотреть, как именно подключаются библиотеки. С winavr на такое не нарывался, поэтому в глубину не копал. А вот с MinGW многократно - именно из-за дублирующего использования библиотек.

Могу посоветовать скомпилировать просто в командной строке - если получится - искать грабли в мэйкфайле.
Sminder
Пардон, оговорился, я имел в виду конечно определение.

Makefile используется тот, что автоматически генерит Studio.

Для компиляции в командной строке требуется все равно файл makefile. Созданный оболочкой Studio файл не подходит, а с файлом, созданным с помощью программы MFile от WinAVR, проект не компилится (любой проект, не только этот - проверял) с ошибкой

> "make.exe" all
Makefile:531: *** target pattern contains no `%'. Stop.


В самом файле текст


# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
@echo
@echo $(MSG_CREATING_LIBRARY) $@
$(AR) $@ $(OBJ)


на который указывает ошибка, на мой взгляд никаких подозрений не вызывает.

Файл makefile, созданный Studio, реально в 10 раз меньше по размеру MFile -овского.
Короче, одна беда) Уже и не знаю, чего делать...
beer_warrior
Ну что тут можно сказать. Оба мэйкфайла к осмотру.
А скомпилить можно и без них типа
Цитата
avr-gcc -c -mmcu=atmega162 -Os -std=c99 main.c -o main.o

А потом слинковать.
Цитата
avr-gcc -mmcu=atmega162 -adhlns=main.o -std=c99 -main.o --output main.elf -lm

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


И еще - я не зря спросил про студию - в ней путь к либам, может быть указан дважды.Типа в системных установках и установках проекта (Точно не знаю, секс со старыми версиями в корне отбил желание работать с этой связкой)
aesok
Цитата(Sminder @ Mar 13 2007, 22:35) *
Makefile используется тот, что автоматически генерит Studio.


Для того чтобы избежать ошибки нужно подлинковать баблиотеку libm.lib. Для этого линкеру нужно добавить ключик -lm, но желательно в конец командной строки.

Давайте попробуем обмануть AVRStudio.

1. В директории вашего проекта создайте файл с именем libm.lib, с любым содержимым.
2. В AVRStudio меню Project/Configuration Option/Libraries жмете кнопку 'Add Object' и выбираете файл 'libm.lib'. Open ... Ok итд итп...
3. удалите файл libm.lib.
4. Попробуйте пересобрать проект. Clean, Rebuld All.

Для контроля:
в makefile должны появиться строки:
## Libraries
LIBS = -lm

и при создании проекта в командной строке линкера должна быть опция -lm:
avr-gcc -mmcu=atmega162 -main.o --output main.elf -lm


У меня сейчас нет WinAVR так что я не могу проверить. Если не заработает пишите будем думать.

Анатолий.
beer_warrior
2 aesok
Анатолий, там ИМХО проблема с libc/libgcc. К сожалению слабо представляю как они коррелируют между собой, но libm здесь ИМХО непричем. В этом случае ругнулось бы на undefined function.

Тут два варианта - либо это очередная кривизна winavr2007, либо IDE подсовывает либу линкеру дважды. Исключить второе поможет билд из командной строки. Если при этом линкер заругается опять, то тогда откатыватся на старую версию (2006). Я так понял, вы ей активно пользуетесь, она надежна и очищена от старья?
aesok
Цитата(beer_warrior @ Mar 14 2007, 01:08) *
2 aesok
Анатолий, там ИМХО проблема с libc/libgcc. К сожалению слабо представляю как они коррелируют между собой, но libm здесь ИМХО непричем. В этом случае ругнулось бы на undefined function.

Тут два варианта - либо это очередная кривизна winavr2007, либо IDE подсовывает либу линкеру дважды. Исключить второе поможет билд из командной строки. Если при этом линкер заругается опять, то тогда откатыватся на старую версию (2006). Я так понял, вы ей активно пользуетесь, она надежна и очищена от старья?


Дело в том что в GCC две версии библиотеки для чисел с плавающей точкой (я говорю только про сложение, вычитание, ..., сравнение, преобразование типов). Одна находиться в стандартной библиотеке компилятора в libgcc.а. Недостаток этой версии в том что эти функции написаны на C, и имеют большой размер кода и время выполнения. Но GCC должен иметь эти функции в стандартной библиотеке. float - это стандартный 'С' тип, и компилятор должен всегда быть готовым сгенерировать код для умножения двух float переменных.

Есть еще один набор тех же самых функций, но написанных на ассемблере, тоесть оптимизированных по скорости и размеру. Эти функции находятся в avr-libc, а физически в библиотеке libm.a. Для того чтобы использовались оптимизированные функции и нужно прилинковать библиотеку libm.a с помощью опции линкера -lm. (кстати в вашем примере этот ключ есть).

Код
avr-gcc -mmcu=atmega162 -adhlns=main.o -std=c99 -main.o --output main.elf [b]-lm[/b]


У Sminder-а возникла следующая проблема: он собирает проект без опции -lm и некоторые модули функцию `__fixsfsi' из libgcc.а. Что эта версия функции не эффективна это только пол проблемы. А основная проблема в том что 'dtostrf' функция из avr-libc и использует `__fixsfsi' из libm.a. Ну и компоновщик не может добавить в проект две функции с одним именем.

К сожалению я не понял как в AVRStudio как по-человечески добавить libm, и поэтому предложил такой способ.

Анатолий.

PS: Мое мнение такое: если у вас меньше 64 кб кода то торопиться переходить на winavr2007 смысла нет.
beer_warrior
Цитата
У Sminder-а возникла следующая проблема: он собирает проект без опции -lm и некоторые модули функцию `__fixsfsi' из libgcc.а. Что эта версия функции не эффективна это только пол проблемы. А основная проблема в том что 'dtostrf' функция из avr-libc и использует `__fixsfsi' из libm.a. Ну и компоновщик не может добавить в проект две функции с одним именем.К сожалению я не понял как в AVRStudio как по-человечески добавить libm, и поэтому предложил такой способ.


Посмотрите внимательно на ошибки - libm там не упоминается.
Если бы она отсутствовала, линкер бы ругнулся на ненайденное имя.
Вот убрал из мэйкфала -lm:
Цитата
Linking: main.elf
C:/_tools/gcc_avr/bin/avr-gcc -mmcu=atmega162 -I. -gstabs - -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=c99 -MD -MP -MF .dep/main.elf.d main.o --output main.elf -Wl,-Map=main.map,--cref

main.o(.text+0x28): In function `main':
: undefined reference to `dtostrf'


В данном случае имеется дубль.
Я очень слабо верю, что в стандартном компиляторе можно иметь одинаковое имя функции, в двух разных либах, которые могут линковаться в один проект. Слишком очевидный баг.


Цитата
Мое мнение такое: если у вас меньше 64 кб кода то торопиться переходить на winavr2007 смысла нет.


Судя по тому, как Йорг и Эрик отбиваются от вопросов на avrfreaks, еще долго не захочется переходить.
Я интересуюсь сборкой 2006. (сам работаю под 2005)
neonix
На данный момент WinAVR 2007 не пригоден для использования , вот допустим у меня он выдавал постоянно ошибку если в еепром ничего не писать + у него был глюк с размером кода (код всегда был толще байт на 30) , и ко всему были проблемы с компиляцие некоторых сторонних библиотек. Поэтому я вернул WinAVR 2005 , но вскоре сменил его на более новую версию winAVR 2006 - пока доволен , ошибок незамечал.
aesok
WinAVR 2006.

Код:
Код
#include <stdlib.h>

volatile float MyFloatNumber;
volatile int MyInt;

int
main (void)
{
    MyInt = MyFloatNumber;

    dtostrf (MyFloatNumber, 16, 3, 0);

    return (0);
}


При компиляции без -lm:
Код
avr-gcc -g -Wall -O2 -mmcu=atmega8  -Wl,-Map,demo.map -lm -o demo.elf demo.o
C:/WinAVR/bin/../lib/gcc/avr/3.4.6/../../../../avr/lib/avr4\libc.a(fixsfsi.o): I
n function `__fixunssfsi':
: multiple definition of `__fixsfsi'
C:/WinAVR/lib/gcc/avr/3.4.6/avr4\libgcc.a(_sf_to_si.o):: first defined here
make: *** [demo.elf] Error 1


При компиляции с -lm:
Код
avr-gcc -g -Wall -O2 -mmcu=atmega8  -Wl,-Map,demo.map  -o demo.elf demo.o -lm
avr-objdump -h -S demo.elf > demo.lst
avr-objcopy -j .text -j .data -O ihex demo.elf demo.hex
avr-objcopy -j .text -j .data -O binary demo.elf demo.bin
avr-objcopy -j .text -j .data -O srec demo.elf demo.srec
....


Анатолий.
aesok
Цитата(beer_warrior @ Mar 14 2007, 03:09) *
Посмотрите внимательно на ошибки - libm там не упоминается.
Если бы она отсутствовала, линкер бы ругнулся на ненайденное имя.
Вот убрал из мэйкфала -lm:

К сожалению я не могу коментировать WinAVR-2005, про 2006 я уже написал проблема решаеться добавлением библиотеки libm при компоновке (опция -lm в [/b]конце[b] командной строки).

Цитата
В данном случае имеется дубль.
Я очень слабо верю, что в стандартном компиляторе можно иметь одинаковое имя функции, в двух разных либах, которые могут линковаться в один проект. Слишком очевидный баг.

Никакого бага нет. Есть правила включения обектов при компоновке. Выший приоритет имеют обекты из библиотеки и обектных файлов расположенных в конце командной строки при вызове линкера. Cамый низший приоритет из стандартных библиотек.

Цитата
Судя по тому, как Йорг и Эрик отбиваются от вопросов на avrfreaks, еще долго не захочется переходить.

Я интересуюсь сборкой 2006. (сам работаю под 2005)

Эрик обещал в апреле новый релиз WinAVR, но можете спокойно добавить месяц. wink.gif

WinAVR-20060421 стабильный, сильно ни кто не ругает. Наверное привыкли. wink.gif
Но выбор вседа за вами.

Анатолий.
Sminder
Огромное спасибо aesok, ваш совет действительно помог. После включения -lm проект стал линковаться без упомянутых ошибок. Правда, добавляется данный ключ не в конец строки, а в середину

Код
avr-gcc.exe -mmcu=atmega8  MyProj2.o    -lm  -o MyProj.elf

Еще в окне Libraries меню Project Options есть список Available Link Objects, в нем уже присутствует библиотека libm.a. Добавление ее вместо "обмана" AVR Studio имеет такой же эффект - линковка происходит нормально.

Насчет перехода на WinAVR2007 - раньше я пользовался версией 2005, довольно долго и успешно. По некоторым причинам пришлось перейти на версию 2006 года. С ней у меня появилось масса проблем - об этом я открывал отдельную тему на форуме Зависает AVR Studio 4. Вкратце: зависание проектов при компиляции. Мне так и не удалось добиться нормальной работы данной версии, поэтому по советам участников форума я и перешел на версию 2007.

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