当前位置:网站首页>基于485总线的评分系统双机实验报告
基于485总线的评分系统双机实验报告
2022-07-06 09:24:00 【芜湖韩金轮】
本来还想着做多机的,但老师已经打分了就算了。为了压缩到6页删减了很多内容,将就看吧
基于485总线的评分系统实验报告
实验目标:
通过本案例加深理解RS485通信方式,实现上位机的主控制器与所有的下位机进行通信。
B级任务
实验要求:
使用两块STC板分别下载上一节所提供的.hex文件,搭建485双机通信电路,在linux中编程实现打分程序代码。
实验资源:Windows10电脑,Ubuntu18.04,单片机,杜邦线
实验步骤:
阅读程序系统流程框图,明确双机通信的功能需求。
熟悉上一节中模拟MODBUS协议的数据包结构,相关功能码及附加数据定义
回顾485总线数据收发实验,搭建双机通信电路。
PC端串口设置如下:串口波特率:9600 数据位:8位 校验位:无 停止位:
5.所编写的PC端程序应参考上一节中的通信协议完成一次完整的评分过程:
需要包含串口的设置
主节点发起从机检测过程:发送指定从机编号正常检测数据包,判断回应查询数据包是否符合上一节中的通信协议。
主机获取从机评分过程:发送指定从机评分相关数据包,判断回应查询数据包是否符合上一节中的通信协议。
主机发起结束评分的过程,若复位成功,STC从机上第1位和第8位LED 灯会熄灭。
展示串口相关信息,展示检测到的从机编号和从机的评分等。
代码设计思路:
1.定义了几个本次实验要用到的函数:
string format(const vector<uchar> &data); //数据处理为字符串
int check(serial &pipe, int addr); //设备检测
int get_score(serial &pipe, int addr); //获取分数
void reset(serial &pipe); //从机复位
2.接下来是主函数,首先从单片机读入数据,波特率设为9600(题目已给出)
serial pipe("/dev/ttyUSB0", B9600);
3.接着根据题目的要求根据用户输入来选择想要的功能。第一个是根据单片机的编号查找对应的分数,第二个是将从机复位,第三个是退出程序,通过设置循环来重复用户的选择。具体代码如下:
while(1){
cout<<"--------------------基于RS485总线的评分系统-------------------------"<<endl;
cout<<"输入说明:\n1. 输入合法从机地址查询分数\n2. 输入-2将从机复位\n3. 输入-1退出程序\n请输入指令:";
cin>>addr;
if(addr == -1) break;
if(addr == -2) {
reset(pipe);
continue;
}
check_ret = check(pipe, addr);
if(check_ret == 1){
cout<<"设备检测正常"<<endl;
sleep(1);
if(!(score = get_score(pipe, addr)))
cout<<"获取分数失败"<<endl;
else
cout<<"分数:"<<score<<endl;
}
else if(check_ret == 0){
cout<<"地址错误,请输入地址重试"<<endl;
continue;
}
else{
cout<<"数据传输错误,请重启从机"<<endl;
}
//reset(pipe);
cout<<"从机已复位,输入-1退出"<<endl;
}
可以看到,输入-1时退出循环,然后return 0
退出程序。输入-2时调用reset
函数使从机复位。输入正确的从机编号后就会输出对应的成绩,主要是通过调用check
函数来检测从机编号是否正确,调用get_score
来获得成绩,下面具体再分析一下这三个函数的实现思路。
4.reset
函数完整代码:
void reset(serial &pipe){
vector<uchar> code = {
0x5a, 0x00, 0x01,0x00,0x5b};
//cout <<"reset:"<< format(code) << endl;
/* 发送数据包 */
for(int i=0;i<600;i++) {
pipe.myWrite(code);
}
return;
}
参数值是serial串口的数据,根据实验指导可以知道,当主机要发送复位信号给从机时,其序列号应为5a + 广播地址00 + 复位功能码01 + 00 +校验字节
,所以实现思路就是定义一个字符串序列号,然后通过主机不断向从机发送数据包,最终实现从机复位。
5.check
函数完整代码:
int check(serial &pipe,int addr){
int check_code = 117 + addr, ret; //校验码为累加和
vector<uchar> code = {
0x5a, 0x08, 0x13};
vector<uchar> rec;
code.insert(code.begin()+1, (uchar)addr); //插入从机地址
code.push_back((uchar)check_code); //插入校验码
//cout << format(code) << endl;
/* 写入并接收回应数据包 */
pipe.myWrite(code);
sleep(1);
rec = pipe.myRead(5);
if(format(rec) == format(code)) //检验接收数据包是否与发送相同,相同则从机地址正确
ret = 1;
else{
if(rec[3] == 0x6f) ret = 0;
else ret = -1;
}
return ret;
}
函数的参数为串口数据和从机地址。主机发送进行数据检测的序列号为5a + 从机地址 + 检测功能码08 + 13 + 校验码
。实现思路就是将数据检测序列号写入,然后根据收到的数据包来判断从机地址是否正确。如果返回1说明地址正确,返回0说明地址错误,返回-1说明数据错误。
6.get_score
函数完整代码:
int get_score(serial &pipe, int addr){
int check_code = 93 + addr, ret; //校验码为累加和
vector<uchar> code = {
0x5a, 0x00, 0x03};
vector<uchar> rec;
code.insert(code.begin()+3, (uchar)addr); //插入从机地址
code.push_back((uchar)check_code); //插入校验码
//cout << format(data) << endl;
/* 写入并接收回应数据包 */
pipe.myWrite(code);
sleep(1);
rec = pipe.myRead(5);
if(rec[3] == 0x6f) ret = -1; //检验是否错误
else {
ret = (int)rec[3]; //转为数字
if(ret < 0 || ret > 100) ret =-2; //检测数字是否合法
}
return ret;
}
函数的参数为串口数据和从机地址。主机发送进行分数获取序列号为5a + 00 + 读取功能码03 + 从机地址 + 校验码
。实现思路和上一个函数一样,将数据检测序列号写入,然后根据收到的数据包来获得分数,同时要对分数的合法性进行判断。如果正确则返回正确分数,返回-1说明从机未准备好,返回-2说明从机错误。
7.format
函数完整代码如下:
string format(const vector<uchar> &data) {
std::string str(2 * data.size() + 1, '\x00');
for (int i = 0; i < data.size(); i++) {
sprintf(&str[i * 2], "%02X", data[i]);
}
return str;
}
函数的功能主要是将数据处理为字符串,在check
函数中使用
验证及结果分析:
这里设置下位机的编号为2号,分数为66分
打开程序,运行后输入从机编号2可得成绩,输入-2可复位从机,输入-1可退出程序
可以看到,结果正确,当输入正确的从机地址2时,输出了分数66。当输入了-2时,从机就会复位,效果如第一张图所示,单片机上的第一个和第八个灯熄灭。当输入-1时,直接退出程序。
实验总结:
- 人文:认识到交流的重要性。很多不懂的问题通过和同学交流都得到了有效解决。同时遇到问题时可以向老师虚心求问。
- 知识:掌握了基于485总线的评分系统的工作原理和具体实现。学会了如何获取串口数据,并利用串口数据进行一些判断。还学会了如何使用c++来实现基于485总线的评分系统的双机评分。
- 技能:能够较快的编写出c++代码,同时对于单片机的使用和串口助手软件的使用更加得心应手,对于单片机的一些按键能够简单使用。
边栏推荐
- Database monitoring SQL execution
- 函数:求两个正数的最大公约数和最小公倍
- [pointer] the array is stored in reverse order and output
- 《统计学》第八版贾俊平第八章假设检验知识点总结及课后习题答案
- How to transform functional testing into automated testing?
- [HCIA continuous update] advanced features of routing
- JDBC 的四种连接方式 直接上代码
- The four connection methods of JDBC are directly coded
- Sentinel overall workflow
- Get started with Matplotlib drawing
猜你喜欢
Fundamentals of digital circuit (IV) data distributor, data selector and numerical comparator
内网渗透之内网信息收集(三)
线程的实现方式总结
STC-B学习板蜂鸣器播放音乐
Statistics, 8th Edition, Jia Junping, Chapter 11 summary of knowledge points of univariate linear regression and answers to exercises after class
Statistics 8th Edition Jia Junping Chapter XIII Summary of knowledge points of time series analysis and prediction and answers to exercises after class
150 common interview questions for software testing in large factories. Serious thinking is very valuable for your interview
What is an index in MySQL? What kinds of indexes are commonly used? Under what circumstances will the index fail?
Cadence physical library lef file syntax learning [continuous update]
Build your own application based on Google's open source tensorflow object detection API video object recognition system (I)
随机推荐
《统计学》第八版贾俊平第六章统计量及抽样分布知识点总结及课后习题答案
指针:最大值、最小值和平均值
Keil5 MDK's formatting code tool and adding shortcuts
How to use Moment. JS to check whether the current time is between 2 times
《统计学》第八版贾俊平第九章分类数据分析知识点总结及课后习题答案
后台登录系统,JDBC连接数据库,做小案例练习
Pointer -- output all characters in the string in reverse order
函数:字符串反序存放
[pointer] find the largest string
c语言学习总结(上)(更新中)
使用 flask_whooshalchemyplus jieba实现flask的全局搜索
Fundamentals of digital circuits (III) encoder and decoder
Common Oracle commands
Why can swing implement a form program by inheriting the JFrame class?
Flash implements forced login
数字电路基础(四) 数据分配器、数据选择器和数值比较器
【指针】查找最大的字符串
Fire! One day transferred to go engineer, not fire handstand sing Conquest (in serial)
Logstack introduction and deployment -- elasticstack (elk) work notes 019
About the garbled code problem of superstar script