vc api 串口
来源:互联网 发布:java怎么发音 编辑:程序博客网 时间:2024/06/06 09:32
{
public:
TSerialPort();//构造函数
~TSerialPort();//析构函数
//串口初始化,缺省参数为:COM1,19200Baud,无奇偶校验,8数据为,1停止位,监控读事件
bool InitPort(unsigned uPortNo=1,unsigned uBaud=9600,
char cParity='N',unsigned uDataBits=8,unsigned uStopBits=1,
DWORD dwCommEvents=EV_RXCHAR);
void __fastcall StartMonitoring();//启动串口监控线程
void __fastcall StopMonitoring();//挂起口监控线程
bool WriteToPort(unsigned char ucTxChar);//向串口写一个字符
//////////...................
HANDLE GetComHandle();
//...................
private:
void __fastcall Clear(); //清除占用的资源
HANDLE hComm; //串口句柄
OVERLAPPED ov_Write;//异步写串口时用到的重叠结构
TComThread *ComThread; //串口操作线程
DCB ComDCB; //串口设备控制块
COMMTIMEOUTS CommTimeouts;//超时参数
};
#include <vcl.h>
#pragma hdrstop
#include "stdio.h"
#include "SerialPort.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
int g_iSerialPort; //端口号:COM1,COM2,COM3,COM4
//---------------------------------------------------------------------------
//构造函数,初始化,把各数据成员置0
TSerialPort::TSerialPort()
{
hComm =INVALID_HANDLE_VALUE; //串口句柄
ComThread=NULL; //串口监控线程
//异步写操作中用到的重叠结构中的事件
ov_Write.hEvent=CreateEvent(NULL, true, false, NULL);
}
//----------------------------------------------------------------------
//析构函数
TSerialPort::~TSerialPort()
{
if(ComThread!=NULL)
{
//如果线程挂起则启动它,只要这样Terminate()方法才会有效,
//线程才会FreeOnTerminated
while(ComThread->Suspended)
ComThread->Resume();
ComThread->Terminate();
ComThread=NULL;
}
//释放对象,如果句柄有效,则关闭
if(ov_Write.hEvent!=NULL)
{
CloseHandle(ov_Write.hEvent);
ov_Write.hEvent=NULL;
}
}
//----------------------------------------------------------------------
//串口初始化,可用于串口1到4,参数意义如下:
//pPortOwner-父窗口,uPortNo-串口号,uBaud-波特率,cParity-奇偶校验,uDatabits-数据位数,
//uStopbits-停止位数,dwCommEvents-需要监控的串口事件
bool TSerialPort::InitPort(unsigned uPortNo,unsigned uBaud,
char cParity,unsigned uDataBits,unsigned uStopBits,DWORD dwCommEvents)
{
char sTemp[100];
if(uPortNo<1||uPortNo>4)
{
printf("无法打开串口COM%d,串口号只能是COM1、COM2、COM3或COM4中的一个.");
printf("错误");
return false;
}
//if(Parent==NULL)
//{
// printf("串口的父窗口无效,串口监控线程无法正常工作.");
//return false;
// }
sprintf(sTemp,"COM%d",uPortNo);//合成串口号字符串
//打开串口,获取串口句柄
hComm = CreateFile(sTemp,//串口号
GENERIC_READ|GENERIC_WRITE,//读写方式
0, //通讯设备必须以独占方式打开
NULL, //无安全属性
OPEN_EXISTING, //通讯设备已存在
FILE_FLAG_OVERLAPPED, //异步I/O
0); //通讯设备不能用模板打开
if (hComm==INVALID_HANDLE_VALUE) //句柄无效,打开串口失败
{
printf("无法打开串口%d(COM%d),请检查串口是否正确安装,或是否被已经被占用.",
uPortNo,uPortNo);
printf("错误");
return false;
}
//设置超时参数,总时间=Multiplier*字符数+Constant
//Interval为读入的字符串中任意两个字符间的最大间隔
CommTimeouts.ReadIntervalTimeout=1000;
CommTimeouts.ReadTotalTimeoutMultiplier=1000;
CommTimeouts.ReadTotalTimeoutConstant=1000;
CommTimeouts.WriteTotalTimeoutMultiplier=1000;
CommTimeouts.WriteTotalTimeoutConstant=1000;
printf("baud=%d parity=%c data=%d stop=%d",uBaud,
cParity,uDataBits,uStopBits);//合成串口参数字符串
//配置串口
if (SetCommTimeouts(hComm,&CommTimeouts))//超时参数
{
if (SetCommMask(hComm,dwCommEvents))//需要监控的事件
{
if (GetCommState(hComm,&ComDCB))//获取原始DCB
{
//禁止硬流控,因为本系统不需要
ComDCB.fOutxCtsFlow=false;
ComDCB.fOutxDsrFlow=false;
ComDCB.fDsrSensitivity=false;
ComDCB.fDtrControl=DTR_CONTROL_DISABLE;
ComDCB.fRtsControl=RTS_CONTROL_DISABLE;
//设置串口设备控制块(DCB)
if (BuildCommDCB(sTemp,&ComDCB))
{
if (!SetCommState(hComm,&ComDCB))
printf("设置串口");
}
else
printf("建立串口设备控制块");
}
else
printf("获取串口状态");
}
else
printf("设置串口事件掩码");
}
else
printf("串口超时参数设置");
//清空串口缓冲区,退出所有相关操作
PurgeComm(hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
//创建串口监控线程
ComThread=new TComThread(true,hComm);
if(ComThread==NULL)//无法创建线程
{
printf("创建线程");
return false;
}
return true;
}
//----------------------------------------------------------------------
//启动串口监控线程
void __fastcall TSerialPort::StartMonitoring()
{
ComThread->Resume();
}
//----------------------------------------------------------------------
//挂起线程
void __fastcall TSerialPort::StopMonitoring()
{
ComThread->Suspend();
}
/****
***/
class TComThread : public TThread
{
private:
//HWND Parent;
OVERLAPPED ov_Read;//异步读串口时用到的重叠结构
HANDLE hComm; //串口句柄
protected:
void __fastcall Execute();
public:
__fastcall TComThread(bool CreateSuspended,HANDLE AhComm/*,HWND AParent*/);
__fastcall ~TComThread();
//接收一个字符
void __fastcall TComThread::ReceiveAChar();
};
__fastcall TComThread::TComThread(bool CreateSuspended,HANDLE AhComm/*,HWND AParent*/)
: TThread(CreateSuspended)
{
hComm=AhComm;
//Parent=AParent;
//异步读操作中用到的重叠结构中的事件
ov_Read.hEvent=CreateEvent(NULL, true, false, NULL);
FreeOnTerminate=true;
}
//---------------------------------------------------------------------------
//析构函数
__fastcall TComThread::~TComThread()
{
//释放对象,如果句柄有效,则关闭
if(ov_Read.hEvent!=NULL)
{
CloseHandle(ov_Read.hEvent);
ov_Read.hEvent=NULL;
}
if (hComm!=INVALID_HANDLE_VALUE)
{
CloseHandle(hComm);
hComm=INVALID_HANDLE_VALUE;
}
}
//---------------------------------------------------------------------------
//线程执行函数
void __fastcall TComThread::Execute()
{
if(hComm==INVALID_HANDLE_VALUE) //串口句柄有效
{
printf("串口句柄无效,串口监控线程无法工作.");
return;
}
//清空串口缓冲区,退出所有相关操作
PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|
PURGE_RXABORT|PURGE_TXABORT);
COMSTAT ComStat; //串口状态
DWORD dwEvent,dwError,dwResult;
//进入无限循环,直到线程被关闭
while(!Terminated)
{
//调用WaitCommEvent().这一调用将立即返回,因为我用异步方式
//(FILE_FLAG_OVERLAPPED)打开串口,并且指定重叠操作结构,
//如果有一个字符到达串口,重叠结构中的事件将被置为有信号态
bool bResult=WaitCommEvent(hComm,&dwEvent,&ov_Read);
if (!bResult)
{
//如果WaitCommEvent()返回FALSE,调用GetLastError()判断原因
dwError=GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING: //重叠操作正在后台进行
{
//如果串口这时无字符,这是正常返回值,继续
break;
}
case 87:
{
//在WIN NT下这是一个可能结果,但我没有找到
//它出现的原因,我什么也不做,继续
break;
}
default:
{
//所有其它错误代码均显示串口出错,显示出错信息
printf("等待串口事件");
return;
}
}
}
else
{
//如果WaitCommEvent()返回true,检查输入缓冲区是否确实
//有字节可读,若没有,则继续下一循环
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0) //输入缓冲队列长为0,无字符
continue;
}
//等待串口事件产生
dwResult=WaitForSingleObject(ov_Read.hEvent,1000);
if(dwResult==WAIT_OBJECT_0) //事件产生
{
//获取串口事件掩码
GetCommMask(hComm,&dwEvent);
if (dwEvent & EV_RXCHAR)//有一个字符
ReceiveAChar();//接收一个字符
}
}
}
//---------------------------------------------------------------------------
//接收一个字符
void __fastcall TComThread::ReceiveAChar()
{
COMSTAT ComStat;
DWORD dwError=0;
bool bResult;
DWORD BytesRead=0;
unsigned char ucRxBuff;
//开始无限循环,因为我不知到需要循环多少次.我的解决方法是开始一个无限循环,
//当我已处理了所有的有效数据后才退出.使用这种方法应小心的保证您的程序能
//正常退出循环.即便如此,我仍觉得这是最有效的解决办法
while(1)
{
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0)
{
//缓冲区中已无数据,退出循环
break;
}
//读串口
bResult=ReadFile(hComm,//串口句柄
&ucRxBuff, //输入缓冲区地址
20, //想读入的字符数
&BytesRead, //实际被读入的字符数
&ov_Read); //重叠结构指针
if(!bResult) //读串口失败,调用GetLastError()判断原因
{
switch (dwError=GetLastError())
{
case ERROR_IO_PENDING://重叠操作在后台进行
{
BytesRead=0;
//等待重叠操作结果
bResult=GetOverlappedResult(hComm,//串口句柄
&ov_Read, //重叠结构
&BytesRead, //实际读入字符数
true); //等待直到串口操作超时
if (!bResult)//重叠操作失败
{
printf("(读串口时)获取重叠操作结果");
return;
}
break;
}
default:
{
//其它情况说明出错
printf("读串口");
return;
}
}
}
//将收到的字符当作消息的参数投递到父窗口
if(BytesRead!=1)//没有读入要求的字符数
continue;
cout<<"接收到的字符为:"<<ucRxBuff<<"\n"<<endl;
}
}
//其他
m_hComm = CreateFile( szPort,
GENERIC_READ, //读模式
FILE_SHARE_READ, //不共享
NULL, //默认安全模式
OPEN_EXISTING, //打开而不是创建
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //重叠方式,
NULL);
- vc api 串口
- VC++串口编程之API
- VC串口通讯(Windows API)
- VC++ API实现串口通信
- VC串口API通信详解
- VC中用API实现串口通信
- VC++中API串口通信详解
- VC++多串口控制解决方案 API版
- 深入浅出VC++串口编程--基于Win32 API
- VC++中API串口通信详解
- VC++串口编程之基于Win32 API
- VC串口API超时的详细介绍
- VC 串口编程的方法介绍-VC API 串口编程_VC串口控件
- 深入浅出VC++串口编程之基于Win32 API
- 深入浅出VC++串口编程之基于Win32 API
- 深入浅出VC++串口编程之基于Win32 API
- 深入浅出VC++串口编程之基于Win32 API
- 深入浅出VC++串口编程之基于Win32 API
- “用最有效率的方法算出2乘以8等於几?”
- 关于职场的思考
- git操作保存(转)
- 学习笔记——IO流
- apue 8-3 演示不同的exit值
- vc api 串口
- apue 8-5调用fork两次以避免僵死进程
- 表单提交原理
- 【Ruby on Rails】Install rjb on Ubuntu
- 四核网络机顶盒芯片局势分析(开放市场):rk3128将会成为四核主流
- Ubuntu PHP环境搭建记录
- 河南男子原地旋转14小时 创基尼斯新纪录
- 【线性扫描】题型总结:最大积连续序列,str2int,2sum, 4sum,reverse word, 链表操作, 蛇形访问, 最大蓄水池,直方图最大矩形
- ng-bind