在C++ Builder6.0下如何对串口操作

morven 2005-09-12 03:02:44
C++ Builder6.0下好像是没有办法直接对串口操做的?如何才可以对串口操作呢?~谢谢大侠了!
...全文
816 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
goodluckyxl 2005-10-29
  • 打赏
  • 举报
回复
使用串口组件
不定非要自己搞
shepherd228 2005-09-30
  • 打赏
  • 举报
回复
方法太多了,API,MSCOMM都可以的。还有其他的串口类,比如研华的PCCOM
llin998 2005-09-23
  • 打赏
  • 举报
回复
用WINDOWS API最好的


//---------------------------------------------------------------------------
bool OpenRS232(int baud,char port)
{
char row[50];
DCB dcb;
sprintf(row,"COM%d",port);
idComDev=CreateFile(row,GENERIC_READ|GENERIC_WRITE,0,NULL,
OPEN_EXISTING,0,NULL);
if(idComDev==INVALID_HANDLE_VALUE)
{
return false;
}
if(!GetCommState(idComDev,&dcb))
{
ShowMessage("GetCommState Error!");
return false;
}
dcb.BaudRate=CBR_9600;
dcb.ByteSize=8;
dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT;
if(!SetCommState(idComDev,&dcb))
{
ShowMessage("SetCommState Error!");
return false;
}
//------------------------------
timeouts.ReadIntervalTimeout=3000;
timeouts.ReadTotalTimeoutMultiplier=3000;
timeouts.ReadTotalTimeoutConstant=3000;
timeouts.WriteTotalTimeoutMultiplier=3000;
timeouts.WriteTotalTimeoutConstant=3000;
if(!SetCommTimeouts(idComDev,&timeouts))
return false;
return true;
}
//-------------------------------------------------------------------------
unsigned char ReadByte(void)
{
char b=0;
DWORD dwErrors,dwRead;
clock_t start;
start=clock();
for(;;)
{
ClearCommError(idComDev,&dwErrors,&lpCommStat);
if (dwErrors|| lpCommStat.cbInQue) /* byte received or error ? */
{
break;
}
else if((clock()-start)>60) /* time out 4 clock ticks */
{
ErrorNumber = 3;
return(0);
}
}
if (dwErrors) /* hardware error ? */
{
ErrorNumber = 2;
return(b);
}
if(!ReadFile(idComDev,&b,1,&dwRead,NULL))
{
ClearCommError(idComDev,&dwErrors,&lpCommStat);
ErrorNumber = 1; // communication error
return(0);
}
else
{
ErrorNumber=0;
return b;
}
}
//---------------------------------------------------------------------
bool ReadRecord(int len,int waittime)
{
int i,length;
clock_t start;
unsigned char ch,comp[3];
unsigned short checksum;
start=clock();
memset(buff,0xff,256);
buff[127]=0;
while(clock()-start<waittime)
{
delay(10);
ErrorNumber=0;
ch=ReadByte();
if(ErrorNumber==0)
{
if(ch=='O'||ch=='E')
{
if(ch=='O')
length=len-1;//命令正确
else
length=6; //错误代码
buff[0]=ch;
for(i=1;i<=length;i++)
{
buff[i]=ReadByte();
if(ErrorNumber!=0)
{
ShowMessage("读取字节错误");
return 0;
}
}
if(i>length)break;
}
}
}
if(clock()-start>waittime)
{
ShowMessage("读取数据超时");
return 0;
}
checksum=crc(buff,(length-1));
comp[0]=checksum>>8;
comp[1]=checksum;
if(memcmp(comp,&buff[i-2],2)!=0)
{
ShowMessage("读取检验和错误");
return 0;
}

return 1;
}
//---------------------------------------------------------------------
bool ReadRecordForDayCollect(int len,int waittime)
{
int i,length,j=0;
clock_t start;
unsigned char ch,comp[3];
unsigned short checksum;
start=clock();
memset(buff,0xff,256);
buff[127]=0;
while(clock()-start<waittime)
{
delay(10);
ErrorNumber=0;
ch=ReadByte();
if(ErrorNumber==0)
{
if(ch=='O'||ch=='E')
{
if(ch=='O')
length=len-1;//命令正确
else
length=6; //错误代码
buff[0]=ch;
for(i=1;i<=length;i++)
{
buff[i]=ReadByte();
if(ErrorNumber!=0)
{
ShowMessage("读取字节错误");
return 0;
}
}
if(i>length)break;
}
}
if(ShowFlag==0)
frmDayCollect->pbrDayCollect->Position=j;
if(ShowFlag==1)
frmMachineLog->pbrDayCollect->Position=j;
j++;
if(j==100)
j=0;
}
if(clock()-start>waittime)
{
ShowMessage("读取数据超时");
return 0;
}
checksum=crc(buff,(length-1));
comp[0]=checksum>>8;
comp[1]=checksum;
if(memcmp(comp,&buff[i-2],2)!=0)
{
ShowMessage("读取检验和错误");
return 0;
}

return 1;
}
//--------------------------------------------------------------------------
short SendByte(unsigned char b)
{
DWORD dwWrite;
clock_t start;
start=clock();
do{}
while(WriteFile(idComDev,&b,1,&dwWrite,NULL)==0&&(clock()-start)<2000);
if((clock()-start)>2000)
return 0;
else
return 1;
}
//-------------------------------------------------------------------------
bool SendRecord(unsigned char *record,int len)
{
int i;
unsigned short checksum=0;
unsigned char comp[3];
for(i=1;i<=len;i++)
{
//delay(10);
if(!SendByte(record[i-1]))
{
ShowMessage("发送第"+IntToStr(i)+"字节错误");
return 0;
}
}
checksum=crc(record,len);
comp[0]=checksum>>8;
comp[1]=checksum;
if(!SendByte(comp[0]))
{
ShowMessage("发送校验和错误");
return 0;
}
if(!SendByte(comp[1]))
{
ShowMessage("发送校验和错误");
return 0;
}
return 1;
}
//------------------------------------------------------------------------


