我今天不说话 发表于 2014-11-27 12:13:16

关于arduino串口接收数据的处理问题。求大神帮助。

我写了一个程序,想要在串口输入1或者2,然后arduino就可以做出相应的回应。
int analogPin = 0;//定义模拟量读取口
int LED = 13;//定义13为led灯接口
void setup()
{
Serial.begin(9600);//定义波特率
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
}
void loop()
{
char val;//定义变量val,用于暂存上位机发送来的字符
if (Serial.available() > 0) //如果上位机发送来了字符
{
    val = Serial.read(); //读取上位机发来的字符,并保存到val
    while (val == '1') //当上位机发送过来'1',执行第一个循环
    {
      int n = analogRead(analogPin);
      int i = n / 1000;
      int a = n % 1000;
      int j = a / 100;
      int b = a % 100;
      int k = b / 10;
      int c = b % 10;
      Serial.print(i);
      Serial.print(j);
      Serial.print(k);
      Serial.print(c);//把模拟量分段从串口输出,输出固定的四字节数据。
      digitalWrite(LED, LOW); //关闭LED灯
      delay(500);
      digitalWrite(LED, HIGH);//点亮LED
      delay(500);
    }
    while (val == '0') //如果上位机发送字符'0',执行第二个循环
    {
      digitalWrite(LED, LOW); //熄灭LED灯
    }
}
}
但是存在一个问题,就是当串口输入“1”时,能够输出模拟量,灯也能够闪烁,单是它一直在执行第一个循环,无法跳出循环,即使串口输入了“0”,也不会执行第二个循环。
求大家帮忙修改一下,如何才能根据串口的数来执行不同的循环啊。

peanut 发表于 2014-11-27 12:59:55

我今天不说话 发表于 2014-11-27 12:54 static/image/common/back.gif
不过呢,还是不行,刚刚试了一下,串口一打开,灯立马就闪了,发送了“1”反而不闪了。

第10行:is_blink = true; 初始化为闪烁,所以打开就闪。
改为 is_blink = false; 默认不闪。

第20行,给1加上单引号,‘1’,串口收的是字符,不是数值。

peanut 发表于 2014-11-27 12:26:58

把while改为if

我今天不说话 发表于 2014-11-27 12:32:54

peanut 发表于 2014-11-27 12:26 static/image/common/back.gif
把while改为if

改为if以后LED就不能闪烁,串口只输出一次数据。

fenggr 发表于 2014-11-27 12:35:01

