利用C#NET进行串口编程.docx

上传人:b****5 文档编号:8800526 上传时间:2023-05-15 格式:DOCX 页数:31 大小:78.44KB
下载 相关 举报
利用C#NET进行串口编程.docx_第1页
第1页 / 共31页
利用C#NET进行串口编程.docx_第2页
第2页 / 共31页
利用C#NET进行串口编程.docx_第3页
第3页 / 共31页
利用C#NET进行串口编程.docx_第4页
第4页 / 共31页
利用C#NET进行串口编程.docx_第5页
第5页 / 共31页
利用C#NET进行串口编程.docx_第6页
第6页 / 共31页
利用C#NET进行串口编程.docx_第7页
第7页 / 共31页
利用C#NET进行串口编程.docx_第8页
第8页 / 共31页
利用C#NET进行串口编程.docx_第9页
第9页 / 共31页
利用C#NET进行串口编程.docx_第10页
第10页 / 共31页
利用C#NET进行串口编程.docx_第11页
第11页 / 共31页
利用C#NET进行串口编程.docx_第12页
第12页 / 共31页
利用C#NET进行串口编程.docx_第13页
第13页 / 共31页
利用C#NET进行串口编程.docx_第14页
第14页 / 共31页
利用C#NET进行串口编程.docx_第15页
第15页 / 共31页
利用C#NET进行串口编程.docx_第16页
第16页 / 共31页
利用C#NET进行串口编程.docx_第17页
第17页 / 共31页
利用C#NET进行串口编程.docx_第18页
第18页 / 共31页
利用C#NET进行串口编程.docx_第19页
第19页 / 共31页
利用C#NET进行串口编程.docx_第20页
第20页 / 共31页
亲,该文档总共31页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

利用C#NET进行串口编程.docx

《利用C#NET进行串口编程.docx》由会员分享,可在线阅读,更多相关《利用C#NET进行串口编程.docx(31页珍藏版)》请在冰点文库上搜索。

利用C#NET进行串口编程.docx

利用C#NET进行串口编程

 

利用C#.NET进行串口编程

 

 

总算最后时间把【智能水电表】的项目啃下来了,总体来说这个项目技术难点不是特别多,主要是一个实现串口通讯的问题,其次就是水电表数据协议的解析问题。

目前已经开始在部署阶段了,利用休息时间将内容整理如下:

一、需求分析

1、水电表部署在家居中正常使用(当然水电表不是普通的家庭用表,而是智能家居用表,具有无线通信功能);

2、水电表通过无线通信协议将数据发送到家庭网关中;

3、家庭网关通过串口与PC机相连,通过串口通讯发给PC机接收;

