串口操作中的读写串口疑问
admin 发表于 2010-07-18 | 来源:互联网 | 阅读:
小弟我初次学习串口通信技术有些疑问请给位大侠给解答下
其中读写串口ReadFile和WriteFile到底是干啥的,是从接入设备读信息和给接入设备写信息?我想不明白哦
假如我想要从接入串口设备中读取数据,ReadFile和WriteFile 起到什么作用,怎么用它们。
请明确说明这两个函数的意义和作用。。小弟在此谢过了
小弟我初次学习串口通信技术有些疑问请给位大侠给解答下
其中读写串口ReadFile和WriteFile到底是干啥的,是从接入设备读信息和给接入设备写信息?我想不明白哦
假如我想要从接入串口设备中读取数据,ReadFile和WriteFile 起到什么作用,怎么用它们。
请明确说明这两个函数的意义和作用。。小弟在此谢过了
评论功能因故关闭!
请加入我们的QQ群一起参与讨论:群号59400482(500人超级群)
Windows环境下,设备,端口,都可以当文件来读写。所以,用CreateFile打开串口,用ReadFile从串口读取数据,用WriteFile向串口输出数据。
请详细说明下,刚看串口通讯还不懂了,给位得说的傻瓜点。假如我就是要从串口读数据,我不给串口返回数据还需要 写串口么,我最终从串口得到想要的数据是通过读串口得到还是通过写串口得到?
一句话真说不清楚呀,呵呵,
请详细说明下,刚看串口通讯还不懂了,给位得说的傻瓜点。假如我就是要从串口读数据,我不给串口返回数据还需要 写串口么,我最终从串口得到想要的数据是通过读串口得到还是通过写串口得到?如果你的串口连接的设备无需指令就自动回传数据,你只需要不停的读串口就行了。如果该设备需要收到指令后才返回数据,你需要写一次,读一次,写一次,读一次。。。。所谓的指令,是指发送一些数据给串口连接的设备,而这些数据,取决于该设备厂商提供的协议。
求求大家了,别嫌分少,别嫌麻烦。。。谁能帮帮我呀。。。。。。
似乎明白了点,也就是说我从设备得到数据是通过读串口实现的,那么我想要知道当前接入的设备是哪一个设备,假如我有血压仪,打印机,体重计等电子设备的话。。我咋区分当前接入的是哪个设备呀。。谢谢你了
这么多设备你不可能接在同一个串口上吧。每个设备连在一个不同的串口上,比如串口1连接血压仪,串口2连接打印机,串口3连接体重计,这样当你用CreateFile打开串口1返回一个句柄,用ReadFile读取时,指定这个句柄,那么就相当于从血压仪读取数据。同理,用CreateFile打开串口2返回的句柄,用ReadFile读取时指定第二个句柄,就相当于从打印机读取数据。。。
请详细说明下,刚看串口通讯还不懂了,给位得说的傻瓜点。假如我就是要从串口读数据,我不给串口返回数据还需要 写串口么,我最终从串口得到想要的数据是通过读串口得到还是通过写串口得到?你可以使用PCOMM.dll或者MSCOMM的oxc控件来写串口程序,更简单些
忘记说明了 我的那个串口接的是蓝牙接收器,我就一个串口 这个串口对应多个设备 这时候我咋区分 是哪个设备
我明白了ccrun的意思,每个串口都去做一个 打开串口操作并且插上设备,那没明白串口各自得到自己设备的值。问题是 真的想你说的 我还真把这些设备都接在一个串口上了,这些设备都通过这一个串口去识别,难道我事先得知道每个设备的类型号,然后代码中去根据设备的类型号去区别么?
晕 那没明白串口各自得到自己设备的值 写错了是:明白了串口各自得到自己设备的值
操作串口就是操作文件// 貌似windows上是这样,好像linux也是这样,都是把设备挂载,然后读写借花献佛 叶帆的一串代码,,项目上用了,效果灰常的好 仅仅改动了一下超时部分,就拿来用起了用在跟西门子PLC的通讯上C/C++ code
////// COM.h
#ifndef ComH
#define ComH
#include "vcl.h"
#define uchar unsigned char
long OpenCom(long, char *, long, long);
long CloseCom();
long SendData(uchar *, long);
long AcceptData(uchar *bytBuffer, long);
long ClearAcceptBuffer();
long ClearSendBuffer();
#endif
////////////// COM.c
//—————————————————————————
#pragma hdrstop
#include <stdio.h>
#include "Com.h"
//—————————————————————————
#pragma package(smart_init)
//串口句柄
HANDLE m_COM_Handle;
//两个信号全局变量(串口操作用)
OVERLAPPED m_OverlappedRead, m_OverlappedWrite;
//*************************************************************************
//函 数 名:OpenCom
//输 入:long lngPort, 串口号
// char *cfgMessage, 配置信息,形如"9600,e,8,1"
// long lngInSize, 接收缓冲区大小
// long lngOutSize 发送缓冲区大小
//输 出:long
//功能描述:打开串口
//全局变量:
//调用模块:
//作 者:叶帆
//日 期:2006年4月4日
//修 改 人:
//日 期:
//版 本:
//*************************************************************************
long OpenCom(long lngPort,char *cfgMessage,long lngInSize,long lngOutSize)
{
try
{
char szMsg[255];
DCB dcb;
//打开端口
if (lngPort>9)
sprintf( szMsg, "\\\\.\\COM%d", lngPort );
else
sprintf( szMsg, "COM%d", lngPort );
//用异步方式读写串口
m_COM_Handle = CreateFile(szMsg, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED , NULL );
if( m_COM_Handle == NULL ) return( 2 );
//清空异步读写参数
memset(&(m_OverlappedRead), 0, sizeof (OVERLAPPED));
memset(&(m_OverlappedWrite), 0, sizeof (OVERLAPPED));
//设置dcb块
dcb.DCBlength = sizeof( DCB ); //长度
GetCommState(m_COM_Handle , &dcb );
//波特率,奇偶校验,数据位,停止位 如:9600,n,8,1
sprintf(szMsg,"COM%d:%s", lngPort,cfgMessage);
BuildCommDCB(szMsg,&dcb);
//——————————
dcb.fBinary=TRUE; //二进制方式
dcb.fOutxCtsFlow=FALSE; //不用CTS检测发送流控制
dcb.fOutxDsrFlow=FALSE; //不用DSR检测发送流控制
dcb.fDtrControl=DTR_CONTROL_DISABLE; //禁止DTR流量控制
dcb.fDsrSensitivity=FALSE; //对DTR信号线不敏感
dcb.fTXContinueOnXoff=TRUE; //检测接收缓冲区
dcb.fOutX=FALSE; //不做发送字符控制
dcb.fInX =FALSE; //不做接收控制
dcb.fErrorChar=FALSE; //是否用指定字符替换校验错的字符
dcb.fNull=FALSE; //保留NULL字符
dcb.fRtsControl=RTS_CONTROL_ENABLE; //允许RTS流量控制
dcb.fAbortOnError=FALSE; //发送错误后,继续进行下面的读写操作
dcb.fDummy2=0; //保留
dcb.wReserved=0; //没有使用,必须为0
dcb.XonLim=0; //指定在XOFF字符发送之前接收到缓冲区中可允许的最小字节数
dcb.XoffLim=0; //指定在XOFF字符发送之前缓冲区中可允许的最小可用字节数
dcb.XonChar=0; //发送和接收的XON字符
dcb.XoffChar=0; //发送和接收的XOFF字符
dcb.ErrorChar=0; //代替接收到奇偶校验错误的字符
dcb.EofChar=0; //用来表示数据的结束
dcb.EvtChar=0; //事件字符,接收到此字符时,会产生一个事件
dcb.wReserved1=0; //没有使用
//dcb.BaudRate =9600; //波特率
//dcb.Parity=0; //奇偶校验
//dcb.ByteSize=8; //数据位
//dcb.StopBits=0; //停止位
//——————————
if(dcb.Parity==0 ) // 0-4=None,Odd,Even,Mark,Space
{
dcb.fParity=FALSE; //奇偶校验无效
}
else
{
dcb.fParity=TRUE; //奇偶校验有效
}
sprintf(szMsg,"COM%d:%d,%d,%d,%d (InSize:%ld,OutSize:%ld)", lngPort,dcb.BaudRate,dcb.Parity,dcb.ByteSize,dcb.StopBits,lngInSize,lngOutSize);
//读写超时设置
//西门子参数
/*
CommTimeOuts.ReadIntervalTimeout =0; //字符允许间隔ms 该参数如果为最大值,会使readfile命令立即返回
CommTimeOuts.ReadTotalTimeoutMultiplier = 0; //总的超时时间(对单个字节)
CommTimeOuts.ReadTotalTimeoutConstant = 10; //多余的超时时间ms
CommTimeOuts.WriteTotalTimeoutMultiplier = 0; //总的超时时间(对单个字节)
CommTimeOuts.WriteTotalTimeoutConstant = 10; //多余的超时时间
*/
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 20;
SetCommTimeouts(m_COM_Handle, &CommTimeOuts);
//获取信号句柄
m_OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if( !SetCommState( m_COM_Handle, &dcb ) || //判断设置参数是否成功
!SetupComm( m_COM_Handle, lngInSize, lngOutSize ) || //设置输入和输出缓冲区是否成功
m_OverlappedRead.hEvent==NULL ||
m_OverlappedWrite.hEvent==NULL)
{
DWORD dwError = GetLastError(); //获取最后的错误信息
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_COM_Handle );
m_COM_Handle=NULL;
return dwError;
}
return( 0 );
}
catch(…)
{
return -1;
}
}
//*************************************************************************
//函 数 名:CloseCom
//输 入:
//输 出:long
//功能描述:关闭串口
//全局变量:
//调用模块:
//作 者:叶帆
//日 期:2006年4月4日
//修 改 人:
//日 期:
//版 本:
//*************************************************************************
long CloseCom()
{
try
{
if(m_COM_Handle == NULL ) return( 1 );
SetCommMask(m_COM_Handle ,NULL);
SetEvent(m_OverlappedRead.hEvent);
SetEvent(m_OverlappedWrite.hEvent);
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
if (CloseHandle( m_COM_Handle )==FALSE)return (2);
m_COM_Handle = NULL;
}
catch(…)
{
return (3);
}
return( 0 );
}
//*************************************************************************
//函 数 名:SendData
//输 入:BYTE *bytBuffer, 数据
// long lngSize 个数
//输 出:long
//功能描述:发送数据
//全局变量:
//调用模块:
//作 者:叶帆
//日 期:2006年4月4日
//修 改 人:
//日 期:
//版 本:
//*************************************************************************
long SendData(uchar *bytBuffer, long lngSize)
{
try
{
if( m_COM_Handle == NULL ) return( -1 );
DWORD dwBytesWritten=lngSize;
BOOL bWriteStat;
COMSTAT ComStat;
DWORD dwErrorFlags;
ClearCommError(m_COM_Handle,&dwErrorFlags,&ComStat);
bWriteStat=WriteFile(m_COM_Handle, bytBuffer, lngSize, &dwBytesWritten, &(m_OverlappedWrite));
if(!bWriteStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
GetOverlappedResult(m_COM_Handle,&(m_OverlappedWrite),&dwBytesWritten,TRUE); //等待直到发送完毕
}
else
{
dwBytesWritten=0;
}
}
return (long)dwBytesWritten;
}
catch(…)
{
return -1;
}
}
//*************************************************************************
//函 数 名:AcceptData
//输 入:BYTE *bytBuffer, 数据
// long lngSize 个数
//输 出:long
//功能描述:读取数据
//全局变量:
//调用模块:
//作 者:叶帆
//日 期:2006年4月4日
//修 改 人:
//日 期:
//版 本:
//*************************************************************************
long AcceptData(uchar *bytBuffer, long lngSize)
{
try
{
if( m_COM_Handle == NULL ) return( -1 );
DWORD lngBytesRead=lngSize;
BOOL fReadStat;
DWORD dwRes=0;
//读数据
fReadStat=ReadFile(m_COM_Handle,bytBuffer,lngSize,&lngBytesRead,&(m_OverlappedRead));
//Sleep(1);
if( !fReadStat )
{
if( GetLastError() == ERROR_IO_PENDING ) //重叠 I/O 操作在进行中
{
dwRes=WaitForSingleObject(m_OverlappedRead.hEvent,1000); //等待,直到超时
switch(dwRes)
{
case WAIT_OBJECT_0: //读完成
if(GetOverlappedResult(m_COM_Handle,&(m_OverlappedRead),&lngBytesRead,FALSE)==0)
{
//错误
return -2;
}
break;
case WAIT_TIMEOUT: //超时
return -1;
break;
default: //WaitForSingleObject 错误
break;
}
}
}
return lngBytesRead;
}
catch(…)
{
return -1;
}
}
//*************************************************************************
//函 数 名:ClearAcceptBuffer
//输 入:
//输 出:long
//功能描述:清除接收缓冲区
//全局变量:
//调用模块:
//作 者:叶帆
//日 期:2006年4月4日
//修 改 人:
//日 期:
//版 本:
//*************************************************************************
long ClearAcceptBuffer()
{
try
{
if(m_COM_Handle == NULL ) return( -1 );
PurgeComm(m_COM_Handle,PURGE_RXABORT | PURGE_RXCLEAR); //
}
catch(…)
{
return(1);
}
return(0);
}
//*************************************************************************
//函 数 名:ClearSendBuffer
//输 入:
//输 出:long
//功能描述:清除发送缓冲区
//全局变量:
//调用模块:
//作 者:叶帆
//日 期:2006年4月4日
//修 改 人:
//日 期:
//版 本:
//*************************************************************************
long ClearSendBuffer()
{
try
{
if(m_COM_Handle == NULL ) return( -1 );
PurgeComm(m_COM_Handle,PURGE_TXABORT | PURGE_TXCLEAR); //
}
catch(…)
{
return (1);
}
return(0);
}
你连接的每一个串口设备 都有不同的端口,当然也可以通过 设备管理来修改 char szMsg[255]; DCB dcb; //打开端口 if (lngPort>9) sprintf( szMsg, "\\\\.\\COM%d", lngPort );// 大于9时这个 else sprintf( szMsg, "COM%d", lngPort );// 这个 //用异步方式读写串口 m_COM_Handle = CreateFile(szMsg, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED , NULL ); CreateFile的时候也就是按照这点区别来进行操作的..
非常感谢大家的人心回答,我结贴前想知道 我怎样让程序去区分当前串口连接的是什么设备?我只有一个端口 这个端口插着一个蓝牙接收器,所用设备都是通过蓝牙与串口通信的 所以 我要区分当前接入是是哪个设备,再次谢谢大家。。。。。。。我明白这点就该结贴了 谢谢你们了
区分,这不好办吧? 按照 你的蓝牙接收器的协议, 发一个数据过去,看返回的数据是不是想要的?
我现在也在做串口通讯这方面 我用的是 victor chen 的 YbCommDevice控件 非常好用 建议楼主去看看 http://www.cppfans.com 他的主页
非常感谢大家的热心回答,学到了不少东西。对于我这个菜鸟来说帮助很大了呵呵