ppcust 2005-09-13
  • 打赏
  • 举报
回复
对串口操作和对 文件一样啊。。

直接用creatfile 就可以打开了
luchong2000 2005-09-13
  • 打赏
  • 举报
回复
有个很不错的组件:PcommPro,我也在BCB下搞串口的,用的就是这个
===========================================================================
用C++Builder在Windows下开发串行通信程序是程序员们经常遇到却又令人头痛的事情,不但要理解许多复杂的API函数,还要掌握多线程编程。令人欣慰的是有一些公司专门为C++Builder开发了编写串行通信程序的开发工具,例如MOXA公司的Pcomm(该软件可在http:\\www.moxa.com.tw下载),因而帮我们解决了串行编程这一难题。

下面结合一个具体的例子来说明串行通信程序的开发。本程序的编程环境是Win98和C++Builder3.0。这个编程示例的功能比较强,它具有发送数据和自动接收数据的双重功能。在它的基础上稍加修改,即可以让用户选定进行传输的通信端口,并设定这个端口的相关参数,包括波特率、数据位、停止位、奇偶校验和流量控制等。

一、 Pcomm的设置
启动C++Builder3.0,点击File/NewApplication,建立一个项目文件,修改表单的Name属性为Comm,然后存盘,命名项目(Project)为CommTest,命名单元(Unit)为Comm。
----PcommLibrary是一个动态连接库(DLL)文件,当使用C++Builder编译器编译PComm.dll库时,我们必须告诉C++Builder的编译器怎样找到这些函数(sio_xxx())。

----因此我们用PCommPro在BorlandC++Builder中开发一个串行程序时,必须做到以下两点:

假如你的PcommPro是安装在c:\Programfiles(缺省安装目录)目录下,把c:\Programfiles\PcommPro\Lib下的Pcommb.lib文件加入到C++Builder的View菜单中ProjectManager的项目中,使之成为项目的一个单元(unit)。
把#include"c:\Programfiles\PcommPro\Lib\PComm.h"包含在你的Comm.cpp中。

