高分请教串口问题 ( 积分: 200 )

  • 主题发起人 主题发起人 dingjiabao
  • 开始时间 开始时间
D

dingjiabao

Unregistered / Unconfirmed
GUEST, unregistred user!
第一个问题是 Resources.resx中的资源,比如一个图像文件的persistence属性
可选"在编译时链接" 或 "嵌入在 .resx 中" 这两者的具体区别(希望高手说的原理一点, 哪一种性能更好) 还有平时我看到有的应用程序,它所用到的资源文件,就放在程序的安装目录之下, 这种情况对应persistence属性的哪一种值? 性能如何?
第二个问题是,我将要对多台仪表发送多种格式的命令,
命令: CC A1 01 Data1L Data1H Data2L Data2H 各校验 类似的多种命令
我的解决方法是 定义一个 enumeration 其中每个成员表示一种命令,
public enum Flag { IsNull, IsStop, IsAscDesc, IsReadStateWord, IsReadData, IsReadEnactment };发送的时候(用VS2005的System.IO.Ports.SerialPort), 比如发送停止命令:
byte[] bytes_Stop = new byte[] { 0xAA, 0x50, MeterAddress, 0};
SumCheck(ref bytes_Stop);
//和校验
serialPort2.Write(bytes_Stop, 0, 4);
flag = Flag.IsStop;
在DataReceive事件中使用开关语句
switch (this.flag)
{
case Flag.IsReadEnactment: //读设定
Recv_Enactment_Handle();
break;
case Flag.IsReadData: //读数据
Recv_Data_Handle();
break;
case Flag.IsReadStateWord: //读状态字
Recv_StateWord_Handle();
break;
case Flag.IsAscDesc: //升降控制
Recv_AscDesc_Handle();
break;
case Flag.IsStop:
Recv_Stop_Handle();
break;
case Flag.IsNull: //未知数据的处理
serialPort2.DiscardInBuffer();
break;
}//分别做出不同处理
当程序运行起来就打开串口,并启动一个线程发送:
while (serialPort2.IsOpen &&
b_Read)
{
byte[] bytes_ReadData = new byte[] { 0xAA, 0x55, MeterAddress, 0 };
SumCheck(ref bytes_ReadData);
serialPort2.Write(bytes_ReadData, 0, 4);
flag = Flag.IsReadData;
Thread.Sleep(Interval);
//这个地方,我觉得写得不好,请高手指教
}
这第二个问题就是大家来评说一下这样一个结构来做串口行吗? 缺点何在? 我自已在写的过程中觉得这个结构并不好, 如果用同步IO或异步IO要怎么做?
第三个问题是 老板提出的另一种结构 当发送一个命令过去后就判断并读取, 三次读不到就认为超时 这个用代码怎么实现
可以加QQ说: 14409071
不够可以加分, 大家关注一下
 
不够可以加分, 大家关注一下
 
自己顶起来不然被别的贴子活埋了~~~~
 
DFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFWDFW
 
侠客行
李白
赵客缦胡缨 吴钩霜雪明
银鞍照百马 飒踏如流星
十步杀一人 千里不留行
事了拂衣去 深藏身与名
闲过信陵饮 脱剑膝前横
将炙啖朱亥 持殇劝侯赢
三杯吐然诺 五岳倒为轻
眼花耳热后 意气素霓生
救赵挥金槌 邯郸先震惊
千秋二壮士 煊赫大梁城
纵死侠骨香 不惭世上英
谁能书阁下 白首太玄经
 
希望大家发扬点侠客精神, 帮帮小弟
 
苦等三小时中...
 
第三个问题是 老板提出的另一种结构 当发送一个命令过去后就判断并读取, 三次读不到就认为超时 这个用代码怎么实现
你发送命令后记录时间,然后就是延迟循环.比较当前时间和发送时记录的时间,如果超过设定值就超时了.
 
谢谢,你是第一个回答的, 但是我想看到代码, 用记时的会会降低很多性能?
 
