本文介绍了带有AVR atmega8的C中的意外浮动行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图弄清楚为什么我无法通过将无符号int与浮点值相乘来获得有意义的值.

执行类似65535 * 0.1的操作符合预期,但是将浮点数与内存中的uint相乘会产生疯狂的值.我有一个读取ADC并返回uin16_t的函数.使用此值,我将其打印到一个4位数的led显示器上,该显示器工作正常.
将相同的值乘以1.0会得到完全不同的结果(对于我的显示器来说太大了,所以我真的不知道它是什么).

我的代码在下面,但争用区域在main()的底部.任何帮助将是巨大的.谢谢

main.c:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>
#define BAUD 9600
#include <util/setbaud.h>
#define DISP_BRIGHT_CMD     'z'
#define DISP_RESET          'v'

#define ADC_AVG            3

volatile uint8_t  lo;
volatile uint16_t result;

ISR(ADC_vect)
{
    lo = ADCL;
    hi = ADCH;
    MCUCR &= ~_BV(SE); //Clear enable sleep
}


void initSerial(void)
{
    // set baud rate
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
    // set frame format
    UCSR0C |= (0x3 << UCSZ00); // 8n1
    // set enable tx/rx
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);
}

void initADC(void)
{
    // AVCC and ADC0
    ADMUX   = _BV(REFS0);
    // Enable, div128, + 1st setup
    ADCSRA  |= _BV(ADEN)|_BV(ADSC)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0)|_BV(ADIE);
}

uint16_t readADC(void)
{
    uint16_t average=0;
    // Start Conversion
    ADCSRA |= _BV(ADSC);

    for (char i=0;i<ADC_AVG;i++) {
        MCUCR   |= _BV(SE);
        ADCSRA  |= _BV(ADSC);
        __asm volatile("sleep");
        MCUCR   &= ~_BV(SE);
        result  = (hi<<8);
        result  |= lo;
        average += result;
    }
    average /= ADC_AVG;
    return average;
}

void sendByte(char val)
{
    while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete
    UDR0 = val;
}

/*
 * Convert voltage to temperature based on a negative coefficient for MAX6613
 */
uint16_t analogToTemp(uint16_t val)
{
  uint16_t temp;
  //v     = 5 * (val/1023.0);
  //temp  = (1.8455 - (5.0*(val/1023.0)))/0.01123;
  temp  = (1.8455 - (5.0*(val/1023.0)))*89;
  //temp = val * M_PI;
  //v     = 5 * ( val/1024);
  //temp  = (2 - v) * 89;

  return temp;
}

void initDisplay()
{
    sendByte(DISP_RESET);
    sendByte(DISP_BRIGHT_CMD);
    sendByte(0);
}

void serialSegments(uint16_t val)
{
  // 4 digit display
  sendByte(val / 1000);
  sendByte((val / 100) % 10);
  sendByte((val / 10) % 10);
  sendByte(val % 10);
}

int main(void)
{
    uint16_t calc=0,sense=0;

    DDRB    |= _BV(DDB5);
    PORTB   |= _BV(PORTB5);
    initSerial();
    initADC();
    initDisplay();
    sei();
    MCUCR   |= (1 << SM0); // Setting sleep mode to "ADC Noise Reduction"
    MCUCR   |= (1 << SE);  // Sleep enable
    for(;;) {
        //PORTB   ^= _BV(PORTB5);
        if (calc>=9999){ // I can't see the real value. Max val on display is 9999
        //if (sense>=330){
            PORTB |= _BV(PORTB5);
        } else {
            PORTB &= ~_BV(PORTB5);
        }

        sense   = readADC();
        //calc    = sense*1.0;      // refuses to calculate properly
    calc    = analogToTemp(sense);  // a bunch of zeroes
        //calc = 65535*0.1;         // a-ok

        serialSegments(calc);
        _delay_ms(500);
        serialSegments(sense);
        _delay_ms(500);
    }
    return 0;
}

制作文件:

# AVR-GCC Makefile
PROJECT=Temp_Display
SOURCES=main.c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=atmega328p
OSC_HZ=16000000UL
OPTIMISATION=2
PORT=/dev/ttyUSB0