改成这样试试: if (Serial.available() > 0) //如果上位机发送来了字符
{
    val = Serial.read();


if (val == 1){
...
...
}

if (val == 0){
...
}

peanut 发表于 2014-11-27 12:45:54

本帖最后由 peanut 于 2014-11-27 14:08 编辑

我今天不说话 发表于 2014-11-27 12:32 static/image/common/back.gif
改为if以后LED就不能闪烁,串口只输出一次数据。



int analogPin = 0;//定义模拟量读取口
int LED = 13;//定义13为led灯接口
bool is_blink;

void setup()
{
Serial.begin(9600);//定义波特率
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
is_blink = false;
}


void loop()
{
char val;//定义变量val,用于暂存上位机发送来的字符
if (Serial.available() > 0) //如果上位机发送来了字符
{
    val = Serial.read(); //读取上位机发来的字符,并保存到val
    if (val == '1')
    {
      is_blink = true;
    }
    else if (val == '0')
    {
      is_blink = false;
    }
}

if (is_blink)
{
    blink(); //闪烁
}
else
{
    shutdown();//熄灭LED灯
}
}


void blink()
{
int n = analogRead(analogPin);
int i = n / 1000;
int a = n % 1000;
int j = a / 100;
int b = a % 100;
int k = b / 10;
int c = b % 10;
Serial.print(i);
Serial.print(j);
Serial.print(k);
Serial.print(c);//把模拟量分段从串口输出,输出固定的四字节数据。
digitalWrite(LED, LOW); //关闭LED灯
delay(500);
digitalWrite(LED, HIGH);//点亮LED
delay(500);
}


void shutdown()
{
digitalWrite(LED, LOW);
}

我今天不说话 发表于 2014-11-27 12:49:00

peanut 发表于 2014-11-27 12:45 static/image/common/back.gif


谢谢这位大神,对我帮助太大了。

我今天不说话 发表于 2014-11-27 12:54:47

我今天不说话 发表于 2014-11-27 12:49 static/image/common/back.gif
谢谢这位大神,对我帮助太大了。

不过呢,还是不行,刚刚试了一下,串口一打开,灯立马就闪了,发送了“1”反而不闪了。

Super169 发表于 2014-11-27 13:58:15

本帖最后由 Super169 于 2014-11-27 14:01 编辑

如果用電腦作 serial input, 每次讀取所需資料後, 除非你會同時處理多行指令, 否則, 最好加上一些 clean-up 的動作.

if (Serial.available()) {
val = Serial.read();
:
:
// clean-up serial buffer
delay(1);
while(Serial.available()) {
    Serial.read();
    delay(1);
}

}

即使改成 if, 預設不閃, 輸入 '1' 後也只會閃一下就停下來.
原因是電腦會多送 LRLF 給你, 而你的程式就會因為 else 部份而停止閃爍了.


Super169 发表于 2014-11-27 14:03:41

注意, clean-up 中的 delay(1) 也很重要的.
除非你可以肯定傳送速度足夠快, 否則, 不要為了節省千分一秒而省去.
對於比較慢的波特率, 甚至要加上 delay(2) 或更多.

peanut 发表于 2014-11-27 14:13:27

Super169 发表于 2014-11-27 14:03 static/image/common/back.gif
注意, clean-up 中的 delay(1) 也很重要的.
除非你可以肯定傳送速度足夠快, 否則, 不要為了節省千分一秒 ...

:lol 学习了。我并没有操作过串口。

sam 发表于 2014-11-27 23:39:58

发送的指令过于简单了,以至于经常被误以为是是到了什么指令。建议加一个简单的指令格式,这样很容易鉴别是否收到了正确的指令。
比如NMEA0183,它这么说话:
$GPRMC,.....,.....,................,*
我建议你也可以这样:
$1*
$0*
$XX,1,YY,*
...

JIMJIM 发表于 2019-3-20 20:28:47

Super169 发表于 2014-11-27 13:58
如果用電腦作 serial input, 每次讀取所需資料後, 除非你會同時處理多行指令, 否則, 最好加上一些 clean-up ...

怎么有两个delay(1); 那这个clean-up怎么接上上面的代码

Super169 发表于 2019-3-25 09:26:01

JIMJIM 发表于 2019-3-20 20:28
怎么有两个delay(1); 那这个clean-up怎么接上上面的代码

delay(1) 是確保有足夠時間接收完整的一個 byte.
試想想, 如果是 9600bps, 一個 bit 就要 1/9600 秒, 8 個 bit 最少都要 8/9600 ... 接近 1ms 了.
第一個 delay 是開始前的確認, 如果刪了, 可能因為時間不足而進不了 while.
之後不斷讀取, 裡面的 delay 是確認完成, 如果刪了, 可能因為時間不足而太早離開 while.

道者 发表于 2023-5-6 19:53:39

亲测可行:
int analogPin = 0;//定义模拟量读取口
int LED = 13;//定义13为led灯接口
char val = 0;//定义为全局变量!!!
void setup()
{
    ...
}
void loop()
{
//char val;//定义变量val,用于暂存上位机发送来的字符
if (Serial.available() > 0) //如果上位机发送来了字符
{
    val = Serial.read(); //读取上位机发来的字符,并保存到val
}
if(val == '1') //当上位机发送过来'1',执行第一个循环
{
    ...
}
if(val == '0') //如果上位机发送字符'0',执行第二个循环
{
    ...
}
}
页: [1]
查看完整版本: 关于arduino串口接收数据的处理问题。求大神帮助。