请教 vb mscoom 通讯为题

tianliang09 2011-04-04 10:20:44
当上位机(电脑软件)与下位机(单片机)通讯时,上位机总不能将下位机发送的数据(十六进制)全部接受,每次通讯数据量在10万以下,vb的 mscoom控件的InBufferSize属性的最大值为32767,大于此值可能会溢出,但奇怪的是当小于此值时也会丢,请问丢哪里了,期待赐教!!!
以下是电脑软件程序的部分代码:

Private Sub Comm_OnComm()
Dim IntR as integer
Static Resv As Variant '接收数据
Static DataC As Long '串口数据字节数
Static CTestData() As Byte'用于存放接受的字符
Static FactCount As Long '累计实际接收的数据
static TestFlag Boolean'实验结束标志
TestFlag = false
Comm.RThreshold = 0
FactCount = 0
DataC = Comm.InBufferCount: Resv = Comm.Input
ReDim CTestData(100000)
For IntR = 0 To DataC - 1
CTestData(IntR) = Resv(IntR)
FactCount = FactCount + 1
Next IntR

Static CurrTime As Long '等待时间
CurrTime = GetTickCount
'一直接受数据,直到接受完成为止
do
If Comm.InBufferCount >= 1000 Or Abs(GetTickCount - CurrTime) >= 100 Then
CurrTime = GetTickCount
DataC = Comm.InBufferCount: Resv = Comm.Input
For IntR = 0 To DataC - 1
CTestData(FactCount) = Resv(IntR)
FactCount = FactCount + 1
DoEvents
Next IntR
End If
DoEvents
Endif
Do While Comm.InBufferCount = 0 '无数据则测试结束
debug.print "实验结束"
TestFlag = ture
Exit Do
Loop
if TestFlag then Exit do

Exit Sub




...全文
483 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
现在还是人类 2011-04-14
  • 打赏
  • 举报
回复
其实你可以参考一下我资源里的一个串口通讯的VC代码,用起来也很简单的。
http://download.csdn.net/source/2690778
现在还是人类 2011-04-14
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 tianliang09 的回复:]
谢谢您!现在的问题是,想用多线程处理通信,但关于线程的安全退出一直存在问题,请问有何高见,谢谢!!![/Quote]
VB的多线程要编译P代码才好用,而且调试最好是编译EXE后运行看看,直接调试弄不好会有问题的。
VB做多线程本来就很多要注意的地方,个人感觉VC在这方面要简单和稳定很多。
tianliang09 2011-04-14
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 supermanking 的回复:]
找了一下,这里还有一段VB的过程

VB code

Private Sub MSComm1_OnComm()
Dim TempBytes() As Byte, TempBytesCount As Long
Dim X As Long, nowxor As Long, RetEventStr As String
On Error Resume Next
'通……
[/Quote]


谢谢您!现在的问题是,想用多线程处理通信,但关于线程的安全退出一直存在问题,请问有何高见,谢谢!!!
现在还是人类 2011-04-11
  • 打赏
  • 举报
回复
找了一下,这里还有一段VB的过程

Private Sub MSComm1_OnComm()
Dim TempBytes() As Byte, TempBytesCount As Long
Dim X As Long, nowxor As Long, RetEventStr As String
On Error Resume Next
'通过 CommEvent 属性判断是发生什么事件
If MSComm1.CommEvent = comEvReceive Then
JJ = JJ + 1
ReadBytes = MSComm1.Input

ReadCount = UBound(ReadBytes)
'ReDim ReadBytes(ReadCount)
'CopyMemory ReadBytes(0), TempBytes(0), ReadCount + 1

For X = 0 To ReadCount
Select Case Approach
Case 201: '判断是否是结束符号
If ReadBytes(X) = &HB3 Then
'开始运算数据是否正确
Select Case NowCommand
Case &HFF: '机器型号命令
nowxor = &HB2
nowxor = nowxor Xor m_ENumber
nowxor = nowxor Xor NowCommand
nowxor = nowxor Xor Parameter1
For Y = 0 To Parameter1 - 1
nowxor = nowxor Xor ReadByteArray(Y)
Next Y
If xorvalue = nowxor Then
ReturnString = StrConv(ReadByteArray, vbUnicode)
Else
ReturnString = ""
End If
Timer1.Enabled = False
WaitTime = 0
End Select
End If
Approach = 0 '完成处理,将步骤设置为初始阶段