4、PC机通过串口接收到网关传来的数据,进行解析显示,并存储在MySQL数据中(如何配置数据库已经在前面的

5、JSP页面读取MySQL中的数据,并显示;

6、烧录机顶盒内核,将JSP页面显示在电视机中。

二、串口编程

本项目的技术难点主要是获取串口数据,并依据现有的通信协议对数据包进行解析并显示。

之前有做过类似的串口编程用于WSN,但是现在才发现代码冗余量太大,而且不易于扩展,现在将总体过程整理如下:

2.1创建SerialPort实例

该步骤可以按照如下方式创建,当然也可以直接在工具箱中拖进SerialPort。

viewplaincopytoclipboardprint?

usingSystem.IO.Ports;

SerialPortserialport=newSerialPort();

usingSystem.IO.Ports;

SerialPortserialport=newSerialPort();

2.2列举可用的串口名

窗口首次加载时,我们将获取计算机上所有可用的串口名称并将这些名称添加到ComboBox控件里面。

双击窗体实现Form1_Load事件处理。

viewplaincopytoclipboardprint?

privatevoidForm1_Load(objectsender,EventArgse)

{

string[]portNames=SerialPort.GetPortNames();

for(inti=0;i

{

this.cbbPorts.Items.Add(portNames[i]);

}

this.cbbPorts.Items.Add(this.serialPort1.PortName);

this.btdisconn.Enabled=false;

}

privatevoidForm1_Load(objectsender,EventArgse)

{

string[]portNames=SerialPort.GetPortNames();

for(inti=0;i

{

this.cbbPorts.Items.Add(portNames[i]);

}

this.cbbPorts.Items.Add(this.serialPort1.PortName);

this.btdisconn.Enabled=false;

}

按照以下的方法经常会出现问题(比如不能获得正确的串口名称),后面通过查阅资料得出了以下的一个解决方案,首先需要引用Microsoft.VisualBasic,用以下遍历SerialPortNames,获得所有的串口:

viewplaincopytoclipboardprint?

privatevoidForm1_Load(objectsender,EventArgse)

{

this.timer1.Enabled=true;

serialport.DataReceived+=newSerialDataReceivedEventHandler(serialport_DataReceived);

Computerpc=newComputer();

string[]portNames=SerialPort.GetPortNames();

foreach(stringsinpc.Ports.SerialPortNames)

{

this.cbbPorts.Items.Add(s);

}

this.btdisconn.Enabled=false;

}

privatevoidForm1_Load(objectsender,EventArgse)

{

this.timer1.Enabled=true;

serialport.DataReceived+=newSerialDataReceivedEventHandler(serialport_DataReceived);

Computerpc=newComputer();

string[]portNames=SerialPort.GetPortNames();

foreach(stringsinpc.Ports.SerialPortNames)

{

this.cbbPorts.Items.Add(s);

}

this.btdisconn.Enabled=false;

}

注意还要添加DataReceived事件:

viewplaincopytoclipboardprint?

this.serialPort1.DataReceived+=newSystem.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);

this.serialPort1.DataReceived+=newSystem.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);

2.3打开串口

选择串口名后,用户点击【连接】按钮以打开所选择的端口,代码实现如下:

viewplaincopytoclipboardprint?

privatevoidbtconn_Click(objectsender,EventArgse)

{

if(this.serialPort1.IsOpen)

{

this.serialPort1.Close();

}

try

{

this.serialPort1.Encoding=System.Text.Encoding.Unicode;

this.serialPort1.Open();

this.lbMsg.Text=this.serialPort1.PortName.ToString()+"Connected.";

this.btconn.Enabled=false;

this.btdisconn.Enabled=true;

this.rtbData.BeginInvoke(newmyDelegate(updateTextBox));

this.lvdata.BeginInvoke(newmyDelegate(updateListView));

}

catch(Exceptionex)

{

//MessageBox.Show(ex.ToString());

return;

}

}

privatevoidbtconn_Click(objectsender,EventArgse)

{

if(this.serialPort1.IsOpen)

{

this.serialPort1.Close();

}

try

{

this.serialPort1.Encoding=System.Text.Encoding.Unicode;

this.serialPort1.Open();

this.lbMsg.Text=this.serialPort1.PortName.ToString()+"Connected.";

this.btconn.Enabled=false;

this.btdisconn.Enabled=true;

this.rtbData.BeginInvoke(newmyDelegate(updateTextBox));

this.lvdata.BeginInvoke(newmyDelegate(updateListView));

}

catch(Exceptionex)

{

//MessageBox.Show(ex.ToString());

return;

}

}

2.4断开串口连接

断开串口连接只需要调用一个方法即可。

viewplaincopytoclipboardprint?

privatevoidbtdisconn_Click(objectsender,EventArgse)

{

try

{

this.serialPort1.Close();

this.lbMsg.Text=this.serialPort1.PortName+"Disconnected.";

this.btconn.Enabled=true;

this.btdisconn.Enabled=false;

}

catch(Exceptionex)

{

//MessageBox.Show(ex.ToString());

return;

}

}

privatevoidbtdisconn_Click(objectsender,EventArgse)

{

try

{

this.serialPort1.Close();

this.lbMsg.Text=this.serialPort1.PortName+"Disconnected.";

this.btconn.Enabled=true;

this.btdisconn.Enabled=false;

}

catch(Exceptionex)

{

//MessageBox.Show(ex.ToString());

return;

}

}

2.5接收串口的数据

SerialPort类的一个良好的特性是,无需不断的查询数据是否已经到达,而只需处理DataReceived事件,它将在检测到数据到达时自动触发,不过,因为事件运行在独立的线程里,任何试图直接更新主窗体的尝试都会引发错误,因此,需要使用一个代理来更新主线程里的控件(这个尤为重要,否则一切都白搭)。

viewplaincopytoclipboardprint?

privatevoidserialport_DataReceived(Objectsender,SerialDataReceivedEventArgse)

{

this.rtbData.BeginInvoke(newmyDelegate(updateTextBox));

this.lvdata.BeginInvoke(newmyDelegate(updateListView));

}

privatevoidserialport_DataReceived(Objectsender,SerialDataReceivedEventArgse)

{

this.rtbData.BeginInvoke(newmyDelegate(updateTextBox));

this.lvdata.BeginInvoke(newmyDelegate(updateListView));

}

定义代理如下所示:

viewplaincopytoclipboardprint?

publicdelegatevoidmyDelegate();

publicvoidupdateTextBox()

{

try

{

//求出需要读取的Bytes数

//intbytesToRead=serialport.BytesToRead;

intbytesToRead=this.serialPort1.BytesToRead;

//声明char数组

byte[]ch=newbyte[bytesToRead];

//char[]ch1=newchar[bytesToRead];

intbytesRead=0;

//将读取到的bytes存储在ch数组中

//bytesRead=serialport.Read(ch,0,bytesToRead);

bytesRead=this.serialPort1.Read(ch,0,bytesToRead);

//bytesRead=this.serialPort1.Read(ch1,0,bytesToRead);

//将ch数组转换为string类型

str=this.ByteArrayToHexString(ch).Replace("","").Trim();

//str=newstring(ch1,0,bytesRead);

//测试代码

//str="5353535342621708005262000704000000000000E9F245";

//将string类型放置在文本框中

this.rtbData.AppendText(str);

//MessageBox.Show(str.Length.ToString());

this.rtbData.ScrollToCaret();

stringrtbstr=this.rtbData.Text.ToString();

if((rtbstr.Length>=46)&&(rtbstr.IndexOf("5353535342")

{

stringstrnew=rtbstr.Substring(rtbstr.IndexOf("5353535342"),46);

if(strnew.Substring(44,2).Trim().ToString()=="45")

{

DataAnalyse(strnew);

this.rtbData.BeginInvoke(newmyDelegate(clearTextBox));

}

}

else

{

this.rtbData.BeginInvoke(newmyDelegate(clearTextBox));

}

DataStore();

}

catch(Exceptionex)

{

//MessageBox.Show(ex.ToString());

return;

}

}

publicvoidupdateListView()

{

try

{

if(this.TableID.ToString().Trim()!

="")

{

ListViewItemlist=newListViewItem();

list.Text=TableID;

list.SubItems.Add(TableID);

list.SubItems.Add(ReadFlag);list.SubItems.Add(TableType);

list.SubItems.Add(TableState);list.SubItems.Add(TableNum);

list.SubItems.Add(PreNum);list.SubItems.Add(CRCNum);

list.SubItems.Add(date);

list.SubItems.Add(DataTail);

this.lvdata.Items.Add(list);

}

}

catch(Exceptionex)

{

//MessageBox.Show(ex.Message.ToString());

//throw;

return;

}

}

publicdelegatevoidmyDelegate();

publicvoidupdateTextBox()

{

try

{

//求出需要读取的Bytes数

//intbytesToRead=serialport.BytesToRead;

intbytesToRead=this.serialPort1.BytesToRead;

//声明char数组

byte[]ch=newbyte[bytesToRead];

//char[]ch1=newchar[bytesToRead];

intbytesRead=0;

//将读取到的bytes存储在ch数组中

//bytesRead=serialport.Read(ch,0,bytesToRead);

bytesRead=this.serialPort1.Read(ch,0,bytesToRead);

//bytesRead=this.serialPort1.Read(ch1,0,bytesToRead);

//将ch数组转换为string类型

str=this.ByteArrayToHexString(ch).Replace("","").Trim();

//str=newstring(ch1,0,bytesRead);

//测试代码

//str="5353535342621708005262000704000000000000E9F245";

//将string类型放置在文本框中

this.rtbData.AppendText(str);

//MessageBox.Show(str.Length.ToString());

this.rtbData.ScrollToCaret();

stringrtbstr=this.rtbData.Text.ToString();

if((rtbstr.Length>=46)&&(rtbstr.IndexOf("5353535342")

{

stringstrnew=rtbstr.Substring(rtbstr.IndexOf("5353535342"),46);

if(strnew.Substring(44,2).Trim().ToString()=="45")

{

DataAnalyse(strnew);

this.rtbData.BeginInvoke(newmyDelegate(clearTextBox));

}

}

else

{

this.rtbData.BeginInvoke(newmyDelegate(clearTextBox));

}

DataStore();

}

catch(Exceptionex)

{

//MessageBox.Show(ex.ToString());

return;

}

}

publicvoidupdateListView()

{

try

{

if(this.TableID.ToString().Trim()!

="")

{

ListViewItemlist=newListViewItem();

list.Text=TableID;

list.SubItems.Add(TableID);

list.SubItems.Add(ReadFlag);list.SubItems.Add(TableType);

list.SubItems.Add(TableState);list.SubItems.Add(TableNum);

list.SubItems.Add(PreNum);list.SubItems.Add(CRCNum);

list.SubItems.Add(date);

list.SubItems.Add(DataTail);

this.lvdata.Items.Add(list);

}

}

catch(Exceptionex)

{

//MessageBox.Show(ex.Message.ToString());

//throw;

return;

}

}

2.6传输Unicode字符

默认情况下,SerialPort类只传输ASCII字符,这是通过SerialPort类的Encoding属性设置的,如果你想传输另一种语言,就需要设置SerialPort类的Encoding属性为Unicode,以保证数据的正常发送与接收。

2.7串口发送数据

要通过串口向接收者发送数据,使用SerialPort类的Write()方法即可。

viewplaincopytoclipboardprint?

privatevoidbtrefresh_Click(objectsender,EventArgse)

{

try

{

this.serialPort1.Write(this.tbsend.Text.ToString()+Environment.NewLine);

tbsend.Text=string.Empty;

}

catch(Exceptionex)

{

}

}

privatevoidbtrefresh_Click(objectsender,EventArgse)

{

try

{

this.serialPort1.Write(this.tbsend.Text.ToString()+Environment.NewLine);

tbsend.Text=string.Empty;

}

catch(Exceptionex)

{

}

}

三、运行测试

由于今天图片上传功能暂时关闭,所以不能上传图片,所有的代码如下所示:

viewplaincopytoclipboardprint?

usingSystem;

usingSystem.Collections.Gene

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2