微机原理及应用课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
微机原理及应用
课程设计
设计题目:基于PC机串行通信的点到点文
件传输系统
专业计算机科学与技术
班级计104
学生 D
指导教师
2013 年秋季学期
目录
目录 (2)
一、实验目的 (3)
二、实验内容及要求 (3)
三、课设基本思想 (3)
四、程序流程图以及程序设计 (5)
(一)、程序流程图: (5)
(二)、程序设计思想: (5)
五.实验结果截图 (6)
六.程序源代码 (7)
七.课程设计心得体会 (14)
八.参考文献 (15)
一、实验目的
1.学习虚拟串口的使用方法。
2.学会在windows平台上进行串口通信的方法。
二、实验内容及要求
1.基本要求:采用VB,VC,C#或其他开发工具设计一个简易的聊天系统。
用户可以设置波特率或采用自动协商机制。
界面如下图:
2.设计提示:在Windows平台上通过API或MSComn控件实现串行通信。
3.进一步设计要求:采用多线程完成通信任务。
三、课设基本思想
1.在.NET平台下使用C#创建串口通信程序,.NET
2.0提供了串口通信的功能,其命名空间是System.IO.Ports。
这个新的框架不但可以访问计算机上的串口,还可以和串口设备进行通信。
我们将使用标准的RS 232 C 在PC间通信。
它工作在全双工模式下,而且我们不打算使用任何的握手或流控制器,而是使用无modem连接。
2.串口的硬件知识:
在数据传输的时候,每个字节的数据通过单个的电缆线传输。
包包括开始位,数据,结束为。
一旦开始位传出,后面就会传数据,可能是5,6,7或8位,就看你的设定了。
发送和接收必须设定同样的波特率和数据位数。
3.关于本程序使用SerialPort的一些属性和方法:
属性:
四、程序流程图以及程序设计(一)、程序流程图:
(二)、程序设计思想:
首先需要定义一个SerialPort对象,添加DataReceived事件响应收到数据。
然后利用系统提供函数获取当前端口号,以及用户选择的波特率,对对象进行初始化。
通过两边建立起来的串口连接的缓冲区,进行数据的交互。
这样便实现里串口点对点的字符串聊天。
对于实现二进制文件的传输,主要通过的是利用list<>来进行缓冲区数据的读取,同时自己约定好所用的文件协议。
通过对数组文件的分析来判断是否是合法的数据,通过对校验位的检查确定是否是正确的数据,对于不正确的数据,我采用的是直接丢弃不予处理的政策。
至此,便是整个程序的基本思想。
五.实验结果截图程序主界面:
设置界面:
运行结果:
六.程序源代码
1.主界面部分:
using System;
using System.Collections.Generic; using ponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;
namespace windows_test
{
public partial class Main : Form
{
private SerialPort sp = new SerialPort();
private StringBuilder TheString = new StringBuilder();
private bool Listening = false;//是否没有执行完invoke相关操作
private bool Closing = false;//是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke
public static string[] ports;
private List<byte> buffer = new List<byte>(4096);
private byte[] B_data=new byte[10];//自定义数据格式,由2个字节的头文件+一个字节的长度+最后一位的校验位而来DD 22 06 11 22 33 44 55 66 8E
public Main()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ports = SerialPort.GetPortNames();//得到可用端口名字
Array.Sort(ports);//将它们排序
sp.DataReceived += sp_DataReceived;//调用DataReceived事件
sp.NewLine = "\r\n";
btn_Send.Enabled = sp.IsOpen;//通过串口的打开与否控制控件显示
checkbox_data.enabled = false;
// sp.encoding = system.text.encoding.getencoding("gb2312");转换字符编码
}
void sp_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
//////////////////Version.1无法避免死锁/////////////////
//int n=sp.BytesToRead;第一次书写的代码无法避免2个线程的死锁
//byte[] buff= new byte[n];
//sp.Read(buff,0,n);
//TheString.Clear();
//this.Invoke((EventHandler)(delegate{
// TheString.Append(Encoding.ASCII.GetString(buff));
// this.txtGet.AppendText(TheString.ToString());
//}));
//////////////////Version.2解决问题/////////////////////
if (Closing)
return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
try
{
Listening = true;//设置标记
int n = sp.BytesToRead;//读取缓冲区字符数
byte[] buff = new byte[n];
sp.Read(buff, 0, n);//读出缓冲区数据
TheString.Clear();
bool data_catched = false;
buffer.AddRange(buff);
while (buffer.Count >= 4)//至少要包含4个字节的固定格式
{
if (buffer[0] == 0xDD && buffer[1] == 0x22)//检查头文件
{
int len = buffer[2];//得到长度
if (buffer.Count < len + 4) break;
byte sum = 0;
for (int i = 0; i < len + 3; i++)
{
sum ^= buffer[i];//通过异或校验得到校验码
}
if (sum != buffer[len + 3])
{
buffer.RemoveRange(0, len + 4);//校验结果不对则直接丢弃
continue;
}
buffer.CopyTo(0, B_data, 0, len + 4);//若数据符合,便将其拷贝至数据缓冲
data_catched = true;//设置标记
buffer.RemoveRange(0, len + 4);//移出正确的数据
}
else
{
buffer.RemoveAt(0);//若数据不是开头则删除之
}
}
if (data_catched)
{
string data = B_data[3].ToString("X2") + " " + B_data[4].ToString("X2") + " " +
B_data[5].ToString("X2") + " " + B_data[6].ToString("X2")
+ " " +
B_data[7].ToString("X2")+ " " +B_data[8].ToString("X2");//由于格式已经规定好,因此可以直接读取数据,通过StringFormat选择16进制2位。
this.Invoke((EventHandler)(delegate { txtData.Text = data; }));//更新界面
}
//string output
TheString.Clear();
this.Invoke((EventHandler)(delegate
{
TheString.Append(Encoding.ASCII.GetString(buff));
this.txtGet.AppendText(TheString.ToString());
}));//将读到的字符串显示到发送数据文本框中
}
finally
{
Listening = false;//设置标志,通知ui可以关闭串口
}
}
private void open_Click(object sender, EventArgs e)//通过按键来初始串口 {
if (sp.IsOpen)
{
Closing = true;
while (Listening)
Application.DoEvents();
sp.Close();
Closing = false;
}
else
{
try
{
sp.PortName = Setting.get_port;
sp.BaudRate = int.Parse(Setting.get_baudrate);
sp.Open();
}
catch (Exception ex)
{
sp = new SerialPort();
MessageBox.Show("请先单击\"设置\" 设置串口参数","警告",MessageBoxButtons.OK);
}
}
btn_Open.Text = sp.IsOpen ? "关闭连接" : "打开连接";//通过3目运算控制按键显示
btn_Send.Enabled = sp.IsOpen;
}
private void Send_Click(object sender, EventArgs e)
{
int n = 0;
try
{
if (checkBox_line.Checked)
{
sp.WriteLine(Setting.get_port + " : " + DateTime.Now + " > " + txtSend.Text);//若勾选单行发送,则显示数据来源端口和时间
n = txtSend.Text.Length + 2;
}
else
{
sp.Write(txtSend.Text);//写入到缓冲区
n = txtSend.Text.Length;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btn_Setting_Click(object sender, EventArgs e)
{
Setting s = new Setting();
s.Show();
this.Visible=false;
}
private void btn_Reset_Click(object sender, EventArgs e)
{
txtGet.Text = "";
txtSend.Text = "";
}
private void btn_Exit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void checkBox_line_CheckedChanged(object sender, EventArgs e)
{
txtGet.WordWrap = checkBox_line.Checked;
}
七.课程设计心得体会
在这一周的课设中,让我对微机原理的课程有了更加深入的了解,使我对串口实现字符串的传送和数据的收发有了进一步的掌握。
在初次拿到题目的时候,由于以前的编程主要面向的是软件,而这次是面向硬件。
因此开始课设的时候,脑子里面是一团雾水,不知道从何出去下手,也不知道要到达怎样的目标。
经过一天的上网查找资料,渐渐的让我明白了串口通信的基本实现方法。
在之后的几天中,我通过这学期学习的c#的知识和微机知识,将两者结合起来,实现了界面的搭建和逻辑的选择。
对于遇到的不会使用的方法和属性就在MSDN中查询了解。
而且我也学习到了SerialPort类的使用,以及其各种参数(串口名、波特率、停止位、校验位、停止位等)的设置方式。
经过熟能生巧的过程使我对于C#串口通信有了一定程度的了解。
当然在开发过程中也不是一帆风顺的,遇到了很多麻烦,例如缓冲区的读取异常,程序逻辑异常等等。
通过不断的去查资料,翻阅书籍,让我收获了很多很多,也提高了我关于分析问题,解决问题的能力。
计算机专业的学生我觉得对于如何利用网络资源解决自身问题,是至关重要的。
人只有在不断的努力学习和查找中才可以进步。
因此,我觉得这次课设之于我来说是意义非凡的,不仅使我了解知识提升了能力,还使我对于未来的计算机相关硬件开发有了好感,对于我将来的学习也有着指导意义。
八.参考文献
[1] 钱晓捷,陈涛,《16/32位微机原理、汇编语言及接口技术(第二)》,北京,机械
工业出版社,2005
[2] 周艳萍,邹伟,《汇编语言程序设计教程》,北京,清华大学出版社,2007
欢迎下载,资料仅供参考!!!
资料仅供参考!!!。