应该影响很少。
b:=now;
repeat
application.processmessage;
until b-now>=(1/(24*3600));//1秒
 
嗯,这块代码对我有点启发
 
自己解决了, 原因是在主线程使用了Thread.Sleep();
感觉像是整个程序都在Sleeping
 
串口通讯可以引出kernel32.dll中的API来操作,相关源码如下:
using System;
using System.Runtime.InteropServices;
namespace Telehome.GSM
{
/// <summary>
/// ************************************************************************************
///
/// Function: 连接,断开串口;发送,接收串口数据,使用kernel32.dll中相关串口操作
/// 函数对COM口进行操作
///
/// Author: Telehome.Hzyong
///
/// DateTime: 2005-11-20
///
/// ************************************************************************************
/// </summary>
public class CommPort
{
/// <summary>
/// 端口名称(COM1,COM2...COM4...)
/// </summary>
public string PortNum;

/// <summary>
/// 波特率9600
/// </summary>
public int BaudRate;
/// <summary>
/// 数据位4-8
/// </summary>
public byte ByteSize;
/// <summary>
/// 奇偶校验0-4=no,odd,even,mark,space
/// </summary>
public byte Parity;

/// <summary>
/// 停止位
/// </summary>
public byte StopBits;
// 0,1,2 = 1, 1.5, 2
/// <summary>
/// 超时长
/// </summary>
public int ReadTimeout;
/// <summary>
/// COM口句柄
/// </summary>
private int hComm = -1;
/// <summary>
/// 串口是否已经打开
/// </summary>
public bool Opened = false;

/// <summary>
/// WINAPI常量,写标志
/// </summary>
private const uint GENERIC_READ = 0x80000000;
/// <summary>
/// WINAPI常量,读标志
/// </summary>
private const uint GENERIC_WRITE = 0x40000000;
/// <summary>
/// WINAPI常量,打开已存在
/// </summary>
private const int OPEN_EXISTING = 3;
/// <summary>
/// WINAPI常量,无效句柄
/// </summary>
private const int INVALID_HANDLE_VALUE = -1;

/// <summary>
/// 设备控制块结构体类型
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct DCB
{
/// <summary>
/// DCB长度
/// </summary>
public int DCBlength;
/// <summary>
/// 指定当前波特率
/// </summary>
public int BaudRate;
/// <summary>
/// 指定是否允许二进制模式
/// </summary>
public int fBinary;
/// <summary>
/// 指定是否允许奇偶校验
/// </summary>
public int fParity;
/// <summary>
/// 指定CTS是否用于检测发送控制,当为TRUE是CTS为OFF,发送将被挂起。
/// </summary>
public int fOutxCtsFlow;
/// <summary>
/// 指定CTS是否用于检测发送控制
/// </summary>
public int fOutxDsrFlow;
/// <summary>
/// DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手"
/// </summary>
public int fDtrControl;
/// <summary>
/// 当该值为TRUE时DSR为OFF时接收的字节被忽略
/// </summary>
public int fDsrSensitivity;
/// <summary>
/// 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送是否停止。
/// TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送出
/// XoffChar字符中止接收字节之后,发送继续进行。 FALSE时,在接收缓冲区接
/// 收到代表缓冲区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之
/// 后,发送继续进行。XOFF continues Tx
/// </summary>
public int fTXContinueOnXoff;
/// <summary>
/// TRUE时,接收到XoffChar之后便停止发送接收到XonChar之后将重新开始 XON/XOFF
/// out flow control
/// </summary>
public int fOutX;
/// <summary>
/// TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去接收
/// 缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去 XON/XOFF in flow control
/// </summary>
public int fInX;
/// <summary>
/// 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误
/// 的接收字符 enable error replacement
/// </summary>
public int fErrorChar;
/// <summary>
/// eTRUE时,接收时去掉空(0值)字节 enable null stripping
/// </summary>
public int fNull;
/// <summary>
/// RTS flow control RTS_CONTROL_DISABLE时,RTS置为OFF RTS_CONTROL_ENABLE时, RTS置为ON
/// RTS_CONTROL_HANDSHAKE时,当接收缓冲区小于半满时RTS为ON当接收缓冲区超过四分之
/// 三满时RTS为OFF RTS_CONTROL_TOGGLE时,当接收缓冲区仍有剩余字节时RTS为ON ,否则
/// 缺省为OFF
/// </summary>
public int fRtsControl;
/// <summary>
/// TRUE时,有错误发生时中止读和写操作 abort on error
/// </summary>
public int fAbortOnError;
/// <summary>
/// 未使用
/// </summary>
public int fDummy2;
/// <summary>
/// 标志位
/// </summary>
public uint flags;
/// <summary>
/// 未使用,必须为0
/// </summary>
public ushort wReserved;
/// <summary>
/// 指定在XON字符发送这前接收缓冲区中可允许的最小字节数
/// </summary>
public ushort XonLim;
/// <summary>
/// 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数
/// </summary>
public ushort XoffLim;
/// <summary>
/// 指定端口当前使用的数据位
/// </summary>
public byte ByteSize;
/// <summary>
/// 指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY 0-4=no,odd,even,mark,space
/// </summary>
public byte Parity;
/// <summary>
/// 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS 0,1,2 = 1, 1.5, 2
/// </summary>
public byte StopBits;
/// <summary>
/// 指定用于发送和接收字符XON的值 Tx and Rx XON character
/// </summary>
public char XonChar;
/// <summary>
/// 指定用于发送和接收字符XOFF值 Tx and Rx XOFF character
/// </summary>
public char XoffChar;
/// <summary>
/// 本字符用来代替接收到的奇偶校验发生错误时的值
/// </summary>
public char ErrorChar;
/// <summary>
/// 当没有使用二进制模式时,本字符可用来指示数据的结束
/// </summary>
public char EofChar;
/// <summary>
/// 当接收到此字符时,会产生一个事件
/// </summary>
public char EvtChar;
/// <summary>
/// 未使用
/// </summary>
public ushort wReserved1;
}
/// <summary>
/// 串口超时时间结构体类型
/// </summary>
[StructLayout(LayoutKind.Sequential)]
private struct COMMTIMEOUTS
{
public int ReadIntervalTimeout;
public int ReadTotalTimeoutMultiplier;
public int ReadTotalTimeoutConstant;
public int WriteTotalTimeoutMultiplier;
public int WriteTotalTimeoutConstant;
}
/// <summary>
/// 湓出缓冲区结构体类型
/// </summary>
[StructLayout(LayoutKind.Sequential)]
private struct OVERLAPPED
{
public int Internal;
public int InternalHigh;
public int Offset;
public int OffsetHigh;
public int hEvent;
}

/// <summary>
/// 打开串口
/// </summary>
/// <param name="lpFileName">要打开的串口名称</param>
/// <param name="dwDesiredAccess">指定串口的访问方式,一般设置为可读可写方式</param>
/// <param name="dwShareMode">指定串口的共享模式,串口不能共享,所以设置为0</param>
/// <param name="lpSecurityAttributes">设置串口的安全属性,WIN9X下不支持,应设为NULL</param>
/// <param name="dwCreationDisposition">对于串口通信,创建方式只能为OPEN_EXISTING</param>
/// <param name="dwFlagsAndAttributes">指定串口属性与标志,设置为FILE_FLAG_OVERLAPPED(重叠I/O操作),指定串口以异步方式通信</param>
/// <param name="hTemplateFile">对于串口通信必须设置为NULL</param>
[DllImport("kernel32.dll")]
private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode,
int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
/// <summary>
/// 得到串口状态
/// </summary>
/// <param name="hFile">通信设备句柄</param>
/// <param name="lpDCB">设备控制块DCB</param>
[DllImport("kernel32.dll")]
private static extern bool GetCommState(int hFile, ref DCB lpDCB);
/// <summary>
/// 建立串口设备控制块
/// </summary>
/// <param name="lpDef">设备控制字符串</param>
/// <param name="lpDCB">设备控制块</param>
[DllImport("kernel32.dll")]
private static extern bool BuildCommDCB(string lpDef, ref DCB lpDCB);
/// <summary>
/// 设置串口状态
/// </summary>
/// <param name="hFile">通信设备句柄</param>
/// <param name="lpDCB">设备控制块</param>
[DllImport("kernel32.dll")]
private static extern bool SetCommState(int hFile, ref DCB lpDCB);
/// <summary>
/// 读取串口超时时间
/// </summary>
/// <param name="hFile">通信设备句柄</param>
/// <param name="lpCommTimeouts">超时时间</param>
[DllImport("kernel32.dll")]
private static extern bool GetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts);
/// <summary>
/// 设置串口超时时间
/// </summary>
/// <param name="hFile">通信设备句柄</param>
/// <param name="lpCommTimeouts">超时时间</param>
[DllImport("kernel32.dll")]
private static extern bool SetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts);
/// <summary>
/// 读取串口数据
/// </summary>
/// <param name="hFile">通信设备句柄</param>
/// <param name="lpBuffer">数据缓冲区</param>
/// <param name="nNumberOfBytesToRead">多少字节等待读取</param>
/// <param name="lpNumberOfBytesRead">读取多少字节</param>
/// <param name="lpOverlapped">溢出缓冲区</param>
[DllImport("kernel32.dll")]
private static extern bool ReadFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToRead,
ref int lpNumberOfBytesRead, ref OVERLAPPED lpOverlapped);
/// <summary>
/// 写串口数据
/// </summary>
/// <param name="hFile">通信设备句柄</param>
/// <param name="lpBuffer">数据缓冲区</param>
/// <param name="nNumberOfBytesToWrite">多少字节等待写入</param>
/// <param name="lpNumberOfBytesWritten">已经写入多少字节</param>
/// <param name="lpOverlapped">溢出缓冲区</param>
[DllImport("kernel32.dll")]
private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite,
ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped);
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool FlushFileBuffers(int hFile);
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool PurgeComm(int hFile, uint dwFlags);
/// <summary>
/// 关闭串口
/// </summary>
/// <param name="hObject">通信设备句柄</param>
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(int hObject);
/// <summary>
/// 得到串口最后一次返回的错误
/// </summary>
[DllImport("kernel32.dll")]
private static extern uint GetLastError();

