I am going around in circles with this one and hope that someone can help.
I am using an Atmega 328 running at 16MHz and Atmel Studio 7. Fuses are correct.
I am using the USART to send characters to PUTTY on my PC.
I can send single characters and an array of assigned characters BUT when I use sprintf to express a double as a string and then try to send each character of that string, it just responds with a single '?' indicating, I assume, that the character is not recognized.
Thanks for any hints on this issue, it seems that sprintf is not working???
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h> // Needed for sprintf
int8_t d;
double xx;
int main(void)
{
uart_init(); // USART initialization code
while (1)
{
//FIRST TEST
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 65; // load data to send
// Correctly sends an 'A'
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 13; // load data to send carriage return
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 10; // load data to send line feed
///////////////////////////////////////
//SECOND TEST
char cc[50];
cc[0]='Z';cc[1]='4'; cc[2]='B'; cc[3]='C'; cc[4]='D';
for (int i=0;i<5;i++)
{
while (!( UCSR0A & (1<<UDRE0))){}; // wait until register is free
UDR0 = cc[i]; // load data to send
_delay_ms(100);
}
//Correctly sends 'Z4BCD'
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 13; // load data to send carriage return
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 10; // load data to send line feed
//////////////////////////////////////
//THIRD TEST
xx=66.666;
char ccw[50];
sprintf(ccw, "%f", xx);
for (int i=0;i<=5;i++)
{
while (!( UCSR0A & (1<<UDRE0))){}; // wait until register is free
UDR0 = ccw[i]; // load data to send
_delay_ms(100);
}
//JUST SHOWS A '?'.
Does the Atmega have hardware floating point? Perhaps this implementation of sprintf() just doesn't know how to convert doubles to strings. I have an implementation, if you'd like to use it, although it's not particularly fast: https://gist.github.com/Helios-vmg/abd9ef1153c5d43d7a29
I didn't ask what the manual says about sprintf. I'm well aware of what it returns. And I didn't ask if you passed in a negative value. I asked if the return value of sprintf is negative.
Instead of just apologizing for the code format, why not edit the post and recopy/paste it in code tags so it's actually readable?
#define F_CPU 16000000UL
#define BAUDRATE 9600
#define BD ((F_CPU / (BAUDRATE * 16UL)) - 1)
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h> // Needed for sprintf
int8_t d;
double xx;
int main(void)
{
uart_init(); // USART initialization code
while (1)
{
//FIRST TEST
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 65; // load data to send
// Correctly sends an 'A'
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 13; // load data to send carriage return
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 10; // load data to send line feed
///////////////////////////////////////
//SECOND TEST
char cc[50];
cc[0]='Z';cc[1]='4'; cc[2]='B'; cc[3]='C'; cc[4]='D';
for (int i=0;i<5;i++)
{
while (!( UCSR0A & (1<<UDRE0))){}; // wait until register is free
UDR0 = cc[i]; // load data to send
_delay_ms(100);
}
//Correctly sends 'Z4BCD'
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 13; // load data to send carriage return
while (!( UCSR0A & (1<<UDRE0))); // wait until register is free
UDR0 = 10; // load data to send line feed
//////////////////////////////////////
//THIRD TEST
xx=66.666;
char ccw[50];
sprintf(ccw, "%f", xx);
for (int i=0;i<=5;i++)
{
while (!( UCSR0A & (1<<UDRE0))){}; // wait until register is free
UDR0 = ccw[i]; // load data to send
_delay_ms(100);
}
//JUST SHOWS A '?'.
return(0);
}
}
But unless you can tell us if the sprintf is returning a negative value or not then there's not much else we can do.
1 2 3 4 5 6 7 8 9 10 11 12 13
// Put this right after the includes:
#define WAIT while (!( UCSR0A & (1<<UDRE0)))
// Replace the sprintf with this:
char ch = 'Y';
if (sprintf(ccw, "%f", xx) < 0)
ch = 'N';
WAIT;
UDR0 = ch;
WAIT;
UDR0 = 13;
WAIT;
UDR0 = 10;
If it prints 'Y' then the sprintf returned a "successful" value; if it prints 'N' then it returned a negative value.
EDIT:
Here's a rewrite of your code using some macros:
no. If it does not work and the value made sense, you still have a problem.
compare the result of sprintf and the strlen() of the string you wrote into. Those should be the same.
What do you know about these doubles?
you can always do something rather moronic like this
int left,right;
left = doubleval;
right = (doubleval-left)*10000;
char zeros[10] = {0};
//loop to fill in leading zeros for right, if any
sprintf(target,"%i.%s%i", left,zeros,right);
or try a different format, if it is acceptable, like scientific notation format
the answer could just be that your compiler/library have a bug. Could check updates, or open a ticket with the provider.
Unfortunately a "successful" result tells us very little. If it was a "failure" then it would tell us that sprintf doesn't like "%f".
Try printing the count with the following code. If it prints the count then we can see if it's a reasonable value. If it doesn't print it then it means that it doesn't even work for "%d".