十万火急,关于串口通讯,高手请进(100分)

  • 主题发起人 主题发起人 yk_wry
  • 开始时间 开始时间
Y

yk_wry

Unregistered / Unconfirmed
GUEST, unregistred user!
我在写串口通讯时,碰到这样的问题。当我初始化串口后然后关闭串口。退出程序,程序就
提示 Runtime on at XXXXXX 出错。我用的是MSCOMM控件,但在我已经完成的另一套软件中加入同样的代码,不会出错。是不是MSCOMM控件的BUG啊。名位多多指点。
 
初始化串口的代码如下:
///////////////////////////////////////////////////////////////////
//串口初始化
// 成功:0 失败:-1
///////////////////////////////////////////////////////////////////
function ComInitReadWrite(pComPort:pchar; CardType: Pchar):integer;stdCall;
begin
Result:=-1;
if not Assigned(myCom) then
mycom:=TMSComm.Create(nil);
if mycom.PortOpen then
mycom.PortOpen:=false;
mycom.CommPort:=GetComID(pComPort); //指定串口号
if CardType = 'MiFare' then mycom.Settings:='19200,n,8,1'
else
if CardType = 'ID' then mycom.Settings:='14400,n,8,1'
else
mycom.Settings:='19200,n,8,1';
mycom.InputMode:=0; //ASCII码格式传送数据
mycom.RThreshold:=0; //禁止接收中断
mycom.SThreshold:=0; //禁止发送中断
try
mycom.PortOpen:=true; //打开串口
except
exit; //串口打开出错
end;
Result:=0;
end;
//关闭串口
////////////////////////////////////////////////////////////////////////////
//关闭串口
////////////////////////////////////////////////////////////////////////////
function ComExitReadWrite():integer;stdCall;
begin
if mycom.PortOpen then
mycom.PortOpen:=False;
Result:=0;
end;
上面是写成DLL的。
外部调用如下:
//初始化串口
function GetReadWriteThandle(PortNo : string): boolean;
begin
Result:= (ComInitReadWrite(pchar(PortNo),'MiFare') = 0);
end;
//关闭串口
procedure ClearHandle();
begin
ComExitReadWrite();
end;

///程序中初始化串口/
procedure TMainFrm.Button2Click(Sender: TObject);
var
CardIn: string;
begin
GetReadWriteThandle(sCom);
ClearHandle;
end;


 
我用串口也是用mscomm控件
只是比较笨,用的是拖个控件到窗口上;
反正你计算机也就那么两串口,这样不用你自己创建,系统负责创建和销毁
你只需要动态设置mscomm的属性即可。

嘿嘿,写完又看了一遍,原来你是写进DLL了,对这个不熟,就当我骗分了。
 
以前做过一个纯SDK的试验品,现在都忘了,要是你有用我就找找。
 
mscomm 是activex组件,往dll里写恐怕很麻烦
 
mscomm32.ocx你使用的机上要有这个,然后还要注册成功后才能用,你有确定你使用的机上正确的注册了该控件了吗?
 
确认你的机器上存在这个控件且已经用regsvr32注册了.
 
他们说得都对,要注册
或者不要用OCX控件,spcomm,cport都不错啊
 
问题已经解决,原因是我的窗口BorderStyle是bsDialog,但是非常奇怪,我其他的软件就没有这个问题。参与都有分。
to 6p14
  好的你给我发到chinawry@zj165.com 我学习学习。谢谢。
 
问题已经解决???我只能參與接分了!
 
想順便問一下樓主,知道mscom控件的延時是如何處理的嗎?
怎樣設定延時呢?
 
好的,你等等再结贴,我回头发给你,我也想赚点分
 
你退出(释放)dll的时候 对 mycom:=TMSComm.Create(nil);
mycom这个对象是怎么处理的?
 
请教楼主:
mscomm 文本格式能收到hex(00)的数据?怎么设置?
当数据值大于hex(80)时,收到的是hex(3F),为什么?
 
我建议你用SPCOMM
我以前好像也碰到过这样问题,
MSCOMM一定要在注册过的机子上使用。
 
完整的已经发了邮件给你。
串口主程序:

#include<windows.h>
#include"StdAfx.h"
#include"ChuanKou.h"


HINSTANCE hInst;
DWORD Thread1;
DWORD Thread2;
HANDLE hEvent[2]; //事件对象句柄数组
HWND hMainWnd;
DWORD i=1;//线程1结束标志
DWORD j=1;//线程2结束标志
int ThreadPriority;
HANDLE hCom;
HANDLE hThread1; //线程句柄
HANDLE hThread2; //线程句柄
char text_buffer[1024];//编辑框字符缓冲区
char Buffer[1024];
char EditShow[1024];

