紫外工控论坛

 找回密码
 立即注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
查看: 3467|回复: 0

(SerialPort)串口编程知识整理:(一)基本概念和项目实践概述

[复制链接]
冰糖 发表于 2010-8-2 22:53:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
1、基本概念
      MS .NET FrameWork2.0中对串口通讯进行了封装,我们可以在.net2.0及以上版本开发时直接使用SerialPort类对串口进行读写操作。
SerialPort类的属性主要包括:
串口名称(PortName

波特率(BaudRate
数据位 DataBits
停止位 StopBits
奇偶校验 Parity
握手协议 Handshake
SerialPort类的事件主要包括:
DataReceived:用于异步接收串口数据
SerialPort类的方法主要包括:
Open();Close();Read();Write()等。
相关内容可以参考MSDN或者博文

2、需求和场景介绍

本文是基于之前开发的一个油站项目,主要功能是实现对加油机数据的采集和对加油机的一些控制,例如停开机、设置单价、定量定额加油等操作。
系统通过PC机串口,与下位机进行通讯,下位机和加油机进行通讯,负责采集加油机数据和控制加油机的操作。

3、设计思想
         (1)在界面设计上,由于系统启动后要始终实时监控加油数据,采用了SDI展示方式。
截图如下:



   (2)在系统设计方面,加油机监控软件具有一定的实时性、稳定性和数据并发的非功能性需求。所以在对加油数据采集时,使用事件DataReceived,用于异步接收串口数据。使用watchdog方式监控系统消息,通过缓存池对数据进行过滤,减轻数据库的压力,提高系统性能。


4、代码演示

系统采用CS结构,使用SerialPort类进行串口通讯。对SerialPort类进行了封装,以保证多个窗体间对串口实例的调用。

封装的串口通讯类参考:http://blog.csdn.net/yefanqiu/archive/2007/03/27/1543187.aspx



串口通讯类:SerialPortDao.cs /*----------------------------------------------------------------
           // Copyright (C) 北京****科技有限公司
           // 版权所有。
           //
           // 文件名:SerialPortDao
           // 文件功能描述:封装串口组件,实现对串口的统一访问和操作
           //
           //
           // 创建标识:** 2009-5-23
           //
           // 修改标识:**
           // 修改描述:
//----------------------------------------------------------------
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;

namespace LY.FuelStationPOS.Protocol
{
   
///
<summary>
/// 提供对串口的统一访问
   
///
</summary>

public
sealed
class SerialPortDao
    {
        
#region 事件和字段定义
public
event PortDataReceivedEventHandle Received;
        
public SerialPort serialPort =
null;
        
public
bool ReceiveEventFlag =
false;  //接收事件是否有效 false表示有效

private
static
readonly SerialPortDao instance =
new SerialPortDao();

        
#endregion
#region 属性定义
private
string protName;
        
public
string PortName
        {
            
get { return serialPort.PortName; }
            
set
            {
                serialPort.PortName
= value;
                protName
= value;
            }
        }
        
#endregion
#region 构造函数
private SerialPortDao()
        {
            LoadSerialPort();
        }

        
private
void LoadSerialPort()
        {
            serialPort
=
new SerialPort();
            serialPort.BaudRate
=
9600;
            serialPort.Parity
= Parity.Even;
            serialPort.DataBits
=
8;
            serialPort.StopBits
= StopBits.One;
            serialPort.Handshake
= Handshake.None;
            serialPort.RtsEnable
=
true;
            serialPort.ReadTimeout
=
2000;
            serialPort.DataReceived
+=
new SerialDataReceivedEventHandler(DataReceived);
        }

      
        
#endregion

#region 串口操作集合
///
<summary>
/// 返回串口对象的单个实例
        
///
</summary>
///
<returns></returns>

public
static SerialPortDao GetSerialPortDao()
        {         
            
return instance;
        }      

        
///
<summary>
/// 释放串口资源
        
///
</summary>

~SerialPortDao()
        {
            Close();
        }

        
///
<summary>
/// 打开串口
        
///
</summary>

public
void Open()
        {
            
try
            {
               
if (!serialPort.IsOpen)
                {
                    serialPort.Open();                    
                }
            }
            
catch (Exception ex)
            {
               
throw ex;
            }           
        }

        
///
<summary>
/// 关闭串口
        
///
</summary>

public
void Close()
        {
            
if (serialPort.IsOpen)
            {
                serialPort.Close();
            }
        }

        
///
<summary>
/// 串口是否打开
        
///
</summary>
///
<returns></returns>

public
bool IsOpen()
        {
            
return serialPort.IsOpen;
        }

      

        
///
<summary>
/// 数据发送
        
///
</summary>
///
<param name="data">要发送的数据字节</param>

public
void SendData(byte[] data)
        {
            
try
            {
                serialPort.DiscardInBuffer();
                serialPort.Write(data,
0, data.Length);
            }
            
catch (Exception ex)
            {
               
throw ex;
            }
        }

        
///
<summary>
/// 发送命令
        
///
</summary>
///
<param name="SendData">发送数据</param>
///
<param name="ReceiveData">接收数据</param>
///
<param name="Overtime">超时时间</param>
///
<returns></returns>

public
int SendCommand(byte[] SendData, ref
byte[] ReceiveData, int Overtime)
        {
            
if (serialPort.IsOpen)
            {
               
try
                {
                    ReceiveEventFlag
=
true;        //关闭接收事件
                    serialPort.DiscardInBuffer();   //清空接收缓冲区                 
                    serialPort.Write(SendData, 0, SendData.Length);
                    System.Threading.Thread.Sleep(
50);
                    
int num =
0, ret =
0;
                    
while (num++
< Overtime)
                    {
                        
if (serialPort.BytesToRead >= ReceiveData.Length)
                        {
                           
break;
                        }
                        System.Threading.Thread.Sleep(
50);
                    }
                    
if (serialPort.BytesToRead >= ReceiveData.Length)
                    {
                        ret
= serialPort.Read(ReceiveData, 0, ReceiveData.Length);
                    }
                    
else
                    {
                        ret
= serialPort.Read(ReceiveData, 0, serialPort.BytesToRead);
                    }
                    ReceiveEventFlag
=
false;       //打开事件

return ret;
                }
               
catch (Exception ex)
                {
                    ReceiveEventFlag
=
false;
                    
throw ex;
                }
            }
            
return
-1;
        }

        
///<summary>
///数据发送
        
///</summary>
///<param name="data">要发送的数据字符串</param>

public
void SendData(string data)
        {
            
//禁止接收事件时直接退出

if (ReceiveEventFlag)
            {
               
return;
            }
            
if (serialPort.IsOpen)
            {
                serialPort.Write(data);
            }
        }

         
///<summary>
///将指定数量的字节写入输出缓冲区中的指定偏移量处。
         
///</summary>
///<param name="data">发送的字节数据</param>
///<param name="offset">写入偏移量</param>
///<param name="count">写入的字节数</param>

public
void SendData(byte[] data, int offset, int count)
        {
            
//禁止接收事件时直接退出

if (ReceiveEventFlag)
            {
               
return;
            }
            
if (serialPort.IsOpen)
            {
                serialPort.Write(data, offset, count);
            }
        }
               

        
///
<summary>
/// 数据接收
        
///
</summary>
///
<param name="sender"></param>
///
<param name="e"></param>

public
void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            
//禁止接收事件时直接退出

if (ReceiveEventFlag)
            {
               
return;
            }

            
try
            {
               
byte[] data =
new
byte[serialPort.BytesToRead];
                serialPort.Read(data,
0, data.Length);
               
if (Received !=
null)
                {
                    Received(sender,
new PortDataReciveEventArgs(data));
                }
            }
            
catch (Exception ex)
            {
               
//throw ex;
            }
            
        }
    }
}



串口通讯数据类:PortDataReciveEventArgs /*----------------------------------------------------------------
           // Copyright (C) 北京****科技有限公司
           // 版权所有。
           //
           // 文件名:PortDataReciveEventArgs
           // 文件功能描述:重写PortDataReciveEventArgs参数类
           //
           //
           // 创建标识:** 2009-5-23
           //
           // 修改标识:
           // 修改描述:
           //
           // 修改标识:
           // 修改描述:
//----------------------------------------------------------------
*/
using System;
using System.Collections.Generic;
using System.Text;

namespace LY.FuelStationPOS.Protocol
{
   
public
delegate
void PortDataReceivedEventHandle(object sender, PortDataReciveEventArgs e);

   
public
class PortDataReciveEventArgs : EventArgs
    {
        
private
byte[] data;

        
public
byte[] Data
        {
            
get { return data; }
            
set { data = value; }
        }

        
public PortDataReciveEventArgs()
        {
            
this.data =
null;
        }

        
public PortDataReciveEventArgs(byte[] data)
        {
            
this.data = data;
        }

        
    }
}




5、声明
     本文来源于实际项目,并且系统的串口通讯很稳定,各位朋友可以放心使用。本文的参考内容都已经标示,如果有任何问题欢迎回复。
     接下来准备要分享的内容包括:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


--------------------------------------------------------------------------------------------------------------------
本站是工控技术交流站点,论坛内容均为网络收集或会员所发表,并不代表本站立场,会员拥有该内容的所有权力及责任!
本站内容如有侵犯您的版权,请按下面方式联系本站管理员,我们将及时删除处理
管理员:冰糖 QQ:5483695(请直击主题), Mail:admin#ziwai.net(#改成@) 其它非本人.
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论!

QQ|Archiver|手机版|小黑屋|紫外工控论坛. ( 苏ICP备11032118号-1 )

GMT+8, 2024-5-5 06:51 , Processed in 0.906261 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表