(这个有留word哈哈)
4.1 4.2 Linux 操作系统平台
一、实验目的
- 了解 Linux 系统文件系统的基本组织
- 了解 Linux 基本的多用户权限系统
- 熟练使用 ls、cd、cat、more、sudo、gcc、vim 等基本命令
- 会使用 ls 和 chmod 命令查看和修改文件权限
二、实验过程
(1)安装 Linux 系统虚拟机
(2)安装firstrun.deb包
使用指令sudo dpkg -i firstrun.deb 进行安装。
(3)安装成功后,运行根目录下的/gettips 可执行程序。该程序将在屏幕上给出下一步骤要探索的目录。
(4)切换到root权限进入目录
运行指令切换到上面提供的目录,切换到root用户(直接进入权限不够),进入该目录。
(5)使用ls打开文件
ls查看并使用vim打开文件.puzzle.txt。
文件中内容如下:
(6)使用curl提交结果
使用如下命令提交:
curl “132.232.98.70:6363/check?id=2022xxxxxxxx&v=3321385423”
提交后返回OK,表示正确。
4.3 Linux 平台串口数据接收
一、实验目的
1、熟练使用 Linux 下 io 函数 read、write 和 epoll 函数
2、了解 Linux 设备文件机制
3、熟练使用示波器识读 UART 波形
二、实验过程
(1)安装 STC-ISP 软件
(2)按照 4.3.1 节说明,向 STC 单片计算机板下载程序
(3)使用示波器观察 STC 单片机 UART 串口输出信号,识别单片机发送数据所使用的波特率。
测得该板波特率为 1800。
(4)根据单片机串口波特率,编写 C 语言程序从虚拟机的串口读取信息。
修改 com.c 的波特率:
(5)使用 gcc 进行编译并运行,解析程序返回的序列号和密码,并且向服务器发送指令
根据指导书:
【STC单片机计算串口发出来的内容格式为:
0xAA 0x55 序列号
以上内容为二进制数据表示,共13个字节。例如:
0xAA 0x55 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xBB 。
其中0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xBB 就是该单片机的序列号。请用程序读出所领单片机的序列号。】
可知,这里aa 55是开始的序列号,而后面的 a0 1d 55 17 75 98 e6 66 66 9e 7e即为传输的11位数据。
注意,提交答案的时候不要把aa,55放入,否则是错误的。
返回OK,说明正确。
4.4 计算机串口数据收发与测量
一、实验目的
1、熟练使用 Linux 下 io 函数 read、write 和 epoll 等
2、熟练处理流式通信数据二、实验过程
二、实验过程
(1)向 STC 单片机下载下面的程序
(2)下载程序后,单片机将使用 1200 波特率发送自身序列号,格式同上一节课(4.3 节内容)相同。请记录下该序列号。
可得序列号为AA 55 A0 1D 56 4F 74 72 F7 39 0D 46 9E
(机器序列号为AA55后面的部分)
(3)向串口写入自己的学号,格式为 0xAA 0x55 十二位学号数字。
如我就写入AA 55 02 00 02 02 XX XX XX XX XX XX XX XX
(4)STC 单片机接收到学号后会发送第一串密码,密码长度为 4 字节。请将解析出该串密码并原样发回给串口。STC 单品机收到返回后会继续发送下一串密码,请继续解析出该串密码并原样发回给串口。以此往复,将收到的最后一串密码记录下来。
由于只将以上(3)(4)步获得的密码提交得分较低,因此选择在Linux系统下使用 Python代码完成上面两步动作,并将取到的最后一组密码发送到课程后台中。
程序如下:
1. import serial.tools.list_ports
2. # 字符串转字符串
3. def b2s(data):
4. return ''.join([f'{ch:0>2x}' for ch in data]).upper()
5. # 连接设备
6. ser = serial.Serial(list(serial.tools.list_ports.comports()[0])[0], 1200)
7. # 判断是否连接到设备
8. assert (ser != None)
9. # 输入学号
10. studentID = input("学号:")
11. # 判断学号是否正确
12. assert (studentID.isdigit() and len(studentID) == 12)
13. # 读入序列号
14. number = b2s(ser.read(13))
15. # 断言魔数为AA55
16. assert (number[:4] == "AA55")
17. # 取出序列号
18. number = number[4:]
19. assert (len(number) == 11 * 2)
20. print(f'序列号:{number}')
21. # 使用学号构造即将发送的字节数据
22. startData = b'\xaa\x55' + bytes([ord(ch) - ord('0') for ch in studentID])
23. # 写入设备
24. ser.write(startData)
25. password = b'' # 读到的密码
26. i = 1 # 循环次数
27. # 开启永真循环,直到ctrl+c被按下
28. while True:
29. # 读1位,探测魔数
30. t = b2s(ser.read(1))
31. # 第一个魔数应该是AA
32. if t != "AA":
33. continue
34. # 再读一位
35. t = b2s(ser.read(1))
36. # 第二个魔数应该是55
37. if t != "55":
38. continue
39. # 判断魔数后可以放心读取数据
40. # 读入密码开始位置的索引
41. index = list(ser.read(1))[0]
42. # 若索引大于4,则表明中间有无关字节,吸收掉无关字节
43. if index - 4 > 0:
44. ser.read(index - 4)
45. # 读入四字节的密码
46. password = ser.read(4)
47. print(f'[{i}]密码:{b2s(password)}')
48. # 使用这次读到的密码构造数据,发送给设备以读取下一次的密码
49. ser.write(b'\xaa\x55' + password)
50. i += 1
在sudo权限下运行main.py,输入自己的学号,得到结果。
(5)将学号、序列号、最后一串密码发送到课程后台。上送命令语法为
curl "132.232.98.70:6363/checkSecret?id=学号&v=序列号&s=密码"
返回256,表示已经拿到最高分,实验成功。
4.5 RS485 信号的测量
一、实验目的
1、熟练使用 Linux 下 io 函数 read、write 和 epoll 等
2、熟练 RS485 串口的信号特点二、实验过程
二、实验过程
(1)为自己的板(A板)下载新的hex文件。
然后按下K3按键,电路板将通过RS485向外发出一组序列号信息。该信号序列格式为:
0xAA 0x55 4字节序列号
在板上RS485接口插上杜邦线,然后示波器观察该序列信息的内容和波特率并做好记录。
下图是A板的示波器显示,使用1÷836μs,其波特率为1200
(2)下载B板文件
使用同学的STC电路板(后面称为B板),下载B板Hex文件:
B板会将计算机通过USB 串口发送的数据,转发到RS485接口上。同时将RS485接口收到的数据,通过USB 串口转发到计算机上。我们接下来使用这个B板与自己的A板进行通信,读取A板的密码。
B板每次上下拨动摇杆,其串口和RS485总线上波特率会发生变化,同时会在RS485接口上输出一个0x55。请插上杜邦线后,使用示波器观察其波特率。
请通过上下拨动B板摇杆调节B板波特率,使之与A板输出的RS485波特率相匹配。
这里我们上下拨动B板摇杆,直至差不多能等于上面的836μs为止,这样B板的波特率也会是1200,与A板对应。
完成时结果如下:
(3)获取A板序列号
在A板、B板的波特率相同后,按下A板K3键,返回序列号(请一定注意是4字节)如下:
96 20 48 98
(4)使用串口通信程序,调用 write 函数接口向串口发送读密码命令。读密码命令格式为:
0xAA 0x55 A 板序列号 12 字节学号
A 板会回应密码,回应格式为:
0xAA 0x55 4 字节密码
回应密码会经过B板转发到计算机上。请调用read函数接口从串口读取该密码。
返回答案如下图所示:
密码为18 1C 99 F3
5、请将 A 板序列号、学号和密码通过 curl 命令发送到课程后台系统。
上送命令语法为
curl "132.232.98.70:6363/check485?id=学号&v=序列号&s=密码"
返回 OK。
4.6 RS485 总线数据收发
一、实验目的
1、熟练使用 Linux 下 io 函数 read、write 和 epoll 等
2、熟练处理流式通信数据
3、理解 485 总线的冲突问题
二、实验过程
(1)向单片机板下载程序
向 A 单片机板下载下面的程序
下载程序后,A 板单片机将使用 1200 波特率约每 300ms 发送一次自身序列号,格式为
0xAA 0x55 4 字节序列号
向 A 单片机板下载下面的程序
(2)通过 B 板串口向 RS485 总线写入自己的学号,格式为
0xAA 0x55 十二位学号数字。
(3) A 板单片机接收到学号后会每 300ms 发送第一串密码,密码长度为 4 字节。请将解析出该串密码并在 150ms 内原样发回给串口(否则会造成总线的冲突)。STC 单品机收到返回后会继续发送下一串密码,请继续解析出该串密码并在 150ms 内原样发回给串口。以此往复,将收到的最后一串密码记录下来。
由于人力无法实现满分,因此接下来编写代码来进行实验。
(4)编写python代码并获取结果
代码如下:
1. import serial
2. import serial.tools.list_ports
3. # 字节转字符串
4. def b2s(data):
5. return ''.join([f'{ch:0>2x}' for ch in data]).upper()
6. # 连接设备
7. ser = serial.Serial(list(serial.tools.list_ports.comports()[0])[0], 1200)
8. # 判断是否连接到设备
9. assert(ser != None)
10. # 输入学号
11. studentID = input("学号:")
12. # 判断学号是否正确
13. assert(studentID.isdigit() and len(studentID) == 12)
14. # 读入序列号
15. number = b2s(ser.read(6))
16. # 断言魔数为AA55
17. assert(number[:4] == "AA55")
18. # 取出序列号
19. number = number[4:]
20. # 判断序列号长度是否正确
21. assert(len(number) == 4 * 2)
22. print(f'序列号:{number}')
23. # 使用学号构造即将发送的字节数据
24. startData = b'\xaa\x55' + bytes([ord(ch) - ord('0') for ch in studentID])
25. # 写入数据
26. ser.write(startData)
27. password = b'' # 读到的密码
28. i = 1 # 记录循环次数
29. # 开启永真循环,直到Ctrl+C被按下
30. try:
31. while True:
32. data = ser.read_all()
33. sdata = b2s(data)
34. if data != b'' and sdata[:4] == "AA55":
35. password = data[-4:]
36. if len(password) == 4:
37. print(f'[{i}]密码:{b2s(password)}')
38. # 使用这次读到的密码构造数据,发送给设备以读取下一次的密码
39. ser.write(b'\xaa\x55' + password)
40. i += 1
41. # 当Ctr+C被按下时执行,建议在读到的密码不再变化时按下,大概在256次循环之后
42. except KeyboardInterrupt:
43. print(f'[结束]最后一串密码为:{b2s(password)}')
(5)获得结果并向服务器发送指令:
结果如下:
将学号、序列号、最后一串密码发送到课程后台。上述命令语法为
curl “132.232.98.70:6363/check485Secret?id=学号&v=序列号&s=密码”
使用curl指令提交答案,获取分数256,表明实验完美实现。
实验总结
通过本次计算机串口使用与测量实验,我获得了深入且实际的串口通信知识,并且在实际操作中进一步熟悉了相关技术和方法。实验不仅让我掌握了串口基本概念,还加深了对Linux操作系统及单片机编程的理解。
在实验过程中,我使用Linux操作系统进行了大量的文件操作,并通过单片机软件与硬件交互。这不仅加深了我对操作系统的熟悉,也让我更好地理解了计算机硬件与软件的协同工作方式。
我学习了如何通过编写程序,使用IO函数来实现串口的数据收发。通过实际编写串口数据收发程序,我体会到了如何处理串口数据,使用如write和read等函数进行数据读写。实验中,我特别关注了RS485接口的应用,通过半双工通信模式,成功实现了两块单片机间的数据传输。
在进行RS485通信时,我发现了数据冲突导致错误的情况,这使我认识到在编程时对错误处理的重要性。我通过Python编写程序来实现功能,意识到后续还需要进一步提高代码的性能及优化编程技巧。
总结来说,这次实验不仅增强了我对串口通信的理论知识和实际操作的理解,而且通过实验的即时反馈,如使用curl命令获取实验分数,极大地增强了我学习的动力和实验的互动性。未来我希望继续探索更多关于串口通信的深层次知识,并将这些知识应用到实际问题的解决中。