DWORD WriteLength;
DWORD Writen;

char szAppName[]="这是个串口通信程序";

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) //创建主窗口
{
//char szAppName[]="这是个串口通信程序";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
hInst=hInstance;

////////////////定义窗口类

wndclass.cbSize =sizeof(wndclass);
wndclass.style =CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc =ChuanKouProc;
wndclass.cbClsExtra =0;
wndclass.cbWndExtra =0;
wndclass.hInstance =hInstance;
wndclass.hIcon =LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor =LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
wndclass.lpszClassName=szAppName;
wndclass.lpszMenuName =NULL;
wndclass.hIconSm =LoadIcon(NULL,IDI_WINLOGO);

RegisterClassEx(&amp;wndclass); //注册窗口类

hwnd=CreateWindow(szAppName, //窗口类名
"ChuanKouAppication",//窗口标题
WS_SYSMENU|WS_MINIMIZEBOX,//窗口样式
CW_USEDEFAULT,//窗口起始位置x

CW_USEDEFAULT,//窗口起始位置y

//CW_USEDEFAULT,//用于缺省大小x
//CW_USEDEFAULT,//用于缺省大小y
300, //窗口长
100, //窗口宽

NULL,//无父事例句柄
NULL,//无菜单
hInstance,//当前事例句柄
NULL);//无参数
hMainWnd=hwnd;
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);

while(GetMessage(&amp;msg,NULL,0,0))
{
TranslateMessage(&amp;msg);
DispatchMessage(&amp;msg);

}
return msg.wParam;
}

LRESULT CALLBACK ChuanKouProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
static HWND hWndEdit1; //编辑框句柄1
static HWND hWndEdit2; //编辑框句柄1
static HWND hWndButton1; //按钮句柄
static HWND hWndButton2; //按钮句柄
static HWND hWndButton3; //按钮句柄


switch(msg)
{
case WM_CREATE:
hWndEdit1=CreateWindow("EDIT",NULL,
WS_CHILD|WS_VISIBLE|WS_BORDER|
ES_LEFT|ES_AUTOHSCROLL,
0,0,0,0,
hWnd,
(HMENU)IDE_EDIT1,
hInst,
NULL); //创建编辑框子窗口1

hWndEdit2=CreateWindow("EDIT",NULL,
WS_CHILD|WS_VISIBLE|WS_BORDER|
ES_LEFT|ES_AUTOHSCROLL,
0,0,0,0,
hWnd,
(HMENU)IDE_EDIT2,
hInst,
NULL); //创建编辑框子窗口2

hWndButton1=CreateWindow("BUTTON","Send",
BS_PUSHBUTTON|WS_CHILD|
WS_VISIBLE|BS_CENTER,
210,10,80,20,
hWnd,
(HMENU)IDB_BUT1,
hInst,
NULL); //创建按钮子窗口1

hWndButton2=CreateWindow("BUTTON","Exit",
BS_PUSHBUTTON|WS_CHILD|
WS_VISIBLE|BS_CENTER,
210,45,80,20,
hWnd,
(HMENU)IDB_BUT2,
hInst,
NULL); //创建按钮子窗口2

/* hWndButton3=CreateWindow("BUTTON","传送文件",
BS_PUSHBUTTON|WS_CHILD|
WS_VISIBLE|BS_CENTER,
280,225,80,25,
hWnd,
(HMENU)IDB_BUT3,
hInst,
NULL); ////创建按钮子窗口3
*/

///////////////打开串口资源

hCom=CreateFile("COM1", //打开com
GENERIC_READ|GENERIC_WRITE, //可读写
0, //应用程序可在不访问设备情况下查询设备
NULL, //无安全属性
OPEN_EXISTING, //打开方式:若文件不存在则函数失败
FILE_FLAG_OVERLAPPED, //异步通讯方式FILE_FLAG_OVERLAPPED
NULL); //打开串口
if(hCom!=INVALID_HANDLE_VALUE)
MessageBox(hWnd,"串口打开成功","Message",0);


SetupComm(hCom,1024,1024); //设置输入输出缓冲区
PurgeComm(hCom,
PURGE_TXCLEAR| //清空输出缓冲
PURGE_RXCLEAR //清空输入缓冲
); //清空输入输出缓冲区

COMMTIMEOUTS CommTimeOuts;//定义超时结构
CommTimeOuts.ReadIntervalTimeout=1000;
CommTimeOuts.ReadTotalTimeoutMultiplier=5000;
CommTimeOuts.ReadTotalTimeoutConstant=5000;
CommTimeOuts.WriteTotalTimeoutMultiplier=5000;
CommTimeOuts.WriteTotalTimeoutConstant=5000;

if(!SetCommTimeouts(hCom,&amp;CommTimeOuts))
{
CloseHandle(hCom);
MessageBox(hWnd,"设置超时失败","Message",0);
return FALSE;
}
DCB dcb;
GetCommState(hCom,&amp;dcb); //读串口原来的参数设置
/////////设置DCB块结构
dcb.BaudRate=9600; dcb.ByteSize=8; dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT; dcb.fBinary=TRUE; dcb.fParity=FALSE;
////////设置DCB为:波特率9600,8字节数据位,无校验,1位停止位,
////////允许2进制位(必须为TUNE),无校验检查

SetCommState(hCom,&amp;dcb);//配置串口参数

///////////建立工作者线程

if(!(hThread1=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc1,//线程函数
NULL,
0,
&amp;Thread1)))//建立线程1(读线程)
MessageBox(hWnd,"出现错误,不能建立读线程","Message",0);

