Not really your code, maybe close enough, or maybe not.
First of all, when I show the output and compare it with the lines:
val = (unsigned int)(i++ * 1.5); ... val = i+(i>>1); i++;
The result is the same. Disassembly also reveals some things. Avr-gcc first
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 float does not double, so comments about 1.5F vs 1.5 are quite acceptable in general, but not relevant here. Secondly, it produces floating point values, single precision and performs math with floating point, the compiler did not use the shortcut there, it is converted to float, whether it is then multiplied.
Using my hexadecimal mapping procedure and your decimal display routine (modified for output to a serial terminal), here it again gives the same result, floating point math does not seem to be a problem.
I started this task to see if floating point performance is a killer, but it depends on how I test it. floating-point code required 157 times more than fixed-point code. If I stay in the serialSegments () call, but for this call, instead of a dummy routine, instead of the serial port, it will be 3 times slower for float. I also built two different methods and pulled into libc / m, which used a different set of floating point routines, the floating point programs selected by the C compiler were 7 times slower than libc / libm.a, sitting in / usr / lib 64 / avr / lib /. When you add the wait to the serial port and other delays, you may not notice the time difference, therefore this experiment, demonstrating that the float is rather painful, probably is not a smoking gun, even if your code is time sensitive, we are talking about a few milliseconds .
In addition to the code below, I also tried this:
for (i = 0; i <9999; i ++) {vala = (unsigned int) (i * 1.5); valb = i + (i → 1); I ++; if (Vala! = valb) {hexstring16 (i); hexstring16 (Shaft); hexstring16 (valb); }}
Not. I limited myself to 9999 because serialSegments () only beats decimal numbers from 0 to 9999. Now your loop goes beyond this value to 65535, but you will see that the problem is with the problem without a float, 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) {
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
All of this was running on arduino pro mini (atmega328p).