RS485信号的测量

一、实验目的

1、熟练使用Linux下io函数read、write和epoll等

2、熟练RS485串口的信号特点

二、实验过程

1、为自己单片机电路板(后面称为A板)下载新的hex文件。

然后按下K3按键,电路板将通过RS485向外发出一组序列号信息。该信号序列格式为:

0xAA 0x55 4字节序列号

请在板上RS485接口插上杜邦线,然后示波器观察该序列信息的内容和波特率并做好记录。

2、使用同学的STC电路板(后面称为B板),下载B板Hex文件:

B板会将计算机通过USB 串口发送的数据,转发到RS485接口上。同时将RS485接口收到的数据,通过 USB 串口转发到计算机上。我们接下来使用这个B板与自己的A板进行通信,读取A板的密码。

B板每次上下拨动摇杆,其串口和RS485总线上波特率会发生变化,同时会在RS485接口上输出一个 0x55。请插上杜邦线后,使用示波器观察其波特率。

请通过上下拨动B板摇杆调节B板波特率,使之与A板输出的RS485波特率相匹配。

3、使用在计算上的程序,调用write函数接口向串口发送读密码命令。读密码命令格式为:

0xAA 0x55 A板序列号 12字节学号

注意,发送时所使用的波特率应该与A板通信波特率一致。命令通过B板转换为RS485信号发送到A板。

A板会回应密码,回应格式为:

0xAA 0x55 4字节密码

回应密码会经过B板转发到计算机上。请调用read函数接口从串口读取该密码。

#include <stdio.h>

#include "com.h"

#include "com.c"

int main(void)

{

unsigned char tmp[15] = {0}; //用于存放读取出来的数据的缓冲区

unsigned char w[18] =

{0xAA,0X55,0x20,0x22,0x4B,0xE5,0x02,0x00,0x02,0x00,0x02,0x06,0x00,0x01,0x00,0x05

,0x01,0x06};

int rl; //读取数据的长度(单位:字节)

int i;

fd = openSerial("/dev/ttyUSB0"); //打开串口,ttyUSB0是串口文件

if(fd < 0)

{

printf("open com fail!\n");

return 0;

}

EpollInit(fd); //初始化终端事件触发函数epoll,设置要监听的事件及相关参数等

write(fd,w,18);

while(1)

{bzero(tmp,sizeof(tmp)); //把tmp对应的内存块的前sizeof(tmp)个字节置零

rl = ComRead(tmp,13);//读取13个字节放到缓存

//打印读到的数据

printf("read_len = %d\n", rl);

tmp[rl] = '\0';

for(i = 0; i < rl; i++)

printf(" z %02x", tmp[i]);

printf("\n\n");

}

close(epid);

close(fd);

return 0;

}

4、请将A板序列号、学号和密码通过curl命令发送到课程后台系统。

上送命令语法为

curl "132.232.98.70:6363/check485?id=学号&v=序列号&s=密码"

回应OK表示正确,其它表示错误。例如,序列号是20 22 4B E5 ,学号是202026010516,回应的密码

为 2B EC 20 4B,那么上报结果命令为:

RS485总线数据收发

一、实验目的

1、熟练使用Linux下io函数read、write和epoll等

2、熟练处理流式通信数据

3、理解485总线的冲突问题

二、实验过程

1、向A单片机板下载下面的程序

向B单片机板下载下面的程序

下载程序后,A板单片机将使用1200波特率约每300ms发送一次自身序列号,格式为

0xAA 0x55 4字节序列号

2、通过B板串口向RS485总线写入自己的学号,格式为

0xAA 0x55 十二位学号数字。

例如学号202026010516,应该通过串口发送以下数据

AA 55 02 00 02 00 02 06 00 01 00 05 01 06

3、A板单片机接收到学号后会每300m发送第一串密码,密码长度为4字节。请将解析出该串密码并在

150ms内原样发回给串口(否则会造成总线的冲突)。STC单品机收到返回后会继续发送下一串密码,

请继续解析出该串密码并在150ms内原样发回给串口。以此往复,将收到的最后一串密码记录下来。

import serial

import requests

import serial.tools.list_ports

# 字节转字符串

def b2s(data):

return ''.join([f'{ch:0>2x}' for ch in data]).upper()

# 连接设备

ser = serial.Serial(list(serial.tools.list_ports.comports()[0])[0], 1200)

# 判断是否连接到设备

assert(ser != None)

# 输入学号

studentID = input("学号:")

# 判断学号是否正确

assert(studentID.isdigit() and len(studentID) == 12)

# 读入序列号

number = b2s(ser.read(6))

# 断言魔数为AA55

assert(number[:4] == "AA55")

# 取出序列号

number = number[4:]

# 判断序列号长度是否正确

assert(len(number) == 4 * 2)

print(f'序列号:{number}')

# 使用学号构造即将发送的字节数据

startData = b'\xaa\x55' + bytes([ord(ch) - ord('0') for ch in studentID])

# 写入数据

ser.write(startData)

password = b'' # 读到的密码i = 1 # 记录循环次数

# 开启永真循环,直到Ctrl+C被按下

try:

while True:

data = ser.read_all()

sdata = b2s(data)

if data != b'' and sdata[:4] == "AA55":

password = data[-4:]

if len(password) == 4:

print(f'[{i}]密码:{b2s(password)}')

# 使用这次读到的密码构造数据,发送给设备以读取下一次的密码

ser.write(b'\xaa\x55' + password)

i += 1

# 当Ctr+C被按下时执行,建议在读到的密码不再变化时按下,大概在256次循环之后

except KeyboardInterrupt:

print(f'[结束]最后一串密码为:{b2s(password)}')

print(f'[正在提交]http://132.232.98.70:6363/checkSecret?id={studentID}&v=

{number}&s={b2s(password)}')

# 提交实验结果至服务器

r = requests.get(f"http://132.232.98.70:6363/checkSecret?id={studentID}&v=

{number}&s={b2s(password)}")

# 判断提交是否成功

assert(r.status_code == 200 and r.text.isdigit())

print(f'[提交成功]学号:{studentID} 密码循环次数:{r.text}')

序列号是0822990F,最后一串密码为0023980F4、将学号、序列号、最后一串密码发送到课程后台。上送命令语法为

curl "132.232.98.70:6363/check485Secret?id=学号&v=序列号&s=密码"

例如,序列号是0822990F,学号是[202026010516],最后一串密码为0023980F,那么上报结果命令 为:

curl "132.232.98.70:6363/check485Secret?id=202026010516&v=0822990F&s=0023980F"

后台返回的数字表示该密码的编号,返回DUP表示该序列号已经被其它同学使用,请更换电路板重新取得密码。

RS485总线有两条线信号线,能够传输一个逻辑信号。计算机标准的UART串口有RX、TX收发两条线, 因此能够同时进行数据的接收和发送。而RS485只有一个逻辑信号,因此同一时刻只能有一个主体进行 数据发送(因此叫做半双工通信串口)。

实验体会

通过这两个实验,我们了解了如何进行RS485信号的测量和RS485总线数据收发。明白波特率可以通过串口得到,也可以通过示波器得到,和上次实验一样,需要使用Linux下io函数read、write函数,对这些函数我们增加了理解

猜你喜欢

转载自blog.csdn.net/a45667/article/details/125955251