CFLAGS=-mmcu=${MMCU} -std=gnu99 -Wall -O${OPTIMISATION}  -DF_CPU=${OSC_HZ} -lm -lc

${PROJECT}.hex: ${PROJECT}.out
    ${OBJCOPY} -j .text -O ihex ${PROJECT}.out ${PROJECT}.hex
    avr-size ${PROJECT}.out

$(PROJECT).out: $(SOURCES)
    ${CC} ${CFLAGS} -I./ -o ${PROJECT}.out ${SOURCES}

program: ${PROJECT}.hex
    stty -F ${PORT} hupcl
    avrdude -V -F -c arduino -p m168 -b 57600 -P ${PORT} -U flash:w:${PROJECT}.hex

clean:
    rm -f ${PROJECT}.out
    rm -f ${PROJECT}.hex

好的,我已经简化了代码

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#define BAUD 9600
#include <util/setbaud.h>
#define DISP_BRIGHT_CMD     'z'
#define DISP_RESET          'v'


void initSerial(void)
{
    // set baud rate
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
    // set frame format
    UCSR0C |= (0x3 << UCSZ00); // 8n1
    // set enable tx/rx
    UCSR0B = _BV(TXEN0);
}


void sendByte(char val)
{
    while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete
    UDR0 = val;
}


void initDisplay()
{
    sendByte(DISP_RESET);
    sendByte(DISP_BRIGHT_CMD);
    sendByte(0);
}

void serialSegments(uint16_t val) {
  // 4 digit display
  sendByte(val / 1000);
  sendByte((val / 100) % 10);
  sendByte((val / 10) % 10);
  sendByte(val % 10);
}

int main(void)
{
    uint16_t i=0,val;

    DDRB    |= _BV(DDB5);
    initSerial();
    initDisplay();
    for(;;) {
        val = (uint16_t)(i++ * 1.5);
        serialSegments(i);
        _delay_ms(500);
        serialSegments(val);
        _delay_ms(500);
        if (val > 9999){
            PORTB |= _BV(PORTB5);
        } else {
            PORTB &= ~_BV(PORTB5);
        }
    }
    return 0;
}
解决方案

不完全是您的代码,也许足够接近,也许不是.

首先,当我显示输出并将它们与行进行比较时:

val = (unsigned int)(i++ * 1.5);
...
val = i+(i>>1); i++;

结果是一样的.拆卸也显示了一些东西.首先是avr-gcc

avr-gcc --version
avr-gcc (GCC) 4.3.4
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

use浮点数不会加倍,因此,关于1.5F与1.5的注释总体上是很有效的,但此处不相关.其次,它生成浮点值,单精度并进行浮点数学运算,编译器在那里没有捷径,而是转换为浮点,先进行乘法再转换回去.

使用我的十六进制显示例程和十进制显示例程(修改为在串行终端上输出),在这里再次产生相同的输出,浮点数学似乎不是问题.

我开始执行此任务,以查看浮点性能是否是杀手,,但实际上,时间的变化取决于我对其进行测试的方式.与固定点相比,带有浮点的代码要花费多达157倍的时间.如果我不留任何对serialSegments()的调用,但是让它调用一个虚拟例程而不是串行端口,则它的浮点速度要慢3倍.我还建立了两种不同的方式,并引入了使用一组不同的浮点例程的libc/m,C编译器选择的浮点例程比/usr/lib64中的libc/libm.a慢7倍./avr/lib/目录.一旦添加了串行端口等待时间和其他延迟,您可能就不会注意到时间上的差异,因此本实验在演示浮点很痛苦的同时,即使您的代码对时间敏感,也可能不是吸烟者,我们正在讨论一些毫秒.

除了下面的代码,我也尝试过这样做:

for(i = 0; i< 9999; i ++){ vala =(unsigned int)(i * 1.5); valb = i +(i >> 1); i ++; 如果(vala!= valb) { hexstring16(i); hexstring16(vala); hexstring16(valb); }}

没有失败.我限制为9999,因为serialSegments()仅将小数从0切成9999.现在您的循环超出了该范围,达到65535,但是您会发现虽然没有浮点数也会引起问题,对吧?

avr.c

