NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » scanf_P doesn't work

February 27, 2012
by Gil
Gil's Avatar

trying to get a simple printf scanf program to work and i am completely stumped. i searched the forum and its seems this has been a problem for others as well. i never found a solution. here is my code, if someone could please give me some insight. all it does is read a number from the terminal(putty) and blink an led at the entered frequency. ignore the lcd stuff. seems simple. also i loaded the printf scanf.c code from the tutorial and it works fine. connected the green and yellow wires on the ttl cable and it echos. the output of the code below is that it prints "please enter the frequency: thanks,the frequency is: 500" on a single terminal line and then repeats every 500ms (1/2s). it never pauses and reads like the tutorial does and the code is identical. please help.

 gil's blinking led with keyboad input

#define F_CPU 14745600

#include <inttypes.h>
#include <avr/io.h>
#include <math.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

    int main() {

    //pin definitions
    //pb1=led anode
    //  led as output
    DDRB |= (1<<PB1);

    //set up lcd    
    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0,_FDEV_SETUP_WRITE);
    lcd_write_string(PSTR("frequency from keyboard"));

     // start up the serial port
    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
    stdin = stdout = &uart_stream;

    int16_t t = 500;

while(1){   
  // write message to serial port
    printf_P(PSTR("\r\nplease enter the frequency: "));
    scanf_P(PSTR("%d"), &t);
    printf_P(PSTR("thanks, the frequency is: %d\n\r"), t);

        lcd_clear_and_home();
        lcd_write_string(PSTR("frequency is: "));
        lcd_write_int16(t);
        lcd_write_string(PSTR(" Hz "));
        lcd_line_two(); 
        lcd_write_string(PSTR("thanks"));

    //turn on led
     PORTB |= (1<<PB1);

     //delay 
     delay_ms(t);

     //turn off led
     PORTB &= ~(1<<PB1);

     //delay 
     delay_ms(t);

  }

  return 0;
}
February 27, 2012
by Gil
Gil's Avatar

forgot to say the led blinks as expected. thanks again gil

February 27, 2012
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Gil,

Your code looks like it should do what you expect, so I'm thinking there is something more subtle going on here. Could you post up your makefile for me, there are some compiler flags that need to be there for scan_f to work correctly. You can read all about it in the vscanf documentation

Humberto

February 27, 2012
by Gil
Gil's Avatar

thanks for the quick response. i'm pulling my hair out on this and will soon be bumping up agaist the write limit on my chip for loading programs. its like 1 million right, i'm close. here is the make file. its the same file that i compiled the tutorial with which worked. thanks for the help. gil

GCCFLAGS=-g -Os -Wall -mmcu=atmega168 
LINKFLAGS=-Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm
AVRDUDEFLAGS=-c avr109 -p m168 -b 115200 -P /COM3
LINKOBJECTS=../libnerdkits/delay.o ../libnerdkits/lcd.o ../libnerdkits/uart.o

all:    keyboard-upload

keyboard.hex:   keyboard.c
    make -C ../libnerdkits
    avr-gcc ${GCCFLAGS} ${LINKFLAGS} -o keyboard.o keyboard.c ${LINKOBJECTS}
    avr-objcopy -j .text -O ihex keyboard.o keyboard.hex

keyboard.ass:   keyboard.hex
    avr-objdump -S -d keyboard.o > keyboard.ass

keyboard-upload:    keyboard.hex
    avrdude ${AVRDUDEFLAGS} -U flash:w:keyboard.hex:a
February 27, 2012
by Gil
Gil's Avatar

one more piece of information. i am using the usb cable to power my board. can't imagine that it matters, because again the tutorial runs fine.

March 01, 2012
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Gil,

I'm just following up on this thread, because its got me fairly confused. Have you figured out a solution yet?

Just as a precaution, delete all .o and .hex files both in libnerdkits and your project folder and recompile.

Another thing you could try is changing the optimization settings from -Os to -O0 or -O1, perhaps its your compiler that is optimizing away from part of the code.

Humberto

March 01, 2012
by Gil
Gil's Avatar

Humberto - thanks for keeping this in mind. no solution yet. i will try and recompile tonight with your delete suggestions. i'm really new at this and don't know where the optimization settings are located. can you guide me? am i right in thinking that the program should pause at the scanf and wait for and read input until an enter is pressed. i did read the vscanf document but have to admit that all i really understood was the format string stuff.