/// <summary>
/// 建立与串口的连接
/// </summary>
public void Open()
{

DCB dcbCommPort = new DCB();
COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();

// 打开串口
hComm = CreateFile(PortNum ,GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(hComm == INVALID_HANDLE_VALUE)
{
return;
}

// 设置通信超时时间
GetCommTimeouts(hComm, ref ctoCommPort);
ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
ctoCommPort.ReadTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutConstant = 0;

SetCommTimeouts(hComm, ref ctoCommPort);

// 设置串口
GetCommState(hComm, ref dcbCommPort);
dcbCommPort.fOutxCtsFlow = 524800;
dcbCommPort.BaudRate = BaudRate;
dcbCommPort.flags = 0;
dcbCommPort.flags |= 1;
if (Parity > 0)
{
dcbCommPort.flags |= 2;
}
dcbCommPort.Parity = Parity;
dcbCommPort.ByteSize = ByteSize;
dcbCommPort.StopBits = StopBits;
dcbCommPort.fOutxCtsFlow = 524800;
if (!SetCommState(hComm, ref dcbCommPort))
{
return;
}
Opened = true;
}

/// <summary>
/// 关闭串口,结束通讯
/// </summary>
public void Close()
{
if (hComm != INVALID_HANDLE_VALUE)
{
CloseHandle(hComm);
}
}

/// <summary>
/// 读取串口返回的数据
/// </summary>
/// <param name="NumBytes">数据长度</param>
public byte[] Read(int NumBytes)
{
byte[] BufBytes;
byte[] OutBytes;
BufBytes = new byte[NumBytes];
if (hComm != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesRead = 0;
ReadFile(hComm, BufBytes, NumBytes, ref BytesRead, ref ovlCommPort);
OutBytes = new byte[BytesRead];
Array.Copy(BufBytes, OutBytes, BytesRead);
return OutBytes;
}
else
{
return new byte [0];
}
}
/// <summary>
/// 清空COM口缓冲区数据
/// </summary>
/// <returns></returns>
public bool ClearPortData()
{
bool result = false;
if (hComm != INVALID_HANDLE_VALUE)
{
result = PurgeComm(hComm, 0);
}
return result;
}

/// <summary>
/// 向串口写数据
/// </summary>
/// <param name="WriteBytes">数据数组</param>
public bool Write(byte[] WriteBytes)
{
bool result;
if (hComm != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesWritten = 0;
WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);
result = true;
}
else
{
result = false;
}
return result;
}
}
}
 