#define UCSRA (*((volatile unsigned char *)(0xC0)))
#define UDR   (*((volatile unsigned char *)(0xC6)))
#define TCCR0A  (*((volatile unsigned char *)(0x44)))
#define TCCR0B  (*((volatile unsigned char *)(0x45)))
#define TCNT0   (*((volatile unsigned char *)(0x46)))

#define TCCR1A  (*((volatile unsigned char *)(0x80)))
#define TCCR1B  (*((volatile unsigned char *)(0x81)))
#define TCNT1L  (*((volatile unsigned char *)(0x84)))
#define TCNT1H  (*((volatile unsigned char *)(0x85)))

void dummy ( unsigned int );
void uart_putc ( unsigned char c )
{
    while(1) if(UCSRA&0x20) break;
    UDR=c;
}
void hexstring16 ( unsigned int d )
{
    unsigned int rb;
    unsigned int rc;

    rb=16;
    while(1)
    {
        rb-=4;
        rc=(d>>rb)&0xF;
        if(rc>9) rc+=0x37; else rc+=0x30;
        uart_putc(rc);
        if(rb==0) break;
    }
    uart_putc(0x0D);
    uart_putc(0x0A);
}

#ifdef SEGMENTS

void sendByte(char val)
{
    uart_putc(0x30+val);
}


void serialSegments(unsigned int val) {
  // 4 digit display
  dummy(val / 1000);
  dummy((val / 100) % 10);
  dummy((val / 10) % 10);
  dummy(val % 10);
}

//void serialSegments(unsigned int val) {
  //// 4 digit display
  //sendByte(val / 1000);
  //sendByte((val / 100) % 10);
  //sendByte((val / 10) % 10);
  //sendByte(val % 10);
  //uart_putc(0x0D);
  //uart_putc(0x0A);
//}



#else

void serialSegments(unsigned int val)
{
    dummy(val);
}

//void serialSegments(unsigned int val)
//{
    //hexstring(val);
//}


#endif

int main(void)
{
    unsigned int i,val;
    volatile unsigned int xal,xbl,xcl;
    volatile unsigned int xah,xbh,xch;

    hexstring16(0x1234);

    TCCR1A = 0x00;
    TCCR1B = 0x05;

    xal=TCNT1L;
    xah=TCNT1H;
    for(i=0;i<9999;)
    {
        val = (unsigned int)(i++ * 1.5);
        //serialSegments(val);
        //hexstring16(val);
        dummy(val);
    }
    xbl=TCNT1L;
    xbh=TCNT1H;
    for(i=0;i<9999;)
    {
        val = i+(i>>1); i++;
        //serialSegments(val);
        //hexstring16(val);
        dummy(val);
    }
    xcl=TCNT1L;
    xch=TCNT1H;
    xal|=xah<<8;
    xbl|=xbh<<8;
    xcl|=xch<<8;
    hexstring16(xal);
    hexstring16(xbl);
    hexstring16(xcl);
    hexstring16(xbl-xal);
    hexstring16(xcl-xbl);
    return 0;
}

dummy.s

.globl dummy
dummy:
    ret

vectors.s

.globl _start
_start:
    rjmp reset


reset:
    rcall main
1:
    rjmp 1b

.globl dummy
dummy:
    ret

Makefile

all : avrone.hex avrtwo.hex

avrone.hex : avr.c dummy.s
    avr-as dummy.s -o dummy.o
    avr-gcc avr.c dummy.o -o avrone.elf -mmcu=atmega328p -std=gnu99 -Wall -O2 -DSEGMENTS
    avr-objdump -D avrone.elf > avrone.list
    avr-objcopy avrone.elf -O ihex avrone.hex

a    vrtwo.hex : avr.c vectors.s
    avr-as vectors.s -o vectors.o
    avr-as dummy.s -o dummy.o
    avr-gcc -c avr.c -o avrtwo.o -mmcu=atmega328p -std=gnu99 -Wall -O2 -nostartfiles
    avr-ld vectors.o avrtwo.o -o avrtwo.elf  libc.a libm.a
    avr-objdump -D avrtwo.elf > avrtwo.list
    avr-objcopy avrtwo.elf -O ihex avrtwo.hex



