printf() & co.

Go To Last Post
67 posts / 0 new

Pages

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim's error is that he used:

FILE lcd_str = FDEV_SETUP_STREAM(lcd_puts, NULL, _FDEV_SETUP_WRITE); 

I would respectfully suggest you would get more mileage from:

FILE lcd_str = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE); 

The whole point here is that the stream function only has to put (and in the case of UART possibly also get) one character at a time. Sure, once you have connected lcd_str to stdout you can then use:

puts("hello");
printf("pi is roughly %f", M_PI);

but all these need a single character outputting routine at their core. lcd_putchar (with the correct interface) is it. lcd_puts is not.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Earlier discussions glossed over the 'correct' putchar() function.

I would also suggest that you choose a more intuitive name for the FILE stream :

FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE); 

I look at "lcd_str" and immediately think "string".
I know that machines don't care what you call variables.

However c, ch, key, letter, ... imply a char or int
And s, str, buf, string, ... imply a pointer or array

I don't mind single letters for local variables. You can see all the references in the block. Hopefully the whole block fits on the screen.

Global variables need to be very descriptive or else you lose the plot. Only ASM programmers can keep 1000 global variables in their head at any one time.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I look at "lcd_str" and immediately think "string".

Me too but this is what stdiodemo.c in the AVR-LibC manual has:

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
FILE lcd_str = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After looking at the above examples, I pulled a chunk of code out of a working experiment and inserted it into the current experiment that your comments above reference to:

#include 
#include 
#include 
#include 
#include 
#include "lcd.h"

#define MYUBRR (((F_CPU / (9600 * 16UL)))-1)


int uart_putchar(char c, FILE * fp)
{
	while (!(UCSR0A & (1<<UDRE0)));
	UDR0 = c;
	return c;
}

void avrinit(void)
{
	DDRA = 0xFF;	//porta all outputs for LCD
	PORTB = 0xFF;
	static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
	stdin = stdout = &mystdout;
	UBRR0H = MYUBRR >> 8;
	UBRR0L = MYUBRR;
	UCSR0B = (1<<TXEN0)|(1<<RXEN0);
	UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);     // Set frame: 8data, 1 stp
}



int main(void)
{	avrinit();
	lcd_init(LCD_DISP_ON_CURSOR_BLINK);
while(1)
{ 
	

if(bit_is_set(PINB,0))	
	{ lcd_clrscr();
		/* put string to display (line 1) with linefeed */
	 lcd_puts("LCD Test Line 1\n");
	 printf("LCD Test Line 1\n");
	 
	 /* cursor is now on second line, write second line */
	 lcd_puts("Line 2");
	 printf("Line 2");
	 while(bit_is_set(PINB,0))
	 {
	 }
	 
	}
	
if(bit_is_clear(PINB,0))
{lcd_clrscr();
	lcd_puts("AVRfreaks");
	while(bit_is_clear(PINB,0))
	{
	}

}

}
}

I figured I would add the uart sending out a quick message, but while I get no compile errors my disassembly window says otherwise as I get nothing on the terminal program.

One thing I notice in the different notes of this:

int uart_putchar(char c, FILE * fp)
{
	while (!(UCSR0A & (1<<UDRE0)));
	UDR0 = c;
	return c;
}

Is that sometimes I see STREAM in place of fp:

int uart_putchar(char c, FILE * stream)
{
	while (!(UCSR0A & (1<<UDRE0)));
	UDR0 = c;
	return c;
}

tried both and get the same result. Will play with this for a little while.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

sometimes I see STREAM in place of fp
[...]
tried both and get the same result.

Does not matter what you use. It's "just" a parameter/variable name. Add that it is actually not used and it matters even less.

Why not used, you ask? Search out the sketch for a tutorial that I wrote the other day and the answer is there.

-----

You should take some time to fix your indentation. It is not a thing one does as the last step, so that the end result looks pretty. It is something you maintain all the time so that you have a better chance reading the code you yourself write.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1. Is your F_CPU defined correctly?

