前言:
1、由于我和我的partner都用的WSL(Windows Subsystem for Linux),对于通信方面有一定的优化,在读取信号方面代码可以做到很简洁。 2、如果代码方面有问题或者想尝试安装一个WSL可以移步我的计算机系统专栏,里面有一篇文章有教学。其实安装挺简单的,半个小时就ok了,比虚拟机好得多。 3、先赞后看,养成习惯。 4、仅供参考,谨慎抄袭
RS485信号的测量
一、实验目的 1、熟练使用Linux下io函数read、write和epoll等 2、熟练RS485串口的信号特点
二、RS485信号介绍
三、实验过程 两个同学一人下载A板文件,一人下载B板文件
B板会将计算机通过USB 串口发送的数据,转发到RS485接口上。同时将RS485接口收到的数据,通过USB 串口转发到计算机上。我们接下来使用这个B板与自己的A板进行通信,读取A板的密码。
先将板子连接电脑,第一次我下载B程序,我的partner下载A程序。用示波器与板子标有485位置的两个孔相连,调整示波器参数,使得波形方便看清楚,单次触发,可以计算出A板的波特率。 这里计算出波特率是九千多那个档次(1除以一个稍微比100微秒大一点的数) 然后将示波器与B板相连,通过调节B板的摇杆,使得它与A板有相同的的波特率。 现在准备工作就算做完了,波特率相同就可以通信了。现在最好不要再动板子,以防再出什么问题。 用电脑上之前下载的STC-ISP可以读取A板的序列号:波特率调成用示波器算出来的那个波特率,打开串口助手就可以了。 下载B程序的就要在电脑上写程序来读取密码(注意在com.c里面要改波特率)。
这个代码只能在WSL顺利得到结果,虚拟机上不行。
#include <stdio.h>
#include "com.h"
#include "com.c"
#include <assert.h>
int main(void)
{
int rl;
fd = openSerial("/dev/ttyS4");
if(fd < 0)
{
printf("open com fail!\n");
return 0;
}
EpollInit(fd);
unsigned char number[14] = {0xAA,0x55,0x02,0x00,0x02,0x00,0x00,0x08,0x00,0x01,0x00,0x03,0x00,0x03};
write(fd, number, sizeof(number));
unsigned char tmp[19] = {0};
unsigned char fill[6] = {0};
while(1)
{
int i;
rl = ComRead(tmp,18);
assert(rl > 6);
printf("read_len = %d\n", rl);
tmp[rl] = '\0';
for(i = 0; i < rl; i++)
printf(" %02x", tmp[i]);
printf("\n\n");
for(i = 0; i < 6; i++)
{
if(i == 0)
fill[i] = 0xAA;
else if(i == 1)
fill[i] = 0x55;
else
fill[i] = tmp[(int)tmp[2]-3+i];
}
for(i = 0; i < 6; i++)
printf(" %02x", fill[i]);
printf("\n\n");
bzero(tmp, 19);
if(write(fd, fill, 6) > 0)
printf("Write success\n");
bzero(fill, 6);
}
close(epid);
close(fd);
return 0;
}
curl “132.232.98.70:6363/check485?id=学号&v=序列号&s=密码” 回应OK表示正确,其它表示错误。例如,序列号是D9 01 49 8A ,学号是202201030303,回应的密码为 01 8A D9 49,那么上报结果命令为: curl “132.232.98.70:6363/check485?id=202201030303&v=D901498A&s=018AD949” 这样就算成功一次了。再两个人交换一下,下载另一个程序,重复上述步骤就完成了此任务。
RS485总线数据收发
一、实验目的 1、熟练使用Linux下io函数read、write和epoll等 2、熟练处理流式通信数据 3、理解485总线的冲突问题
二、预备知识 RS485总线有两条线信号线,能够传输一个逻辑信号。计算机标准的UART串口有RX、TX收发两条线,因此能够同时进行数据的接收和发送。而RS485只有一个逻辑信号,因此同一时刻只能有一个主体进行数据发送(因此叫做半双工通信串口)。 单片机板上使用了一颗MAX485芯片作为标准UART接口向485接口转换的接口芯片。请同学们学习该芯片介绍和各引脚的功能。 如下图所示,单片机串口数据发送脚与MAX485的DI脚相连接。在发送数据前,单片机会将DE脚置为高电平,此时A、B引脚信号为所发送的单片机串口数据。 如果多个单片机将DE脚置为高电平,则A、B信号线同时被多个单片机板的MAX485芯片驱动,则会造成数据收发错误甚至损坏芯片。因此,多个单片机对485总线操作的时间控制至关重要。
四、实验过程 和上一个任务一样,分A,B两个程序,两个人每个人下一个程序,总共要做两遍,不同之处在于波特率是确定的,不用再拿示波器测量了。
1、下载程序后,A板单片机将使用1200波特率约每300ms发送一次自身序列号,格式为 0xAA 0x55 4字节序列号 还是用电脑上的STC-ISP波特率调为1200打开串口助手来获得序列号 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 通过写程序来不断获取密码,等到密码一直相同时中断程序,就能向系统发送数据了。
#include <stdio.h>
#include "com.h"
#include "com.c"
#include <assert.h>
int main(void)
{
int rl;
fd = openSerial("/dev/ttyS4");
if(fd < 0)
{
printf("open com fail!\n");
return 0;
}
EpollInit(fd);
unsigned char number[14] = {0xAA,0x55,0x02,0x00,0x02,0x00,0x00,0x08,0x00,0x01,0x00,0x03,0x00,0x03};
write(fd, number, sizeof(number));
unsigned char tmp[19] = {0};
unsigned char fill[6] = {0};
while(1)
{
int i;
rl = ComRead(tmp,18);
printf("read_len = %d\n", rl);
tmp[rl] = '\0';
for(i = 0; i < rl; i++)
printf(" %02x", tmp[i]);
printf("\n\n");
for(i = 0; i < 6; i++)
{
if(i == 0)
fill[i] = 0xAA;
else if(i == 1)
fill[i] = 0x55;
else
fill[i] = tmp[rl-6+i];
}
for(i = 0; i < 6; i++)
printf(" %02x", fill[i]);
printf("\n\n");
bzero(tmp, 19);
if(write(fd, fill, 6) > 0)
printf("Write success\n");
bzero(fill, 6);
}
close(epid);
close(fd);
return 0;
}
4、将学号、序列号、最后一串密码发送到课程后台。上送命令语法为 curl “132.232.98.70:6363/check485Secret?id=学号&v=序列号&s=密码” 例如,序列号是2C9363F5E,学号是202201110203,最后一串密码为51ED8D3A,那么上报结果命令为: curl “132.232.98.70:6363/check485Secret?id=202201110203&v=2C9363F5E&s=51ED8D3A” 后台返回的数字表示该密码的编号,返回DUP表示该序列号已经被其它同学使用,请更换电路板重新取得密码。
|