二、 表单及属性的设置
添加控件,设置各控件的Name和Caption属性。
该通信程序的工作原理为中断方式,即当输入缓存内有数据时,就会触发Pcomm的中断函数sio_cnt_irq(Port,*CntIrq,count),再由它启动中断服务程序CntIrq(),然后由数据接收函数sio_read(port,ibuf,len)来接收数据并做其他相应的处理;至于函数Open()、Sent()、Close()则分别为打开按钮、发送按钮、关闭按钮的click事件函数;SendData、ReceiveData分别为发送数据编辑框和接收数据编辑框相对应的字符串变量。

三、主程序的编制
双击表单上的Button控件,就会产生相应的事件,如双击"打开"按钮,就会产生Open()事件函数。在这些函数中添加代码,以及PcommPro的串行控制函数,就能实现对串口事件的处理。其中一个需要注意的问题是SendData和ReceiveData都为AnsiString字符串,而PcommPro的函数所需发送和接收的字符串都为char型,因此要正确使用Pcomm函数,还要注意字符串转换。AnsiString字符串可通过c_str()函数转换为char型,而char行字符串转换为AnsiString则比较简单。可用AnsiString(char)把char型强制转换为AnsiString型。程序主要代码如下所示:


void__fastcallTComm::Open(TObject*Sender)
//串口打开函数
{
inti;
sio_open(port);//打开串口
sio_ioctl(port,B2400,P_NONE|BIT_7|STOP_1);
//设置串口参数
 //包括波特率、数据位、停止位、奇偶校验
void__stdcall(*p)(int);
p=cntirq;
i=sio_cnt_irq(port,*p,1);//设置中断函数
}
//-----------------
void__fastcallTComm::Sent(TObject*Sender)
//数据发送函数
{
char*SendData=newchar[20];
SendData=SentEdit->Text.c_str();
//把SendEdit中的AnsiString型字
符串转换为char型
sio_write(port,SendData,20);//发送数据
}
//-----------------
void__fastcallTComm::Close(TObject*Sender)
//串口关闭函数
{
sio_close(port);//关闭串口
}
//-----------------
void__stdcallcntirq(intport)
//中断服务函数(手工生成函数)
{
charibuf[20];
AnsiStringReceiveData[20];
sio_read(port,ibuf,20);//接收数据
ReceiveData=Ansistring(ibuf);
//char字符串转换AnsiString型字符串
ReceiveEdit->Text=ReceiveData;
//显示接受到的字符串
}




在程序中,我们使用了一些sio_xxx()型的函数,它们都是Pcommpro自带的串行通信函数(函数的具体用法可以参考Pcommpro的帮助),通过这些函数,我们可以对串行端口进行设置。
sio_open(port)和sio_close(port)为打开串口和关闭串口函数,参数port可设置具体操作的串口;sio_ioctl(intport,intbaud,intmode)为串口控制函数,可设置串口的波特率、数据位、停止位、奇偶校验;至于sio_write(port)和sio_read(port),则为读串口和写串口函数;sio_cnt_irq(intport,VOID(CALLBACK*func)(intport),intcount)为中断函数,当串口有数据时,就触发该函数,然后该函数就会启动其中断服务程序VOID(CALLBACK*func)(intport)(为一函数指针),这里是调用cntirq()函数接收数据,该函数需要程序员手工生成。

由此我们可以看出,只要我们对程序稍加修改,在表单上再添加一些控件,使得sio_xxx()这些函数的参数可以由用户界面输入,就可以做到由用户选定进行数据传输的通信端口,并设定这个端口的相关参数,包括波特率、数据位、停止位、奇偶校验和流量控制等
wxf0204 2005-09-13
  • 打赏
  • 举报
回复
晕,直接使用API也一样的啊!方法太多了!
morven 2005-09-12
  • 打赏
  • 举报
回复
但在C++ Builder下如何才能添加进去呢?!
Tipel 2005-09-12
  • 打赏
  • 举报
回复
有很多com控件,为什么不用?例如mscomm?

3,846

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 无线
社区管理员
  • 无线
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