clean :
    rm -f *.hex
    rm -f *.elf

所有这些都在arduino pro mini(atmega328p)上运行.

I've been trying to figure out why I cannot get a sensible value from multiplying an unsigned int with a float value.

Doing something like 65535*0.1 works as expected but multiplying a float with a uint from memory creates mad values. I have a function that reads an ADC and returns an uin16_t. With this value I am printing it to a 4-digit led-display, which is working fine.
Multiplying the same value with 1.0 returns something different entirely (it's too large for my display so I don't really know what it is).

My code is below but the area of contention is at the bottom in main(). Any help would be great. Thanks

main.c:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>
#define BAUD 9600
#include <util/setbaud.h>
#define DISP_BRIGHT_CMD     'z'
#define DISP_RESET          'v'

#define ADC_AVG            3

volatile uint8_t  hi,lo;
volatile uint16_t result;

ISR(ADC_vect)
{
    lo = ADCL;
    hi = ADCH;
    MCUCR &= ~_BV(SE); //Clear enable sleep
}


void initSerial(void)
{
    // set baud rate
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
    // set frame format
    UCSR0C |= (0x3 << UCSZ00); // 8n1
    // set enable tx/rx
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);
}

void initADC(void)
{
    // AVCC and ADC0
    ADMUX   = _BV(REFS0);
    // Enable, div128, + 1st setup
    ADCSRA  |= _BV(ADEN)|_BV(ADSC)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0)|_BV(ADIE);
}

uint16_t readADC(void)
{
    uint16_t average=0;
    // Start Conversion
    ADCSRA |= _BV(ADSC);

    for (char i=0;i<ADC_AVG;i++) {
        MCUCR   |= _BV(SE);
        ADCSRA  |= _BV(ADSC);
        __asm volatile("sleep");
        MCUCR   &= ~_BV(SE);
        result  = (hi<<8);
        result  |= lo;
        average += result;
    }
    average /= ADC_AVG;
    return average;
}

void sendByte(char val)
{
    while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete
    UDR0 = val;
}

/*
 * Convert voltage to temperature based on a negative coefficient for MAX6613
 */
uint16_t analogToTemp(uint16_t val)
{
  uint16_t temp;
  //v     = 5 * (val/1023.0);
  //temp  = (1.8455 - (5.0*(val/1023.0)))/0.01123;
  temp  = (1.8455 - (5.0*(val/1023.0)))*89;
  //temp = val * M_PI;
  //v     = 5 * ( val/1024);
  //temp  = (2 - v) * 89;

  return temp;
}

void initDisplay()
{
    sendByte(DISP_RESET);
    sendByte(DISP_BRIGHT_CMD);
    sendByte(0);
}

void serialSegments(uint16_t val)
{
  // 4 digit display
  sendByte(val / 1000);
  sendByte((val / 100) % 10);
  sendByte((val / 10) % 10);
  sendByte(val % 10);
}

int main(void)
{
    uint16_t calc=0,sense=0;

    DDRB    |= _BV(DDB5);
    PORTB   |= _BV(PORTB5);
    initSerial();
    initADC();
    initDisplay();
    sei();
    MCUCR   |= (1 << SM0); // Setting sleep mode to "ADC Noise Reduction"
    MCUCR   |= (1 << SE);  // Sleep enable
    for(;;) {
        //PORTB   ^= _BV(PORTB5);
        if (calc>=9999){ // I can't see the real value. Max val on display is 9999
        //if (sense>=330){
            PORTB |= _BV(PORTB5);
        } else {
            PORTB &= ~_BV(PORTB5);
        }

        sense   = readADC();
        //calc    = sense*1.0;      // refuses to calculate properly
    calc    = analogToTemp(sense);  // a bunch of zeroes
        //calc = 65535*0.1;         // a-ok

        serialSegments(calc);
        _delay_ms(500);
        serialSegments(sense);
        _delay_ms(500);
    }
    return 0;
}

Makefile:

# AVR-GCC Makefile
PROJECT=Temp_Display
SOURCES=main.c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=atmega328p
OSC_HZ=16000000UL
OPTIMISATION=2
PORT=/dev/ttyUSB0