if(!(hThread2=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc2,//线程函数
NULL,
0,
&amp;Thread2)))//建立线程2(写线程)
MessageBox(hWnd,"出现错误,不能建立写线程","Message",0);

ThreadPriority=GetThreadPriority(hThread1); //得到线程1的优先级

SetThreadPriority(hThread2,ThreadPriority+1);//设线程2优先级高于线程1

hEvent[0]=CreateEvent(NULL, //无安全属性
TRUE, //手动设定事件为无通知状态
FALSE, //初始值为无通知状态
NULL //无对象名
); //创建事件对象

SetEvent(hEvent[0]); //设置为通知状态

hEvent[1]=CreateEvent(NULL, //无安全属性
TRUE, //手动设定事件为无通知状态
FALSE, //初始值为无通知状态
NULL //无对象名
); //创建事件对象
break;
case WM_SETFOCUS:
SetFocus(hWndEdit1);
break;

case WM_SIZE: //显示编辑框使之可以随窗口变化而变化(本程序设置窗口不可变)
MoveWindow(hWndEdit1,5,45,200,20,FALSE);
MoveWindow(hWndEdit2,5,10,200,20,TRUE);
break;

case WM_COMMAND:
switch (LOWORD(wParam))
{

case 1111://按下发送文本键后由这里处理此消息
if((WriteLength=GetDlgItemText(hWnd,1114,text_buffer,1024))==0)
MessageBox(hMainWnd,"不能发空信息","Message",MB_OK);
else
{
SetEvent(hEvent[1]);
ResetEvent(hEvent[0]);
Writen=WriteLength;
}
SetFocus(hWndEdit1);
break;
case 1112:
PurgeComm(hCom,
PURGE_TXCLEAR| //清空输出缓冲
PURGE_RXCLEAR //清空输入缓冲
); //清空输入输出缓冲区
CloseHandle(hCom);
CloseHandle(hEvent[0]);
CloseHandle(hEvent[1]);
i=0;
j=0;
PostQuitMessage(0);
break;
}
break;//这里少了这个break造成很大麻烦
case 2222:
MessageBox(hMainWnd," 数据已读入","Message",MB_OK);
break;
case 3333:
MessageBox(hMainWnd," 数据已写入","Message",MB_OK);
break;

case WM_DESTROY:
PurgeComm(hCom,
PURGE_TXCLEAR| //清空输出缓冲
PURGE_RXCLEAR //清空输入缓冲
); //清空输入输出缓冲区
CloseHandle(hCom);
CloseHandle(hEvent[0]);
CloseHandle(hEvent[1]);
i=0;
j=0;
PostQuitMessage(0);
break;

default:
return(DefWindowProc (hWnd,msg,wParam,lParam));
}
return(0);
}

