Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вывод с помощью fprintf в WinAVR
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
smk
Мне нужно выводить строчку в виде "F = 0.0000 Hz". При этом число дожно иметь три вида в зависимости от значения частоты: 1) 0.0000; 2) 00.000; 3) 000.00 . Как правильно это сделать используя библиотечные функции форматированного вывода? Спасибо.
ReAl
В стандартном С это делаетcя так (ширина поля и точность могут задаваться аргументом, тогда в формате * вместо числа):
Код
#include <stdio.h>
void pr(int digits, float value)
{
        printf("%6.*f\n", digits, value);
}

int main()
{
        pr(4, 1.2345f);
        pr(3, 12.345f);
        pr(2, 123.45f);
}
Из-под avr-gcc сейчас некуда залить для на терминлку выдать, но должно работать в максимальном форматтере (а с float всё равно только максимальный и нужен).
Так что можно нагородить что-то в духе
Код
        printf("F = %6.*f Hz\n", value < 10 ? 4 : value < 100 ? 3 : 2, value);
smk
Не получается. Нужно как-то иначе. Или прийдется писать свою процедуру вывода.
skripach
printf("F = %06f Hz\n", value); Не?
ReAl
Цитата(smk @ Jul 3 2011, 15:32) *
Не получается. Нужно как-то иначе. Или прийдется писать свою процедуру вывода.
Точно, не получается :-(
Таки не всё поддерживает, а жаль.
Ну тогда так
Код
    fprintf_P(fconsole
        , value < 10 ? PSTR("F = %6.4f Hz\n") : value < 100 ? PSTR("F = %6.3f Hz\n") : PSTR("F = %6.2f Hz\n")
        , value);
Так как миленькое работает, просто гробовато выглядит.
sergeeff
А в printf включена поддержка float?
Dnepr33
Цитата(smk @ Jul 1 2011, 19:20) *
Мне нужно выводить строчку в виде "F = 0.0000 Hz". При этом число дожно иметь три вида в зависимости от значения частоты: 1) 0.0000; 2) 00.000; 3) 000.00 . Как правильно это сделать используя библиотечные функции форматированного вывода? Спасибо.

не уверен за WinAVR - но по крайней мере в стандарте С можно извернуться так
1. использовать sprintf - пишем в память
2. из памяти выводим любым удобным способом - даже посимвольно, как из массива.
smk
Цитата(skripach @ Jul 3 2011, 17:08) *
printf("F = %06f Hz\n", value); Не?
Не.



Цитата(Dnepr33 @ Jul 3 2011, 21:46) *
не уверен за WinAVR - но по крайней мере в стандарте С можно извернуться так
1. использовать sprintf - пишем в память
2. из памяти выводим любым удобным способом - даже посимвольно, как из массива.
Ну где-то так оно и делается. fprintf не догма. можно и другую функцию, лишь бы выводить удобно было.


Цитата(sergeeff @ Jul 3 2011, 21:37) *
А в printf включена поддержка float?
А как узнать? Как я понял там аргумент double.


Цитата(ReAl @ Jul 3 2011, 20:06) *
Точно, не получается :-(
Таки не всё поддерживает, а жаль.
Ну тогда так
Код
    fprintf_P(fconsole
        , value < 10 ? PSTR("F = %6.4f Hz\n") : value < 100 ? PSTR("F = %6.3f Hz\n") : PSTR("F = %6.2f Hz\n")
        , value);
Так как миленькое работает, просто гробовато выглядит.

Значение не отображает. Знак вопроса выводит. Текст выводит правильно.

Вот собственно тестовый код, куда и надо вставить строчку с выводом:
Код
#define F_CPU 8000000UL // 16.0 MHz
#include <util/delay.h>
#include "defines.h"
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include "lcd.h"

volatile unsigned char q;
volatile unsigned int f=0xF;
volatile double frq;
double fp = 1;
FILE lcd_str = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);

ISR(TIMER0_OVF_vect)
{
++q;
if(q==1)
    {
    PORTA ^= (1<<7);
    q=0;
    }
}

int main(void)
{
DDRA  = 0b10000000;
PORTB = 0b00000000;
DDRB  = 0b10111111;
TCCR0A = 0b10000000;
TCCR0B = 0b00000110;
TIMSK  = 0b00000010;

frq=123;

lcd_init();
stderr = &lcd_str;


fprintf_P(stderr, PSTR("F = %6.4f Hz\n"), frq);

/*value < 10 ? PSTR("F = %6.4f Hz\n") : value < 100 ? PSTR("F = %6.3f Hz\n") : PSTR("F = %6.2f Hz\n")*/

asm("sei");

    while(1)
        {
        
        asm("nop");
        }

return 0;
}
ARV
Цитата(smk @ Jul 4 2011, 08:23) *
Значение не отображает. Знак вопроса выводит. Текст выводит правильно.
не включена поддержка float в fprintf. добавьте следующие параметры компилятору:

-Wl,-u,vfprintf -lprintf_flt -lm