谢谢Codemoocow, 你提供了一个很好的类, 有没有对多台串口设备实时收发数据的代码, 也就是怎么样应用这个类实现对多台串口设备实时收发数据, 我打算结账, 看情况我再加分
 
如果你想花最少的钱学习流行的计算机技术,本人低价提供
计算机专业高清晰 视 频 教 程,所有教程由业内名家讲解,物超所值,
所有光盘4元/张,特快专递全国三天内到货.
联系方式:手 机:1 3 5 76145612(手机联系佳) Q Q:108410943
E-mail:ncncldjjg@126.com
1、Oracle9iOCP(Oracle认证专家DBA)视频教程(23CD)
2、SQL语言、数据挖掘、SQLServer2000视频教程(6CD)
3、计算机网络原理视频教程(4CD)
4、计算机实用组网技术视频教程(3CD)
5、MCSE(微软认证系统工程师)认证视频教程(11CD)
6、windows2003即学即会视频教程(6CD)
7、J2EE Web程序开发定向班/Java就业班视频教程
(java基础jsp核心技术UML设计)(13CD)
8、J2EE基础高级案例分析视频教程(9CD)
9、马士兵J2SE入门与精通(含坦克大战、BBS实例)视频教程(6CD)
10、java语言深入详解视频教程(12CD)
11、java技术从入门到精通视频教程(21CD)
12、javascript全接触视频教程(13CD)
13、各类网站源程序(9CD)
14、unix原理视频教程(3CD)
15、Linux软件开发工程师(C语言)视频教程(4CD)
16、Linux配置、管理、优化实战工程师视频教程(8CD)
17、Linux内核编程视频教程(11CD)
18、C语言详解视频教程(2CD)
19、VC++6.0(MFC)开发技术术详解视频教程(6CD)
20、ASP.NET中文视频教程(3CD)
21、洪恩C#入门多媒体教程(1CD)
22、XML技术视频教程(2CD)
23、操作系统视频教程(3CD)
24、网络技术基础视频教程(2CD)
25、数据结构视频教程(5CD)
26、清华大学计算机专业多媒体教程(数据结构、汇编、编译原理等)(13CD)
27、大学数学[离散数学线性代数概率与数理统计微积分]视频教程(22CD)
28、LearnKey Asp.Net (老外用英语讲课)(13CD)
29、LearnKey Asp.Net Webservice(老外用英语讲课)(5CD)
30、AppDev Asp.Net2.0 UsingC# (老外用英语讲课)(1CD)
31、APPDev .Net Framework(老外用英语讲课)(2CD)
32、林清安pro/e2001(野火版)视频教程(18CD)
33、深圳大学3D设计视频教程(4CD)
34、3DMAX建模视频教程(老外用英语讲课)(6CD)
35、3DMAX纹理与贴图材质灯光视频教程(老外用英语讲课)(5CD)
36、3DMAX格式500个常用模型库(4CD)
37、lightscape基础入门视频教程(2CD)
38、聚光制造(lightscape3.2入门与精通视频教程)(4CD)
39、coreldraw12中文版入门与精通swf格式视频教程(2CD)
 
这些东西网上到处都是
 
后退
顶部