DWORD WINAPI ThreadFunc1(LPVOID lpParameter) //线程函数
{
DWORD dwEvtMask=0;
OVERLAPPED ReadOverLapped;
COMSTAT ComStat;
DWORD dwLength;
DWORD dwErrorFlags;
BOOL fReadStat;
DWORD dwBytesRead;
DWORD dwError;
DWORD NumberOfBytesTransferred;
ReadOverLapped.hEvent=CreateEvent(NULL, //无安全属性
TRUE, //手动设定事件为无通知状态
FALSE, //初始值为无通知状态
NULL //无对象名
); //创建事件对象
DWORD flag;

memset(&amp;ReadOverLapped,0,sizeof(OVERLAPPED));

while(i)
{
WaitForSingleObject(hEvent[0],INFINITE);

SetCommMask(hCom,EV_RXCHAR); //设置监视类型
WaitCommEvent(hCom,&amp;dwEvtMask,&amp;ReadOverLapped);
flag=0;
if(dwEvtMask==EV_RXCHAR) //如果有数据到达
{


do
{
ClearCommError(hCom,&amp;dwErrorFlags,&amp;ComStat); //报告通信设备的当前状态
dwLength=ComStat.cbInQue; //接受到的且未读的数据的长度
memset(Buffer, 0, 1024);

if(dwLength>0)
{

fReadStat=ReadFile(hCom, //读的文件句柄
Buffer, //数据读入的缓冲区地址
dwLength, //要读的数据长度
&amp;dwBytesRead, //指向一个变量,得到读入的长度
&amp;ReadOverLapped //指向重叠结构的指针
);
strcat( EditShow, Buffer ); //数据可能要读几次到Buffer才能读完,
//所以要把读到的数据连接起来
dwError=GetLastError();

if(!fReadStat)
{
if(dwError==ERROR_IO_PENDING)
{
WaitForSingleObject(ReadOverLapped.hEvent,INFINITE);
while(!GetOverlappedResult(hCom,
&amp;ReadOverLapped,
&amp;NumberOfBytesTransferred,
FALSE));
ReadOverLapped.Offset+=NumberOfBytesTransferred;
}
}
else
{
ReadOverLapped.Offset+=dwBytesRead;
}

}

}while(dwLength>0); //循环结束时读操作完成
}


flag=strcmp(EditShow,"");

if(flag)
{
SetDlgItemText(hMainWnd,1115,EditShow);
}
SetEvent(hEvent[0]);
//PostMessage(hMainWnd,2222,0,0);
//Sleep(0);
}
return 0;
}

DWORD WINAPI ThreadFunc2(LPVOID lpParameter)//线程函数
{
DWORD dwEvtMask=0;
OVERLAPPED WriteOverLapped;
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL fWriteStat;
DWORD dwBytesWrite;
DWORD dwError;
DWORD NumberOfBytesTransferred = 0;
WriteOverLapped.hEvent=CreateEvent(NULL, //无安全属性
TRUE, //手动设定事件为无通知状态
FALSE, //初始值为无通知状态
NULL //无对象名
); //创建事件对象
DWORD dwLength;


while(j)
{
memset(&amp;WriteOverLapped,0,sizeof(OVERLAPPED));

LPSTR pBuffer=text_buffer; //得到缓冲区的指针
WaitForSingleObject(hEvent[1],INFINITE);
memset(EditShow, 0, 1024); //将显示缓冲区清零

do
{
fWriteStat=WriteFile(hCom, //写的文件句柄
pBuffer, //要写入数据的缓冲区地址
WriteLength, //要写的数据长度
&amp;dwBytesWrite,//指向一个变量,得到实际写入的长度
&amp;WriteOverLapped //指向重叠结构的指针
);
dwError=GetLastError();
if(!fWriteStat)
{
if(dwError==ERROR_IO_PENDING)
{
WaitForSingleObject(WriteOverLapped.hEvent,INFINITE);
while(!GetOverlappedResult(hCom,
&amp;WriteOverLapped,
&amp;NumberOfBytesTransferred,
FALSE));
WriteLength=WriteLength-NumberOfBytesTransferred;
pBuffer+=NumberOfBytesTransferred;
}
}
else
{
WriteLength=0;
}
}while(WriteLength>0);//循环结束时写操作完成,下面要做些收尾工作
//PostMessage(hMainWnd,3333,0,0);
memset(text_buffer,0,1024);
SetDlgItemText(hMainWnd,1114,"");

ResetEvent(hEvent[1]);
SetEvent(hEvent[0]);

//Sleep(0);
}
return 0;
}


////////////////////////////////////头文件:
LRESULT CALLBACK ChuanKouProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
DWORD WINAPI ThreadFunc1(LPVOID lpParameter);
DWORD WINAPI ThreadFunc2(LPVOID lpParameter);
#define IDB_BUT1 1111
#define IDB_BUT2 1112
#define IDB_BUT3 1113
#define IDE_EDIT1 1114
#define IDE_EDIT2 1115
//#define WM_JOB1 221
//#define WM_JOB2 222


 
不好意思,过年了。。没空上来,结帖了
 
后退
顶部