关于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”,也不会执行第二个循环。
求大家帮忙修改一下,如何才能根据串口的数来执行不同的循环啊。 我今天不说话 发表于 2014-11-27 12:54 static/image/common/back.gif
不过呢,还是不行,刚刚试了一下,串口一打开,灯立马就闪了,发送了“1”反而不闪了。
第10行:is_blink = true; 初始化为闪烁,所以打开就闪。
改为 is_blink = false; 默认不闪。
第20行,给1加上单引号,‘1’,串口收的是字符,不是数值。 把while改为if peanut 发表于 2014-11-27 12:26 static/image/common/back.gif
把while改为if
改为if以后LED就不能闪烁,串口只输出一次数据。 改成这样试试: if (Serial.available() > 0) //如果上位机发送来了字符
{
val = Serial.read();
}
if (val == 1){
...
...
}
if (val == 0){
...
}
本帖最后由 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);
}
peanut 发表于 2014-11-27 12:45 static/image/common/back.gif
谢谢这位大神,对我帮助太大了。 我今天不说话 发表于 2014-11-27 12:49 static/image/common/back.gif
谢谢这位大神,对我帮助太大了。
不过呢,还是不行,刚刚试了一下,串口一打开,灯立马就闪了,发送了“1”反而不闪了。 本帖最后由 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 部份而停止閃爍了.
注意, clean-up 中的 delay(1) 也很重要的.
除非你可以肯定傳送速度足夠快, 否則, 不要為了節省千分一秒而省去.
對於比較慢的波特率, 甚至要加上 delay(2) 或更多.
Super169 发表于 2014-11-27 14:03 static/image/common/back.gif
注意, clean-up 中的 delay(1) 也很重要的.
除非你可以肯定傳送速度足夠快, 否則, 不要為了節省千分一秒 ...
:lol 学习了。我并没有操作过串口。 发送的指令过于简单了,以至于经常被误以为是是到了什么指令。建议加一个简单的指令格式,这样很容易鉴别是否收到了正确的指令。
比如NMEA0183,它这么说话:
$GPRMC,.....,.....,................,*
我建议你也可以这样:
$1*
$0*
$XX,1,YY,*
... Super169 发表于 2014-11-27 13:58
如果用電腦作 serial input, 每次讀取所需資料後, 除非你會同時處理多行指令, 否則, 最好加上一些 clean-up ...
怎么有两个delay(1); 那这个clean-up怎么接上上面的代码 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. 亲测可行:
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]