Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
5 years, 9 months ago.
Serial scanf does not work
I use STMF303RE.
I connected PC_12 and PD_12 directly.
And I ran the following program, but it stopped at line 11, scanf
main.cpp
#include "mbed.h" Serial self(PC_12,PD_2); Serial pc(USBTX,USBRX); DigitalOut led1(LED1); int data; void toggle_led() { led1 = !led1; pc.printf("before\n\r"); self.scanf("%d",data); pc.printf("get %d\n\r",data); } int main() { led1 = 1; //double test = 0x0123456789abcdef; //double test = 0xfedcba9876543210; int test2 = 0x1234; self.attach(toggle_led,Serial::RxIrq); while(1){ wait(2); //self.printf("%lf",test); self.printf("%d",test2); //self.putc('a'); } }
What is wrong? Please help me.
3 Answers
5 years, 9 months ago.
Hi, the scanf works normal but try this...
try
void toggle_led() { led1 = !led1; /*pc.printf("before\n\r");*/ // without this line it works fine self.scanf("%d",data); pc.printf("get %d\n\r",data); }
or choose another way
Thank you for the reply
I tried it, but it does not work...
And I tried the following, but it did not work.
main.cpp
void toggle_led() { //pc.printf("before\n\r"); self.scanf("%d",&data); led1 = !led1; //pc.printf("get %d\n\r",data); }
And I tried following too.
main.cpp
#include "mbed.h" Serial self(PC_12,PD_2); Serial pc(USBTX,USBRX); DigitalOut led1(LED1); int data; char data2; void toggle_led() { //pc.printf("before\n\r"); self.scanf("%d",&data); led1 = !led1; //pc.printf("get %d\n\r",data); } void toggle2_led(){ data2 = self.getc(); led1 = !led1; } void toggle3_led(){ led1 = !led1; self.scanf("%c",&data2); } int main() { led1 = 1; //double test = 0x0123456789abcdef; //double test = 0xfedcba9876543210; int test2 = 0x1234; self.attach(toggle3_led,Serial::RxIrq); while(1){ wait(2); //self.printf("%lf",test); //self.printf("%d",test2); self.putc('a'); } }
main.cpp
#include "mbed.h" Serial self(PC_12,PD_2); Serial pc(USBTX,USBRX); DigitalOut led1(LED1); int data; char data2; void toggle_led() { //pc.printf("before\n\r"); self.scanf("%d",&data); led1 = !led1; //pc.printf("get %d\n\r",data); } void toggle2_led(){ data2 = self.getc(); led1 = !led1; } void toggle3_led(){ led1 = !led1; self.scanf("%c",&data2); } int main() { led1 = 1; //double test = 0x0123456789abcdef; //double test = 0xfedcba9876543210; int test2 = 0x1234; self.attach(toggle2_led,Serial::RxIrq); while(1){ wait(2); //self.printf("%lf",test); //self.printf("%d",test2); self.putc('a'); } }
toggle2_led worked fine, but toggle2_led did not work.
I think scanf is a problem.
Is it correct to write "%c" or "%d" ?
5 years, 9 months ago.
I'm not looking at whether your code works or not, but something very important that stands out to me is that not to put too much code in an interrupt callback. Generally use the 'callback' to set a flag and act on that flag in your 'main' code. I would expect problems with scanf and printf in your callback. It may work most of the time but will usually fail with MCU lock out at some point. I know this by experience and many hours of scratching my head :)
Thank you for the reply.
I think this idea is very good.
However how should I implemented ?
I wrote the following, but this program has the problem that
toggle_led is kept calling, so main does not proceed.
main.cpp
#include "mbed.h" #define STATE0 0 #define STATE1 1 Serial self(PC_12,PD_2); Serial pc(USBTX,USBRX); DigitalOut led1(LED1); int state = STATE0; void toggle_led() { state = STATE1; return; } int main() { int data; led1 = 1; int test = 1; self.attach(toggle_led,Serial::RxIrq); while(1){ switch(state){ case STATE0: pc.printf("case1\n\r"); wait(1); break; case STATE1: pc.printf("case2\n\r"); self.scanf("%d",&data); pc.printf("get %c\n\r",data); state = STATE0; wait(1); break; } pc.printf("send\n\r"); self.printf("%d",test); } }
5 years, 9 months ago.
As Paul said, even if it did work you shouldn't be doing it that way. printf and scanf should never be used in an interrupt, it's just asking for trouble if you do.
What it looks like you want to do is output some text every 2 second except if the user presses a key at which point everything pauses and waits until they finish entering a number. A better way to do that would be like this:
#include "mbed.h" Serial self(PC_12,PD_2); Serial pc(USBTX,USBRX); DigitalOut led1(LED1); int data; Ticker outputTick; volatile bool outputNow = false; void onTick() { outputNow = true; } int main() { led1 = 1; //double test = 0x0123456789abcdef; //double test = 0xfedcba9876543210; int test2 = 0x1234; // self.attach(toggle_led,Serial::RxIrq); outputTick.attach(&onTick, 2); while(1){ if (outputNow) { self.printf("%d",test2); outputNow = false; } if (self.readable()) { pc.printf("before\n\r") self.scanf("%d",data); pc.printf("get %d\n\r",data); } } }
Thank you for the reply.
I agree with that idea.
However, the program stopped when calling scanf, too.
I think scanf is a problem. Is it correct to write "%d" ?
Scanf should be &data, not just data like I had, sorry made a typo there.
%d is correct if you want to read an integer, I don't think you need a /n or /r/n on the end.
To be honest I normally avoid using scanf whenever possible since it blocks execution for a potentially unlimited time. I much prefer reading the serial input into a buffer and then once a new line is detected using sscanf on the contents of the buffer. That way nothing is blocking.
e.g. with the code below the 2 second output loop doesn't stop as soon as you enter a key until the scanf completes, it keeps running while the number is input. Once a new line is entered the data received is checked and if it contained an integer the value of data is updated.
#include "mbed.h" Serial self(PC_12,PD_2); Serial pc(USBTX,USBRX); DigitalOut led1(LED1); int data; #define _bufferSize_ 16 char stringBuffer[_bufferSize_]; volatile bool inputReady = false;; Ticker outputTick; volatile bool outputNow = false; void onTick() { outputNow = true; } int inputCount = 0; void toggle_led() { stringBuffer[inputCount] = self.getc(); if ((stringBuffer[inputCount] == '/n') || (stringBuffer[inputCount] == '/r')) { stringBuffer[inputCount] = 0; inputReady = true; } inputCount++; if (inputCount == _bufferSize_) inputCount--; led1 = !led1; } int main() { led1 = 1; //double test = 0x0123456789abcdef; //double test = 0xfedcba9876543210; int test2 = 0x1234; self.attach(toggle_led,Serial::RxIrq); outputTick.attach(&onTick, 2); while(1){ if (outputNow) { self.printf("%d",test2); outputNow = false; } if (inputReady) { int tmp; __disable_irq(); int result = sscanf(stringBuffer,"%d",&tmp); inputReady = false; inputCount = 0; __enable_irq(); if (result == 1) { // if correctly decoded a value data = tmp; pc.printf("get %d\n\r",data); } } } }