没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
翻译|其它|编辑:郝浩|2004-12-07 11:07:00.000|阅读 2099 次
概述:
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
关键字 串口
介绍
介绍工业控制领域利用串口和外围设备进行通讯。
正文
前言:
总所周之,利用串口进行数据通讯在在通讯通讯领域重占有着重要的地位。利用RS232-RS485进行数据信号的采集和传递是VC编程的又一大热点。串口通讯在通讯软件重有着十分广泛的应用。如电话、传真、视频和各种控制等。在各种开发工具中间,VC由于功能强大和灵活,同时也得到了Microsoft的最大支持,所以在一般进行涉及硬件操作的通讯编程重,大都推荐使用VC作为开发工具。然而工业控制串口通讯这个又不同于一般的串口通讯程序,因为控制外围设备传送的大都是十六进制数据(BYTE类型),所以,为了提高程序的运行稳定性,我们在编写程序进行通讯时可以不考虑传送BYTE类型数据的工作。
串口通讯目前流行的方法大概有两种:一是利用Microsoft提供的CMSCOMM控件进行通讯,不过现在很多程序员都觉应该放弃这种方式。二是利用WINAPI函数进行编程,这种编程的难度最高,要求你要掌握很多的API函数。三是利用现在网络上面提供的一些串口通讯控件进行编写,比如CSerial类等。
程序实现:
我在经过许多的项目的开发和实践中发现,采用WIN
API函数进行串口的开发能够给程序员很大的控件,并且程序运也很稳定。所以我将与串口接触的函数进行封装,然后在各个工程中进行调用,效果还是比较好的,现将各个函数和调用方法列举出来,希望对各位有所帮助。
一、设置串口相关工作
#define MAXBLOCK 2048
#define XON 0x11
#define XOFF 0x13
BOOL SetCom(HANDLE &m_hCom, const char *m_sPort, int BaudRate, int Databit,
CString parity, CString stopbit)
{
COMMTIMEOUTS TimeOuts; ///串口输出时间 超时设置
DCB dcb; ///与端口匹配的设备
m_hCom=CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL); // 以重叠方式打开串口
if(m_hCom==INVALID_HANDLE_VALUE)
{
AfxMessageBox("设置串口部分,串口打开失败"); /////重叠方式 异步通信(INVALID_HANDLE_VALUE)函数失败。
return FALSE;
}
SetupComm(m_hCom,MAXBLOCK,MAXBLOCK); //设置缓冲区
memset(&TimeOuts,0,sizeof(TimeOuts));
TimeOuts.ReadIntervalTimeout=MAXDWORD; // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作
TimeOuts.ReadTotalTimeoutMultiplier=0; //读时间系数
TimeOuts.ReadTotalTimeoutConstant=0; //读时间常量
TimeOuts.WriteTotalTimeoutMultiplier=50; //总超时=时间系数*要求读/写的字符数+时间常量
TimeOuts.WriteTotalTimeoutConstant=2000; //设置写超时以指定WriteComm成员函数中的
SetCommTimeouts(m_hCom, &TimeOuts); //GetOverlappedResult函数的等待时间*/
if(!GetCommState(m_hCom, &dcb)) ////串口打开方式、端口、波特率 与端口匹配的设备
{
AfxMessageBox("GetCommState Failed");
return FALSE;
}
dcb.fParity=TRUE; //允许奇偶校验
dcb.fBinary=TRUE;
if(parity=="NONE")
dcb.Parity=NOPARITY;
if(parity=="ODD")
dcb.Parity=ODDPARITY;
if(parity=="EVEN")
dcb.Parity=EVENPARITY;
if(stopbit=="1")//设置波特率
dcb.StopBits=ONESTOPBIT;
//if(stopbit=="0")//设置波特率
// dcb.StopBits=NONESTOPBIT;
if(stopbit=="2")//设置波特率
dcb.StopBits=TWOSTOPBITS;
BOOL m_bEcho=FALSE; ///
int m_nFlowCtrl=0;
BOOL m_bNewLine=FALSE; ///
dcb.BaudRate=BaudRate; // 波特率
dcb.ByteSize=Databit; // 每字节位数
// 硬件流控制设置
dcb.fOutxCtsFlow=m_nFlowCtrl==1;
dcb.fRtsControl=m_nFlowCtrl==1 ?RTS_CONTROL_HANDSHAKE:RTS_CONTROL_ENABLE;
// XON/XOFF流控制设置(软件流控制!)
dcb.fInX=dcb.fOutX=m_nFlowCtrl==2;
dcb.XonChar=XON;
dcb.XoffChar=XOFF;
dcb.XonLim=50;
dcb.XoffLim=50;
if(SetCommState(m_hCom, &dcb))
return TRUE; ////com的通讯口设置
else
{
AfxMessageBox("串口已打开,设置失败");
return FALSE;
}
}
二、读串口操作:
int ReadCom(HANDLE hComm, BYTE inbuff[], DWORD &nBytesRead, int ReadTime)
{
DWORD lrc; ///纵向冗余校验
DWORD endtime; /////////jiesuo
static OVERLAPPED ol;
int ReadNumber=0;
int numCount=0 ; //控制读取的数目
DWORD dwErrorMask,nToRead;
COMSTAT comstat;
ol.Offset=0; ///相对文件开始的字节偏移量
ol.OffsetHigh=0; ///开始传送数据的字节偏移量的高位字,管道和通信时调用进程可忽略。
ol.hEvent=NULL; ///标识事件,数据传送完成时设为信号状态
ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒)
for(int i=0;i<2000;i++)
inbuff[i]=0;
Sleep(ReadTime);
ClearCommError(hComm,&dwErrorMask,&comstat);
nToRead=min(2000,comstat.cbInQue);
if(int(nToRead)<2)
goto Loop;
if(!ReadFile(hComm,inbuff,nToRead,&nBytesRead,&ol))
{
if((lrc=GetLastError())==ERROR_IO_PENDING)
{
///////////////////
endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒)
while(!GetOverlappedResult(hComm,&ol,&nBytesRead,FALSE))//该函数取回重叠操作的结果
{
if(GetTickCount()>endtime)
break;
}
}
}
return 1;
Loop: return 0;
}
三、写串口命令
int WriteCom(HANDLE hComm, BYTE Outbuff[], int size, int bWrite[])
{
DWORD nBytesWrite,endtime,lrc;
static OVERLAPPED ol;
DWORD dwErrorMask,dwError;
COMSTAT comstat;
ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
ol.Offset=0;
ol.OffsetHigh=0;
ol.hEvent=NULL; ///标识事件,数据传送完成时,将它设为信号状态
ClearCommError(hComm,&dwErrorMask,&comstat);
if(!WriteFile(hComm,Outbuff,size,&nBytesWrite,&ol))
{
if((lrc=GetLastError())==ERROR_IO_PENDING)
{
endtime=GetTickCount()+1000;
while(!GetOverlappedResult(hComm,&ol,&nBytesWrite,FALSE))
{
dwError=GetLastError();
if(GetTickCount()>endtime)
{
AfxMessageBox("写串口时间过长,目前串口发送缓冲区中的数据数目为空");
break;
}
if(dwError=ERROR_IO_INCOMPLETE)
continue; //未完全读完时的正常返回结果
else
{
// 发生错误,尝试恢复!
ClearCommError(hComm,&dwError,&comstat);
break;
}
}
}
}
FlushFileBuffers(hComm);
PurgeComm(hComm,PURGE_TXCLEAR);
bWrite=0;
return 1;
}
四、调用方法很简单,只需要将你的串口参数进行简单的设置就可以了。比如:
BOOL Main_OpenCom()//设置COM
{
int Boundrate=9600;//波特率
CString StopBits="1";//停止位
int DataBits=8;//数据位
CString Parity="ODD";//奇偶校验
CString m_Port="COM1";
return SetCom(m_hCom1,m_Port,Boundrate,DataBits,Parity,StopBits);
}
void Main()
{
int SIZE;
DWORD BytestoRead=52*Count+6;//要11个字节
int BWRITE[2];
int ReadTime=2000;
BYTE Outbuff[12]={0xff,0x00,0xea,0xff,0xea,0xff,0,0,0,0,0,0};
SIZE=sizeof(Outbuff);
WriteCom(m_hCom,Outbuff,SIZE,BWRITE);
ReadCom(m_hCom,m_Inbuff,BytestoRead,ReadTime);
//进行湘阴的解包处理
}
有了上面的函数的封装,相信大家编程应该能够方便快捷一些吧。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@evget.com
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
慧都科技 版权所有 Copyright 2003-
2025 渝ICP备12000582号-13 渝公网安备
50010702500608号