Case 200: '接收异或校检码准备对数据的完整性和正确性进行核对
xorvalue = ReadBytes(X) '将异或校检码存入公共变量中,等就收到包尾信息后再进行处理
Approach = 201 '因为异或校检码属于不定值,所以无法判断是否正确,直接进入下一步等下一步进行判断


Case 8: '机器型号返回信息
ReadByteArray(ReadByteCount) = ReadBytes(X)
ReadByteCount = ReadByteCount + 1
If ReadByteCount >= Parameter1 Then
Approach = 200 '去接收异或校检码准备和对数据的正确性
End If

Case 6: '机器型号返回信息
ReturnString = ""
Parameter1 = ReadBytes(X) '接收返回字符串数量
ReadByteCount = 0
ReDim ReadByteArray(Parameter1 - 1)
Approach = 8 '无法验证数据的正确性,将接收步骤调整为下一步

Case 2: '识别命令,若数据不在可识别的命令数值范围内,作弃包处理
Select Case ReadBytes(X)
Case &HFF: '机器型号命令
NowCommand = &HFF
Approach = 6 '数据符合要求,将接收步骤调整为下一步
Case Else
Approach = 0 '数据不符合接收步骤和相关的规定,放弃该数据(弃包处理)
End Select

Case 1: '识别机号,判断数据是否应该发送到本机的,若不是就不必继续处理了
If m_ENumber = 0 Then
'初始化时没有机号标准,所以直接读取信息成为机号
m_ENumber = ReadBytes(X)
Approach = 2 '数据符合要求,将接收步骤调整为下一步
Else
If ReadBytes(X) = m_ENumber Then
Approach = 2 '数据符合要求,将接收步骤调整为下一步
Else
Approach = 0 '数据不符合接收步骤和相关的规定,放弃该数据(弃包处理)
End If
End If

Case 0: '根据步骤,等待包头的出现,若不是包头数据就继续等待包头
If ReadBytes(X) = &HB2 Then
Approach = 1 '数据符合要求,将接收步骤调整为下一步
End If

End Select
Next X
End If
Exit Sub
错误处理:
Approach = 0
End Sub
现在还是人类 2011-04-11
  • 打赏
  • 举报
回复
再给你看一段PC处理串口通讯的过程,VC代码,该程序的完整过程可以在我的资源里找到

//============================================================================================================
// 关 键 部 分 代 码
//============================================================================================================
void CDemoDlg::OnOK()
{
BOOL OpenState;
DWORD NowTickCount;
DWORD SaveTickCount;
char * SendText;
// 这里很关键,因为 Send 是通过 GlobalSize 来取得指针大小的,所以需要这样分配控件大小
SendText = (char *)GlobalAlloc(GMEM_ZEROINIT, 4);

ReturnValue = 0; //设置默认返回为失败
Approach = 0; //设置接收步骤参数

COMM1.EventRead = OnComm; //设置处理函数
COMM1.ObjClassAddress = (DWORD)this; //设置类地址,确保在OnComm过程中可以调用本类中的一些过程或变量
COMM1.Port = 1; //设置端口
COMM1.BaudRate = CBR_57600; //设置波特率
COMM1.ByteSize = 8; //设置数据位
COMM1.Parity = 0; //设置校检
COMM1.StopBits = 1; //设置停止位
OpenState = COMM1.Open(); //打开串口,这时候便开始了 OnComm 事件的侦听
if(OpenState==TRUE){
sprintf(SendText,"AT\r\n"); //设置要发送的文本内容(当然也可以发送字节流)
COMM1.Send((BYTE*)SendText); //发送文本到串口

//=========== 以下做超时处理 ===========
//超时处理总共有两个全局变量控制
//ExecOver 和 ReturnValue
ExecOver = FALSE;
SaveTickCount = GetTickCount();
while(ExecOver==FALSE){
Sleep(5);
NowTickCount = GetTickCount();
if(NowTickCount-SaveTickCount>=1000){
//超过1秒钟还未正常返回结果就自动退出循环
ReturnValue = 0;
ExecOver=TRUE;
}
}
COMM1.Close();
}
if(ReturnValue==1){
MessageBox("串口1接入的设备支持AT命令。","执行结果",64);
}else{
MessageBox("没有检测到串口1接入支持AT命令的设备。","执行结果",64);
}
}