smk
Цитата(ARV @ Jul 4 2011, 09:20) *
не включена поддержка float в fprintf. добавьте следующие параметры компилятору:

-Wl,-u,vfprintf -lprintf_flt -lm


Добавил, но не уверен что правильно. Можно подробнее? Как проверить получилось или нет? Спасибо.
sergeeff
Запустите примеры, которые вам коллеги советовали и увидите, работает или нет.
smk
Цитата(sergeeff @ Jul 4 2011, 11:56) *
Запустите примеры, которые вам коллеги советовали и увидите, работает или нет.

не работает. потому и подумал, что неправильно что-то сделал.
sergeeff
Цитата(smk @ Jul 4 2011, 13:00) *
не работает. потому и подумал, что неправильно что-то сделал.


Ну напишите в main для проверки:
Код
   float pi = 3.14f;
   printf("pi = %.02f\n", pi);

Должно печатать:
Код
pi = 3.14

demiurg_spb
Цитата(ReAl @ Jul 3 2011, 21:06) *
Точно, не получается :-(
Таки не всё поддерживает, а жаль.
Тоже давненько наткнулся на отсутствие обработки символа звёздочка в форматере printf'a в gcc.
А топикстартеру рекомендую обратить внимание на функцию
Код
dtostrf(f, WIDTH, PREC, buff)
таким образом можно выиграть по памяти не включая в проект толстую printf с поддержкой float.
smk
Цитата(sergeeff @ Jul 4 2011, 12:03) *
Ну напишите в main для проверки:
Код
   float pi = 3.14f;
   printf("pi = %.02f\n", pi);

Должно печатать:
Код
pi = 3.14

Вот такая ошибка:
Код
../exampl.c:44: warning: format '%.02f' expects type 'double', but argument 2 has type 'float'

В моем случае может следует вот так:
Код
  printf(stderr, "pi = %.02f\n", pi);


Цитата(demiurg_spb @ Jul 4 2011, 12:49) *
Тоже давненько наткнулся на отсутствие обработки символа звёздочка в форматере pfintf'a в gcc.
А топикстартеру рекомендую обратить внимание на функцию
Код
dtostrf(f, WIDTH, PREC, buff)
таким образом можно выиграть по памяти не включая в проект толстую printf с поддержкой float.

Обратил. Теперь пытаюсь понять как пользоваться.
demiurg_spb
Цитата(smk @ Jul 4 2011, 16:01) *
Теперь пытаюсь понять как пользоваться.

Да вроде всё тривиально.
Цитата
char* dtostrf (double __val, char __width, char __prec, char * __s)

The dtostrf() function converts the double value passed in val into an ASCII representationthat will be stored under s. The caller is responsible for providing sufficient storage in s. Conversion is done in the format '[-]d.ddd'. The minimum field width of the output string (including the '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign.

The dtostrf() function returns the pointer to the converted string s.
Разве нет?
smk
Чет не выходит. Наверно таки проще свою процедурку излабать.
demiurg_spb
Вольному - воля.
PS: если аргумент prec отрицательный то выравнивание по левому краю.
smk
я тут похоже с указателем напутал. вывод на дисплейчик происходит из
Код
FILE lcd_str = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);
stderr = &lcd_str;
dtostrf (frq, 3, 1, stderr);
наверно так не правильно.
ReAl
Цитата(demiurg_spb @ Jul 4 2011, 12:49) *
Тоже давненько наткнулся на отсутствие обработки символа звёздочка в форматере printf'a в gcc.
В avr-gcc. Так как в "большом" (lin/win) всё с этим нормально.
Для армов не проверял пока.


Цитата(smk @ Jul 4 2011, 23:15) *
наверно так не правильно.
Конечно неправильно. И в описании, и в прототипе функции явно видно, что нужно выводит в строку (символьный массив). А уже строку потом puts-ом в нужный поток.
smk
Цитата(ReAl @ Jul 5 2011, 02:15) *
Конечно неправильно. И в описании, и в прототипе функции явно видно, что нужно выводит в строку (символьный массив). А уже строку потом puts-ом в нужный поток.

Как правильно сделать не подскажите? Спасибо.
demiurg_spb
Код
FILE myout = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);
stderr  = &myout;
stdout = &myout;

char str[40];
dtostrf (frq, 3, 1, str);
puts(str); // или printf("F = %s Hz\n", str);
smk
Цитата(demiurg_spb @ Jul 5 2011, 09:52) *
Код
FILE myout = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);
stderr  = &myout;
stdout = &myout;

char str[40];
dtostrf (frq, 3, 1, str);
puts(str); // или printf("F = %s Hz\n", str);

как-то нужно из массива в строку мне кажется
demiurg_spb
Цитата(smk @ Jul 5 2011, 11:13) *
как-то нужно из массива в строку мне кажется

Не понял.
Я дал Вам рабочий вариант как мне думается.
В си массив и строка по сути одно и то же.

Я понял. Вам нужна хорошая книга по си. А то Вы тут строите какие-то догадки и предположения на пустом месте.
Извините я умываю руки.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.