c - 带有 float 的 C 中 AVR 上 printf() 的问题

标签 c

我一直在重新学习 C,并且我一直在进行“学术”练习,以再次磨练一些旧技能。我的项目围绕着生成正弦的相当简单的过程展开。我一开始只是在命令行(Fedora Core 20)上为 x86 编码,一切正常。然后我将代码迁移到 AVR,我开始学习很多。例如,如何将 UART 设置为标准输出。然而,由于正弦是浮点数,我在使用 printf 和 sprintf 时遇到了问题。

该程序生成 30 个正弦,然后将这些值打印到终端。文本“正弦:”打印正确,但随后我得到了浮点数的问号。用常量替换变量没有效果。

我被建议的第一件事是我是否记得完整浮点支持的链接器选项 - 实际上我已经忘记了。同样,将它添加到我的 makefile 中没有任何效果。

我不确定这里复制和粘贴代码的政策:我应该将它和我的 makefile 粘贴在这里以供检查吗?

编辑:很抱歉耽搁了很长时间。我做了更多阅读,包括第一个答案链接到的内容。我之前已经阅读过该引用文献(GNU 引用文献)并且我在我的 Makefile 中包含了该链接,这就是我如此困惑的原因。这是我所有荣耀的 Makefile:

P               = sines
OBJ             = sines.o
PROGRAMMER      = buspirate
PORT            = /dev/ttyUSB0
MCU_TARGET      = atmega328p
AVRDUDE_TARGET  = atmega328p
HZ              = 16000000
DEFS            =
LIBS            = -lprintf_flt -lm
CC              = avr-gcc

override CFLAGS = -g -DF_CPU=$(HZ) -Wall -O1 -mmcu=$(MCU_TARGET) $(DEFS)
override LDFLAGS= -Wl,-Map,$(P).map -u,vfprintf

OBJCOPY     = avr-objcopy
OBJDUMP     = avr-objdump

all: $(P).elf lst text

$(P).elf: $(OBJ)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)

clean:
    rm -rf *.hex *.bin *.map *~ sine*.csv *.o $(P).elf *.lst

lst: $(P).lst

%.lst: %.elf
    $(OBJDUMP) -h -S $< > $@

text: hex bin

hex: $(P).hex
bin: $(P).bin

%.hex: %.elf
    $(OBJCOPY) -j .text -j .data -O ihex $< $@

%.bin: %.elf
    $(OBJCOPY) -j .text -j .data -O binary $< $@

install:  $(P).hex
    avrdude -p $(AVRDUDE_TARGET) -c $(PROGRAMMER) -P $(PORT) -v -U flash:w:$(P).hex 

我担心的是链接器参数的顺序可能不正确?据我所知,他们只是……

我相当确定我的代码本身没问题。如果需要,我也可以在这里发布。
另外,感谢您将我的问题转移到这里。不太明白两者的区别!

这是源代码。它在 ATmega328P 上运行。这个当前版本正在打印一个常量作为调试,而不是 sinescalc() 的结果,即使我知道该函数正在工作(至少应该是,我很确定我曾经使用 avr-gdb 检查过) -- 它绝对适用于命令行,也适用于 MSP430)。
#include <avr/io.h>
//#include <util/delay.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>


static int uart_putchar(char c, FILE *stream);

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

static int uart_putchar(char c, FILE *stream) {
    if (c == '\n')
        uart_putchar('\r', stream);
    while(!(UCSR0A & (1<<UDRE0)));
    UDR0 = c;
    return 0;
}

void sinescalc(double *sinptr, int cycles, int size) {

    double pi = acos(-1);
    double step = ((pi * (cycles*2))/ size);

    float temp;
    double z = step;

    int y;
    for(y = 0; y<= size; y++) {
        temp = sin(z); // calculate the current sine
        *sinptr = (double)temp; // pass it into the array from main()
        z += step; // add the step value to prepare for next sine
        sinptr++; // should move the pointer by correct size of variable
    }
}

int main(void) {

    unsigned long _fosc = 16000000;
    unsigned int _baud = 19200;
    unsigned long _myubrr = _fosc/16/_baud-1;
    unsigned int array_size = 256;

    UBRR0L = (unsigned char)_myubrr;
    UCSR0B = (1<<RXEN0)|(1<<TXEN0); //enable receiver and transmitter

    stdout = &mystdout;
    double sines[array_size];
    double *sinepointer = sines; // set sinepointer to first element of sines array

    sinescalc(sinepointer, 2, array_size); // calculate two cycles of sine, with 255 data points

    int y;
    //char msg[6] = ("Sine: ");
    char output[40];

    for(y = 0; y <= array_size; y++) {
        sprintf(output, "Sine:\t %.6f", 1.354462);
        printf(output);
        printf("\n");
    }



    return 0;
}

最佳答案

This page指出要获得完整的 printf()支持打印浮点数的实现,您应该使用:

-Wl,-u,vfprintf -lprintf_flt -lm

关于c - 带有 float 的 C 中 AVR 上 printf() 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26339573/

相关文章:

c - 是否有 1.8.1 版的 svn C API 示例?

.net - 从使用 .NET 代码的 C++/CLI DLL 导出 C 函数

c - 链式哈希表的问题

C memcpy 错误 - 在 Windows XP 上无法写入内存

c++ - 我可以使用 i++ 语法将 int i 增加一个以上吗?

c - 综合C配置文件

c - 为什么bind(socket binding)方法会在当前目录生成一个文件?

c - POSIX C API 中的随机数

php - 集合中所有可能的组合

c++ - 在 C++ 中的指针数组中,内存过度使用是否会导致指针存储在非连续的内存块中?