CFLAGS=-mmcu=${MMCU} -std=gnu99 -Wall -O${OPTIMISATION}  -DF_CPU=${OSC_HZ} -lm -lc

${PROJECT}.hex: ${PROJECT}.out
    ${OBJCOPY} -j .text -O ihex ${PROJECT}.out ${PROJECT}.hex
    avr-size ${PROJECT}.out

$(PROJECT).out: $(SOURCES)
    ${CC} ${CFLAGS} -I./ -o ${PROJECT}.out ${SOURCES}

program: ${PROJECT}.hex
    stty -F ${PORT} hupcl
    avrdude -V -F -c arduino -p m168 -b 57600 -P ${PORT} -U flash:w:${PROJECT}.hex

clean:
    rm -f ${PROJECT}.out
    rm -f ${PROJECT}.hex

EDIT:OK, i've simplified the code somewhat

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#define BAUD 9600
#include <util/setbaud.h>
#define DISP_BRIGHT_CMD     'z'
#define DISP_RESET          'v'


void initSerial(void)
{
    // set baud rate
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
    // set frame format
    UCSR0C |= (0x3 << UCSZ00); // 8n1
    // set enable tx/rx
    UCSR0B = _BV(TXEN0);
}


void sendByte(char val)
{
    while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete
    UDR0 = val;
}


void initDisplay()
{
    sendByte(DISP_RESET);
    sendByte(DISP_BRIGHT_CMD);
    sendByte(0);
}

void serialSegments(uint16_t val) {
  // 4 digit display
  sendByte(val / 1000);
  sendByte((val / 100) % 10);
  sendByte((val / 10) % 10);
  sendByte(val % 10);
}

int main(void)
{
    uint16_t i=0,val;

    DDRB    |= _BV(DDB5);
    initSerial();
    initDisplay();
    for(;;) {
        val = (uint16_t)(i++ * 1.5);
        serialSegments(i);
        _delay_ms(500);
        serialSegments(val);
        _delay_ms(500);
        if (val > 9999){
            PORTB |= _BV(PORTB5);
        } else {
            PORTB &= ~_BV(PORTB5);
        }
    }
    return 0;
}
解决方案

Not exactly your code, maybe close enough, maybe not.

First off when I display the output and compare these to lines:

val = (unsigned int)(i++ * 1.5);
...
val = i+(i>>1); i++;

the result is the same. Disassembling shows a few things as well. First off avr-gcc

avr-gcc --version
avr-gcc (GCC) 4.3.4
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

uses floats not doubles, so the comments about 1.5F vs 1.5 are quite valid in general but not relevant here. Second it is producing floating point values, single precision, and is doing floating point math, the compiler did not take a shortcut there, it converts to float, does the multiply then converts back.

Using my hex display routine and your decimal display routine (modified to output on a serial terminal), here again it produces the same output, the floating point math does not appear to be the problem.

I started this task to see if the floating point performance was a killer, and it is, but the timing changes depending on how I test it. it took as much as 157 times longer for the code with the floating point compared to fixed point. If I leave in the call to serialSegments(), but have that call a dummy routine instead of the serial port it is 3 times slower for the float. Also I built two different ways and pulled in a libc/m which used a different set of floating point routines, the floating point routines chosen by the C compiler were 7 times slower than the libc/libm.a sitting in the /usr/lib64/avr/lib/ directory. Once you add the waiting on serial port and other delays you may not notice the difference in timing so this experiment while demonstrating that the float is quite painful, is probably not the smoking gun even if your code is timing sensitive, we are talking a few milliseconds.

In addition to the code below I tried this as well:

for(i=0;i<9999;i++){ vala = (unsigned int)(i * 1.5); valb = i+(i>>1); i++; if(vala!=valb) { hexstring16(i); hexstring16(vala); hexstring16(valb); }}

No fail. I limited to 9999 because serialSegments() only chops up decimals from 0 to 9999. Now your loop goes beyond that to 65535, but you would see that cause problems without the float though, right?

avr.c

#define UCSRA (*((volatile unsigned char *)(0xC0)))
#define UDR   (*((volatile unsigned char *)(0xC6)))
#define TCCR0A  (*((volatile unsigned char *)(0x44)))
#define TCCR0B  (*((volatile unsigned char *)(0x45)))
#define TCNT0   (*((volatile unsigned char *)(0x46)))