2. Can you see anything on the TX pin with a scope?

3. Do not do this:

   stdin = stdout = &mystdout;

Since your call to FDEV_SETUP_STREAM has NULL as the second parameter the stream can not accept input. Therefore you should not assign stdin. Not that it will make much damage here and now, but it is confusing and is a possible future malign bug. Just do

   stdout = &mystdout;

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another thought:

If you tear out everything in the main() function (execept the initializations) and replace it with e.g. this:

uart_putchar( 'A', NULL);
uart_putchar( 'V', NULL);
uart_putchar( 'R', NULL);

Will that output anything on the UART? If 'no', then your problem is not with the streams/printf implementation but with the UART setup and/or communication as such.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmmm. On a train right now. Will look at your ideas later tonight

Thanks Johan

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since your program 'looks' ok to me, I thought that I would build it on a UNO.

I had to comment out the DDRA line. It is pointless anyway. The LCD port lines are initialised in the lcd_init() function.

I built and ran the program:
It displayed on both the LCD and UART.

If you have a problem with the UART, you are probably using a wrong F_CPU. I suggest that you set it in Toolchain->Symbols and make sure it agrees with the STK600.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Found the problem. Damned carfarcolus switch. It gets a little 'iffy' sometimes. Reset the jumper and things are working correctly.

In the meantime. I will read Johans excellent posts along with Cliffs and the others a few more times while I put together an exercise that will use what I have learned so far.

Thanks all.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Do not do this:

Just as a general point don't do it anyway.

 stdin = &mystdout; 
 stdout = &mystdout; 

would have been clearer to the reader and won't generate any more code. But, as Johan says, if there is no input stream don't do the stdin= line anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks
Before I head out this morning I am going to print out this threD for some light reading

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys!
Recently I extended my little knowledge about MCUs on PICs and I find that the trend is to remove, deleting options ecc in function like sscanf() or similar (only one compiler support, badly, the sscanf, at latest versions of all compilers). But the printf() has a good support everywhere.

So I'm wondering if it is true that in a professional like environments, functions like sscanf() are never used? I mean, if I need to read a float number incoming from a string which contains also letters, is a good practice to make your own function? (is well known the overhead due to the sscanf() )

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So I'm wondering if it is true that in a professional like environments, functions like sscanf() are never used?

Any standard compliant C compiler must implement sscanf(). If it doesn't it is not a standards compliant C compiler. Whether the end users choose to use that or any other function is irrelevant. It sounds like slopiness/laziness if compilers (or rather their libc's) are being produced without one or more of the functions specified in the C standard.

It may well be true that not everyone would choose to use that function but without it examine your comment:

Quote:

if I need to read a float number incoming from a string which contains also letters, is a good practice to make your own function?

If there isn't a library function to that then how are you going to implement it exactly? I suppose you might just use atof() but it's going to involve more work on your part and you'll end up reimplementing parts of sscanf() anyway and likely with some bugs you add. The one argument against printf/scanf in 1/2/4K micros is, I guess, do you really want to spend 2-3K on one library function. If that is the issue then, yes, I guess you need to implement just small, targetted parts of the scanf functionality using your own implementation (though likely assisted by lesser library functions like atof()).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll add this: If the string input that is to be converted to a float has limitations on how it can be formatted (e.g. the counterpart producing the string is not a human but a computer program that keeps within tight limits regarding the format of the string) then you might be able to implement something that is more efficient than sscanf. It is still highly likely that atof() will be a better option than writing your own conversion proper.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So I'm wondering if it is true that in a professional like environments, functions like sscanf() are never used?

I'll add that IME in a dozen years of AVR programming and scores of production applications, I've yet to use the scanf() family in an AVR app. [I've rarely used floating point either, but that is probably a different topic.]

It isn't the overhead of scanf() per se, but rather my aversion to having to process a free-form string on an AVR8 MICROcontroller. With some kind of fixed format, the detection of a valid "message" format at least becomes manageable. The error detection and recovery in a true free-form message can IMO become onerous.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Pages