Arduino与上位机的串口通讯相关笔记(一) Arduino下位机相关
Table of Contents
0.前言
最近在读书籍:《ARDUINO与LABVIEW开发实战》、《Labview虚拟仪器数据采集与串口通信测控应用实战》。
看到了许多用arduino作为下位机的测控实例,感觉颇为有趣。
说到底,ARDUINO与LABVIEW等等只是工具,真正项目使用的元件取决于必须满足的要求、精度、成本和开发时间。在作者提供的测控实例中,arduino作为下位机,体现着性价比极高的特点。尤其是采样速率和精度要求不高时,可以胜任一定的需求。labview作为上位机,简单易用,其虚拟仪器的特点令软件设计可视化,同时提供了系列的前面板设计环境,所见即所得。
最近攒集的笔记主要是关于arduino与上位机通信的内容
1.ARDUINO中的串口通信函数
1.1 函数
Serial.begin(speed) //speed为波特率,通信双方波特率相同。常用300/1200/2400/4800/9600/14400/19200 Serial.available() //从串口读取有效的字节数,在串行接受缓冲区的数据。 //注意:串口缓冲区为64B,使用Serial.read时,读取1字节,同时从缓冲区删除 Serial.read() //读取1字节的数据,若无可用数据,返回-1 Serial.write() //写入二进制数据到串口,如 Serial.write(val) Serial.write(str) Serial.write(buf,len) Serial.print() Serial.println() //注意:每个数字输出使用的是ASCII字符,浮点类型同样输出的是ASCII字符,默认保留小数点后2位 //byte输出单个字符 //字符和字符串原样输出 //println输出数据自动换行 //例如 Serial.print(78); //"78" Serial.print(1.23456);//"123" Serial.print("N");//"N" Serial.print("Hello");//"Hello" Serial.print(78,BIN);//"1001110" //可选: BIN,OCT,DEC,HEX Serial.print(1.23456,0) //"1" Serial.end //停止通信
1.2 需要注意的一些事项
- 串口缓冲区为64B,使用Serial.read时,读取1字节,同时从缓冲区删除
- 注意:每个数字输出使用的是ASCII字符,浮点类型同样输出的是ASCII字符,默认保留小数点后2位
byte输出单个字符
字符和字符串原样输出
println输出数据自动换行 - 输出附加指令参照最后的例子
2. 下位机编程
2.1 模式选择
一般地,一个下位机可能不工作在单一的模式中,需要初始化时指定其工作模式。工作模式通过如下思路选择
volatile int mode_flag =0 ; volatile long maxnum; byte comdata[3]={0}; char numdata[4]={0,0,0,0}; #define A0_Command 0x10 #define A1_Command 0x11 #define A2_Command 0x20 #define A3_Command 0x21 void receive_data() { int i; for(i=0;i<3;i++) { comdata[i]= Serial.read(); delay(2); } for(i=0;i<4;i++) { numdata[i]= char(Serial.read()); delay(2); } } void test_do_data(void) { int x; if(comdata[0] == 0x55) // 头帧 { if(comdata[1] == 0xAA) //模式选择 { switch(comdata[2]) { case A0_Command: mode_flag = 1; break; case A1_Command: mode_flag = 2; break; case A2_Command: mode_flag = 3; break; case A3_Command: mode_flag = 4; break; } for(x=0;x<4;x++) //传入设定数值 maxnum=(maxnum*10+long(numdata[x]-'0')); } } }
命令监测、执行由receive_data()和test_do_data()负责
首先建立缓冲区数组
byte comdata[3]={0};
char numdata[4]={0,0,0,0};
建立flag
用于缓冲上位机传来的数据
上位机数据具有识别功能。
识别:
设定0x55位有效命令开头,开始读取下一帧
设定0xAA为模式选择开头,进入模式选择
设定各模式十六进制代码,switch选择,用flag标记模式号(1~4,0留给未选择)
最后用maxnum缓存传来的数值
然后再loop中调用函数
2.2 数值传递
上位机向下位机发送数值时,按照位传递。这里上位机下位机统一配套,统一传送。如约定传送四位十进制整数“0098”“1368”
下位机对缓冲区数据的处理:
for(x=0;x<4;x++) maxnum=(maxnum*10+long(numdata[x]-'0'));
3.实验原型
对一个脉冲信号进行稀释,比率由上位机传送。
#define PIN 2 volatile long count =0; volatile int flag = 0; volatile int mode_flag =0 ; volatile long maxnum; byte comdata[3]={0}; char numdata[4]={0,0,0,0}; #define A0_Command 0x10 #define A1_Command 0x11 #define A2_Command 0x20 #define A3_Command 0x21 void receive_data(void); void test_do_data(void); void setup() { Serial.begin(9600); // void init(); pinMode(PIN,INPUT); pinMode(13,OUTPUT); pinMode(8,OUTPUT); attachInterrupt(0,blinkA,FALLING); } void loop() { if(Serial.available()>0) { receive_data(); test_do_data(); } delay(100); //自己发出脉冲信号测试 digitalWrite(8,HIGH); digitalWrite(8,LOW); } void receive_data() { int i; for(i=0;i<3;i++) { comdata[i]= Serial.read(); delay(2); } for(i=0;i<4;i++) { numdata[i]= char(Serial.read()); delay(2); } } void test_do_data(void) { int x; if(comdata[0] == 0x55) // 头 { if(comdata[1] == 0xAA) //模式选择 { switch(comdata[2]) { case A0_Command: mode_flag = 1; break; case A1_Command: mode_flag = 2; break; case A2_Command: mode_flag = 3; break; case A3_Command: mode_flag = 4; break; } for(x=0;x<4;x++) maxnum=(maxnum*10+long(numdata[x]-'0')); } } } void blinkA() { count++; if(count>=maxnum) { if(flag==0) digitalWrite(13,HIGH); else digitalWrite(13,LOW); flag=~flag; count=0; } }
比较原始 存在一些问题,随着后来的学习进行改正
[…] 2016-09-06 Arduino与上位机的串口通讯笔记 […]