#define TCCR1A  (*((volatile unsigned char *)(0x80)))
#define TCCR1B  (*((volatile unsigned char *)(0x81)))
#define TCNT1L  (*((volatile unsigned char *)(0x84)))
#define TCNT1H  (*((volatile unsigned char *)(0x85)))

void dummy ( unsigned int );
void uart_putc ( unsigned char c )
{
    while(1) if(UCSRA&0x20) break;
    UDR=c;
}
void hexstring16 ( unsigned int d )
{
    unsigned int rb;
    unsigned int rc;

    rb=16;
    while(1)
    {
        rb-=4;
        rc=(d>>rb)&0xF;
        if(rc>9) rc+=0x37; else rc+=0x30;
        uart_putc(rc);
        if(rb==0) break;
    }
    uart_putc(0x0D);
    uart_putc(0x0A);
}

#ifdef SEGMENTS

void sendByte(char val)
{
    uart_putc(0x30+val);
}


void serialSegments(unsigned int val) {
  // 4 digit display
  dummy(val / 1000);
  dummy((val / 100) % 10);
  dummy((val / 10) % 10);
  dummy(val % 10);
}

//void serialSegments(unsigned int val) {
  //// 4 digit display
  //sendByte(val / 1000);
  //sendByte((val / 100) % 10);
  //sendByte((val / 10) % 10);
  //sendByte(val % 10);
  //uart_putc(0x0D);
  //uart_putc(0x0A);
//}



#else

void serialSegments(unsigned int val)
{
    dummy(val);
}

//void serialSegments(unsigned int val)
//{
    //hexstring(val);
//}


#endif

int main(void)
{
    unsigned int i,val;
    volatile unsigned int xal,xbl,xcl;
    volatile unsigned int xah,xbh,xch;

    hexstring16(0x1234);

    TCCR1A = 0x00;
    TCCR1B = 0x05;

    xal=TCNT1L;
    xah=TCNT1H;
    for(i=0;i<9999;)
    {
        val = (unsigned int)(i++ * 1.5);
        //serialSegments(val);
        //hexstring16(val);
        dummy(val);
    }
    xbl=TCNT1L;
    xbh=TCNT1H;
    for(i=0;i<9999;)
    {
        val = i+(i>>1); i++;
        //serialSegments(val);
        //hexstring16(val);
        dummy(val);
    }
    xcl=TCNT1L;
    xch=TCNT1H;
    xal|=xah<<8;
    xbl|=xbh<<8;
    xcl|=xch<<8;
    hexstring16(xal);
    hexstring16(xbl);
    hexstring16(xcl);
    hexstring16(xbl-xal);
    hexstring16(xcl-xbl);
    return 0;
}

dummy.s

.globl dummy
dummy:
    ret

vectors.s

.globl _start
_start:
    rjmp reset


reset:
    rcall main
1:
    rjmp 1b

.globl dummy
dummy:
    ret

Makefile

all : avrone.hex avrtwo.hex

avrone.hex : avr.c dummy.s
    avr-as dummy.s -o dummy.o
    avr-gcc avr.c dummy.o -o avrone.elf -mmcu=atmega328p -std=gnu99 -Wall -O2 -DSEGMENTS
    avr-objdump -D avrone.elf > avrone.list
    avr-objcopy avrone.elf -O ihex avrone.hex

a    vrtwo.hex : avr.c vectors.s
    avr-as vectors.s -o vectors.o
    avr-as dummy.s -o dummy.o
    avr-gcc -c avr.c -o avrtwo.o -mmcu=atmega328p -std=gnu99 -Wall -O2 -nostartfiles
    avr-ld vectors.o avrtwo.o -o avrtwo.elf  libc.a libm.a
    avr-objdump -D avrtwo.elf > avrtwo.list
    avr-objcopy avrtwo.elf -O ihex avrtwo.hex



clean :
    rm -f *.hex
    rm -f *.elf

This was all run on an arduino pro mini (atmega328p).

这篇关于带有AVR atmega8的C中的意外浮动行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 16:33