void CDemoDlg::OnComm(DWORD pClassAddress, BYTE *ReadBuffers, DWORD ReadCount)
{
// pClassAddress 类地址,由用户自行设置 ObjClassAddress 而来
// ReadBuffers 从串口缓冲区读到的数据指针
// ReadCount 从川口缓冲区读到的数据大小
//=============== 还原类的方法,以下是范例 ===============
//CDemoDlg * DlgObj;
//DlgObj = (CDemoDlg *)pClassAddress;
//DlgObj->COMM1.Send((BYTE *)"AAA");
//========================================================
// 下面做个简单的信息识别处理

// 还原类事例对象,因为要用到类中的变量
CDemoDlg * DlgObj;
DlgObj = (CDemoDlg *)pClassAddress;

DWORD i;
if(ReadCount>0){
for(i=0;i<ReadCount;i++){
switch(DlgObj->Approach){
case 0:
if((BYTE)ReadBuffers[i]==0x0D||(BYTE)ReadBuffers[i]==0x0A){ //有可能先发换行符号
DlgObj->Approach = 1;
}else if((BYTE)ReadBuffers[i]==0x4F||(BYTE)ReadBuffers[i]==0x62){ //有可能直接发 OK 信息
DlgObj->Approach = 2;
}
break;
case 1:
if((BYTE)ReadBuffers[i]==0x4F||(BYTE)ReadBuffers[i]==0x6F){
DlgObj->Approach = 2;
}else if((BYTE)ReadBuffers[i]==0x0D||(BYTE)ReadBuffers[i]==0x0A){
DlgObj->Approach = 1;
}else{
DlgObj->Approach = 0;
}
break;
case 2:
if((BYTE)ReadBuffers[i]==0x4B||(BYTE)ReadBuffers[i]==0x6B){
DlgObj->Approach = 3;
}else{
DlgObj->Approach = 0;
}
break;
case 3:
if((BYTE)ReadBuffers[i]==0x0D||(BYTE)ReadBuffers[i]==0x0A){
DlgObj->ReturnValue = 1;
DlgObj->ExecOver = TRUE;
}
DlgObj->Approach = 0;
break;
}

}
}
}

现在还是人类 2011-04-11
  • 打赏
  • 举报
回复
具体点?那就给你看一段简单的单片机串口通讯时的处理过程吧

void COM_Event () interrupt 4
{
unsigned char dat = 0;
unsigned char NXorData = 0;
if(RI == 1){
//接收数据 SBUF 为单片机的接收发送缓冲寄存器
dat = SBUF;
RI = 0;
// 这里分析你收到的信息,同事可做出反应
switch(CApproach){
case 0: // 数据包头
if(dat==0xB2){
CApproach = 1;
}
break;
case 1: // 机号
if(dat==MyNumber){
CApproach = 2;
}else{
CApproach = 0;
}
break;
case 2: // 命令
if(dat>=1&&dat<=7){
CCommand = dat;
CApproach = 3;
}else{
CApproach = 0;
}
break;
case 3: // 命令参数
switch(CApproach){
case 1: // 探测设备命令,无参数
CXorCount = dat;
CApproach = 255;
break;
case 2: // 开启通讯监视,无参数
CXorCount = dat;
CApproach = 255;
break;
case 3: // 关闭通讯监视,无参数
CXorCount = dat;
CApproach = 255;
break;
default:
CApproach = 0;
break;
}
break;
case 255: // 接收包尾
if(dat==0xB3){
switch(CCommand){
case 1: // 探测设备命令需要进行异或校验
NXorData = 0xB2;
NXorData = NXorData^MyNumber;
NXorData = NXorData ^ CCommand;
if(NXorData==CXorCount){
SendBufToPort("LTC-20100409A",13);
}else{
CApproach = 0;
}
break;
case 2: // 开启通讯监视命令需要进行异或校验
NXorData = 0xB2;
NXorData = NXorData^MyNumber;
NXorData = NXorData ^ CCommand;
if(NXorData==CXorCount){
AddMinute = 0;
AddSecond = 0;
AddMillisecond = 0;
AddMicrosecond = 0;
Approach = 1;

SendBufToPort("Open stakeout.",14);
}else{
CApproach = 0;
}
break;
case 3: // 关闭通讯监视命令需要进行异或校验
NXorData = 0xB2;
NXorData = NXorData^MyNumber;
NXorData = NXorData ^ CCommand;
if(NXorData==CXorCount){
Approach = 0;
AddMinute = 0;
AddSecond = 0;
AddMillisecond = 0;
AddMicrosecond = 0;
SendBufToPort("Close stakeout.",14);
}else{
CApproach = 0;
}
break;
default:
CApproach = 0;
break;
}
}else{
CApproach = 0;
}
break;
}
}else{
TI = 0;
}

}
tianliang09 2011-04-10
  • 打赏
  • 举报
