RS485总线数据收发
一、实验目的
1、熟练使用Linux下io函数read、write和epoll等
2、熟练处理流式通信数据
3、理解485总线的冲突问题
二、RS485信号介绍
RS485总线有两条线信号线,能够传输一个逻辑信号。计算机标准的UART串口有RX、TX收发两条线,因此能够同时进行数据的接收和发送。而RS485只有一个逻辑信号,因此同一时刻只能有一个主体进行数据发送(因此叫做半双工通信串口)。
单片机板上使用了一颗MAX485芯片作为标准UART接口向485接口转换的接口芯片。
如下图所示,单片机串口数据发送脚与MAX485的DI脚相连接。在发送数据前,单片机会将DE脚置为高电平,此时A、B引脚信号为所发送的单片机串口数据。
如果多个单片机将DE脚置为高电平,则A、B信号线同时被多个单片机板的MAX485芯片驱动,则会造成数据收发错误甚至损坏芯片。因此,多个单片机对485总线操作的时间控制至关重要。
三、实验过程
1、向A单片机板下载下面的程序
AHasSecret.hex
向B单片机板下载下面的程序
B_Relay.hex
下载程序后,A板单片机将使用1200波特率约每300ms发送一次自身序列号,格式为
0xAA 0x55 4字节序列号
序列号:E8 F1 A3 5D
2、通过B板串口向RS485总线写入自己的学号,格式为
0xAA 0x55 十二位学号数字。
例如学号20220110203,应该通过串口发送以下数据
AA 55 02 00 02 02 00 01 01 01 00 02 00 03
3、A板单片机接收到学号后会每300m发送第一串密码,密码长度为4字节。请将解析出该串密码并在150ms内原样发回给串口(否则会造成总线的冲突)。STC单品机收到返回后会继续发送下一串密码,请继续解析出该串密码并在150ms内原样发回给串口。以此往复,将收到的最后一串密码记录下来。
例如,收到以下密码串
AA 55 00 00 00 00 00 C9 34 3F 5D
其中AA 55为前导串,最后4个字节是密码。请将密码原样发回给串口。
AA 55 C9 34 3F 5D
代码如下:
(咳咳:有的密码可能包含aa会造成错误得到0结果 所以这个代码大家再改改哈哈哈)
main.c:改成自己的学号
#include <stdio.h>
#include "com.h"
int main(void)
{
unsigned char tmp[15] = {0}; //用于存放读取出来的数据的缓冲区
int rl; //读取数据的长度(单位:字节)
int i;
fd = openSerial("/dev/ttyUSB0"); //打开串口,ttyUSB0是串口文件
if(fd < 0)
{
printf("open com fail!\n");
return 0;
}
EpollInit(fd); //初始化终端事件触发函数epoll,设置要监听的事件及相关参数等
unsigned char sno[14] = {0XAA, 0X55, 0X02, 0X00, 0X02, 0X00, 0X00, 0X08, 0X00, 0X04, 0X00, 0X02, 0X02, 0X04}; //这里改为自己的学号
unsigned char passwd[6] = {0XAA, 0X55};
int n=0;
unsigned s[100] = {0};
const char* errstr = "error!";
write(fd,sno,14);
while(1)
{
rl = ComRead(tmp,1);//读取13个字节放到缓存
//打印读到的数据
int j;
s[n++] = tmp[0];
if(tmp[0]==0xaa&&n>=8){
for(j=0;j<4;j++)
passwd[5-j]=s[n-j-2]; //根据aa55前四位从后往前确定密码
for(j=0; j<6; j++)
printf(" %02x",passwd[j]);
printf("\n\n");
write(fd,passwd,6);
n=0;
}
}
close(epid);
close(fd);
return 0;
}
com.c:(波特率设为1200)
编译:
查看并修改代码:
修改权限sudo chmod 777 /dev/ttyUSB0
或以管理员身份运行 sudo ./main
等待密码不变。
4、将学号、序列号、最后一串密码发送到课程后台。上送命令语法为
curl "132.232.98.70:6363/check485Secret?id=学号&v=序列号&s=密码"
后台返回的数字表示该密码的编号,返回DUP表示该序列号已经被其它同学使用,请更换电路板重新取得密码。
密码:EC F3 A1 5D
返回256,到达了密码的最大次数。