March 01, 2012
by Ralphxyz
Ralphxyz's Avatar

Gil said:

i'm really new at this and don't know where the optimization settings are located.

They are in your MakeFile!!

GCCFLAGS=-g -Os -Wall -mmcu=atmega328p

Ralph

March 01, 2012
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Gil,

You are correct that scanf should block and wait for the input. Is that the way the sample program from the scanf tutorial behaves?

Humberto

March 02, 2012
by Gil
Gil's Avatar

yes, the sample scanf program works fine. thats the confusing part, they are compiled with the exact same make file, with a "find and replace" on the filename obviously. i didn't have a chance to recompile yet but will soon. i feel that there is not much hope for this solution beacause of the sample scanf running as it should. you guys are awesome and the circutlab looks very cool, i can't wait to use it. gil

March 02, 2012
by Gil
Gil's Avatar

looking back at my posts i noticed something. see how my program editor (programers notepad) highlights some instructions in red. in the make file vfprintf is highlighted but vfscanf is not. is this a clue holmes?

March 02, 2012
by Gil
Gil's Avatar

i deleted the .o .h files in the project dir and i changed the optimization settings and got the same results. how do you recompile the libnerdkits dir?, i couldn't get new .o and .h files for delay, uart, and lcd. i think they were there when i got my kit.

March 02, 2012
by Ralphxyz
Ralphxyz's Avatar

Just use a generic MakeFile recompile the .c file!!

This is where using ProjectName (or Target or Whatever) comes in handy.

Just change the ProjectName to delay, uart, lcd etc. and type make!

GCCFLAGS=-g -Os -Wall -mmcu=atmega328p 
LINKFLAGS=-Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm
#AVRDUDEFLAGS=-c avr109 -p m168 -b 115200 -P /dev/ttyUSB0 
AVRDUDEFLAGS=-c avr109 -p m328p -F -b 115200 -P /dev/cu.PL2303-0000101D
LINKOBJECTS=../libnerdkits/delay.o ../libnerdkits/lcd.o ../libnerdkits/uart.o

ProjectName=delay

all:    $(ProjectName)-upload

$(ProjectName).hex: $(ProjectName).c
    make -C ../libnerdkits
    avr-gcc ${GCCFLAGS} ${LINKFLAGS} -o $(ProjectName).o $(ProjectName).c ${LINKOBJECTS}
    avr-objcopy -j .text -O ihex $(ProjectName).o $(ProjectName).hex

$(ProjectName).ass: $(ProjectName).hex
    avr-objdump -S -d $(ProjectName).o > $(ProjectName).ass

$(ProjectName)-upload:  $(ProjectName).hex
    avrdude ${AVRDUDEFLAGS} -U flash:w:$(ProjectName).hex:a

Ralph

March 02, 2012
by Gil
Gil's Avatar

should i recompile these with the -Os changed to -O0 or -O1 as suggested by humberto?

March 02, 2012
by Gil
Gil's Avatar

also why does your make file have a $(projectname) and mine has just projectname? is this a problem for me?

March 02, 2012
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Gil,

I would certainly try it at least once with -00 (thats dash the letter O then the number 0). I too am not too hopeful of this solution working (because the sample program works for you) however compilers can be finicky things, especially when they are trying to optimize things. Id say its worth a shot.

Humberto

August 27, 2012
by Gil
Gil's Avatar

i know this is an old post but i found the solution to my problem and want to share and know why. to recap - my simple printf scanf program above never puased at the scanf it just ran a loop printing "please enter the frequency: thanks,the frequency is: 500" and blinked the led. the sample nerdkits printf scanf program compiled in the same way ran fine " what is your age what is your favorite number". like i mentioned i used the usb to power my board. i got so sick of pluging and unplugging the usb under my desk to reset the board/mc that i installed in the nerdkits push button switch to cut only the usb power to reset the mc. guess what...the scanf in my program worked as expected. so...why??? the tutorial runs fine without the switch. it was print,scan,print,scan,print and mine was print,scan,print. i understand now that there maybe some intial signals sent over the usb once plugged in that could confuse my program but why the endless loop with scanf never pausing and why did the tutorial work. thanks gil

Post a Reply

Please log in to post a reply.

Did you know that you can connect digital calipers to a microcontroller? Learn more...