回复
能说的具体点吗?请教了!
现在还是人类 2011-04-06
  • 打赏
  • 举报
回复
[Quote=引用楼主 tianliang09 的回复:]
当上位机(电脑软件)与下位机(单片机)通讯时,...
[/Quote]
那你知道单片机是怎么工作的吗?那么小的内存单片机既然都可以跑,PC你还怕内存不够会溢出?
不用看你的程序都知道肯定是你的程序方法上就问题。即使是能运行,也是不可取的。
tianliang09 2011-04-05
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dbcontrols 的回复:]
不会好些

引用 7 楼 tianliang007 的回复:
初学串口通讯,望大家多多指教,请问用多线程解决会不会好些?
[/Quote]
有没有别的办法?我查找了些资料,觉得多线程加缓冲池能够稳定些,还不知道会怎样。谢谢!
tianliang09 2011-04-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ybh37 的回复:]
留一个邮箱,给你发我的基于Comm_OnComm()
的测试源码。
双Timer的涉及公司版权,恕不能相赠
[/Quote]
我的信箱是tianliang03@126.com
双Timer会好些吗?我尽量试试,谢谢
dbcontrols 2011-04-05
  • 打赏
  • 举报
回复
不会好些
[Quote=引用 7 楼 tianliang007 的回复:]
初学串口通讯,望大家多多指教,请问用多线程解决会不会好些?
[/Quote]
tianliang007 2011-04-05
  • 打赏
  • 举报
回复
初学串口通讯,望大家多多指教,请问用多线程解决会不会好些?
tianliang007 2011-04-05
  • 打赏
  • 举报
回复
tianliang03@126.com
thinks
咸清 2011-04-04
  • 打赏
  • 举报
回复
留一个邮箱,给你发我的基于Comm_OnComm()
的测试源码。
双Timer的涉及公司版权,恕不能相赠
咸清 2011-04-04
  • 打赏
  • 举报
回复
嘿嘿 的确是发重了
对于通信质量要求高或者数据量偏大的应用,不建议用 Comm_OnComm()
建议:
用双Timer实现。一个管收数据,一个管发数据。建立自己的缓冲区,不间断的接收所有的数据,知道发送端发送完毕。
flfq 2011-04-04
  • 打赏
  • 举报
回复
接收到数据就进行处理,定义那么大数组干嘛,论坛很多串口通信的帖子,看看吧,把数据处理改改
贝隆 2011-04-04
  • 打赏
  • 举报
回复
试一试这个,看看有没有丢失信息的情况,如果没有,依照这个代码写自己的程序即可。
http://download.csdn.net/source/1262066
dbcontrols 2011-04-04
  • 打赏
  • 举报
回复
标题都能写错

863

社区成员

发帖
与我相关
我的任务
社区描述
VB COM/DCOM/COM+
c++ 技术论坛(原bbs)
社区管理员
  • COM/DCOM/COM+社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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