C++builder 和单片机通信时数据帧错

selffight 2014-03-25 02:20:10
大神们好,我要写一个上位机和单片机通信的小程序,目前主要是看能不能从单片机的485口读回数据来,是用C++builder 6.0写的,请帮我看看我写的数据帧那一块是哪里出错了;现在是我把MSComm1->CommPort写死了(主要是我不会用Listbox),调试时那个Com口通过485工装和单片机的485口已经连接好了)。

以下是Unit1.cpp文件内容:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "MSCommLib_OCX"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
if(MSComm1->PortOpen!=true)
{
MSComm1->CommPort=9; //设置通信端口号为COM1
MSComm1->InputMode=1; //设置串口传入数据为二进制
MSComm1->Settings = "4800,n,8,1"; //设置串口参数
MSComm1->InBufferSize=512;
MSComm1->OutBufferSize=1024;
MSComm1->RThreshold=1;
MSComm1->SThreshold=1;
MSComm1->PortOpen=true; //打开通信端口1
Memo1->Text="";
}
else
{
ShowMessage("串口已经打开");
return;
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{
MSComm1->PortOpen=false;
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Memo1->Text="";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i;
String temp="FE FE FE FE 68 AA AA AA AA AA AA 68 13 00 DF 16";
byte buff[15];
buff[0]=StrToInt(0xFE);
buff[1]=StrToInt(0xFE);
buff[2]=StrToInt(0xFE);
buff[3]=StrToInt(0xFE);
buff[4]=StrToInt(0x68);
buff[5]=StrToInt(0xAA);
buff[6]=StrToInt(0xAA);
buff[7]=StrToInt(0xAA);
buff[8]=StrToInt(0xAA);
buff[9]=StrToInt(0xAA);
buff[10]=StrToInt(0xAA);
buff[11]=StrToInt(0x68);
buff[12]=StrToInt(0x13);
buff[13]=StrToInt(0x00);
buff[14]=StrToInt(0xDF);
buff[15]=StrToInt(0x16);

OleVariant Txbuff;
Txbuff=VarArrayCreate(OPENARRAY(int,(0,15)),varByte);
for(i=0;i<=15;i++)
{
Txbuff.PutElement(buff[i],i);
}
MSComm1->Output=Txbuff;
Memo1->Text=temp+'\n';
/* String temp="FEFEFEFE68AAAAAAAAAAAA681300DF16",temp1;
Txbuff

data=Edit1->Text;
temp="0x"+Edit1->Text; //转换成十六进制字符串
buff=StrToInt(temp); //字符串转换成整数
Txbuff=VarArrayCreate(OPENARRAY(int,(0,0)),varByte);
Txbuff.PutElement(buff,0);
MSComm1->Output=Txbuff; */
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
//MSComm1->PortOpen=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
Memo1->Text="hei hei! 嘿嘿!";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MSComm1Comm(TObject *Sender)
{
String temp;
byte buff[100];//声明一个存储接收数据的缓冲区
int ByteNum;//收到的字节数
OleVariant RxBuff;
if(MSComm1->CommEvent==comEvReceive)//表示接收缓冲区内有字符
{
if(MSComm1->InBufferCount>0)
{
RxBuff=MSComm1->Input;//如果缓冲区中有多于一个字节的数据
ByteNum=RxBuff.ArrayHighBound();
for(int i=0;i<=ByteNum;i++)
{
buff[i]=RxBuff.GetElement(i);
}
for(int i=0;i<=ByteNum;i++)
{
temp=IntToHex(buff[i],2)+" ";
}
Memo1->Text=temp;
}
}
else
{
Memo1->Text="数据未收到?";
Memo1->Font->Color=clRed;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
以下是Unit1.h内容:
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "MSCommLib_OCX.h"
#include <OleCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
TButton *Button3;
TMSComm *MSComm1;
TButton *Button4;
TButton *Button5;
TMemo *Memo1;
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button4Click(TObject *Sender);
void __fastcall Button5Click(TObject *Sender);
void __fastcall MSComm1Comm(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
/////////////////////////////////////////////////////////////////////////////////////
以下是Form1截图:
...全文
309 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Test.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "MSCommLib_OCX" #pragma resource "*.dfm" TForm1 *Form1; String temp1; String temp2; byte buff[100]; int j=0,ByteNum;//收到的字节数; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { if(MSComm1->PortOpen!=true) { MSComm1->CommPort=1; //设置通信端口号为COM15 MSComm1->InputMode=1; //设置串口传入数据为二进制 MSComm1->Settings = "9600,n,8,1"; //设置串口参数 MSComm1->InBufferSize=2048; MSComm1->OutBufferSize=1024; MSComm1->RThreshold=1; MSComm1->SThreshold=1; MSComm1->PortOpen=true; //打开通信端口1 Memo1->Text=""; } else { ShowMessage("串口已经打开"); return; } } //--------------------------------------------------------------------------- //发送数据 void __fastcall TForm1::Button1Click(TObject *Sender) { buff[0]=StrToInt(0xFE); buff[1]=StrToInt(0xFE); buff[2]=StrToInt(0xFE); buff[3]=StrToInt(0xFE); buff[4]=StrToInt(0x68); buff[5]=StrToInt(0xAA); buff[6]=StrToInt(0xAA); buff[7]=StrToInt(0xAA); buff[8]=StrToInt(0xAA); buff[9]=StrToInt(0xAA); buff[10]=StrToInt(0xAA); buff[11]=StrToInt(0x68); buff[12]=StrToInt(0x13); buff[13]=StrToInt(0x00); buff[14]=StrToInt(0xDF); buff[15]=StrToInt(0x16); OleVariant Txbuff; Txbuff=VarArrayCreate(OPENARRAY(int,(0,15)),varByte); for(int i=0;i<=15;i++) { Txbuff.PutElement(buff[i],i); temp1+="0x"+IntToHex(buff[i],2)+" "; } MSComm1->Output=Txbuff; //Memo1->Lines->Strings[j++]; Memo1->Text=temp1; } //--------------------------------------------------------------------------- //清空文本框 void __fastcall TForm1::Button2Click(TObject *Sender) { Memo1->Text=""; Memo2->Text=""; temp1=""; temp2=""; } //--------------------------------------------------------------------------- //关闭窗体 void __fastcall TForm1::Button3Click(TObject *Sender) { MSComm1->PortOpen=false; Close(); } //--------------------------------------------------------------------------- //关闭串口 void __fastcall TForm1::Button4Click(TObject *Sender) { MSComm1->PortOpen=false; } //--------------------------------------------------------------------------- //接收到的数据字节 void __fastcall TForm1::Button5Click(TObject *Sender) { String s=IntToStr(MSComm1->CommEvent); String s1=IntToStr(ByteNum); Memo2->Text="CommEvent的值是:"+s+" 收到的字节数是:"+s1; } //--------------------------------------------------------------------------- void __fastcall TForm1::MSComm1Comm(TObject *Sender) { OleVariant RxBuff; if(MSComm1->CommEvent==comEvReceive)//表示接收缓冲区内有字符 { if(MSComm1->InBufferCount>=0) { RxBuff=MSComm1->Input;//如果缓冲区中有多于一个字节的数据 ByteNum=RxBuff.ArrayHighBound(); for(int i=0;i<ByteNum;i++) { buff[i]=RxBuff.GetElement(i); temp2+="0x"+IntToHex(buff[i],2)+" "; } Memo2->Text=temp2; } else { Memo2->Text="只有1个字节数据"; Memo2->Font->Color=clRed; } } else { Memo2->Text="数据未收到?"; Memo2->Font->Color=clRed; } } //---------------------------------------------------------------------------
  • 打赏
  • 举报
回复
只是接收到的数据有几个字节不准确,你再检查一下你的程序
  • 打赏
  • 举报
回复
我用你的程序,可以接收到下位机发送上来的数据啊
hyz_cs 2014-04-01
  • 打赏
  • 举报
回复
引用 10 楼 hjk216 的回复:
[quote=引用 8 楼 hyz_cs 的回复:] 那样改,应该可以的。我试着改后能编译通过,昨天也下了AccessPort,发现收不到单片机发回的数据
你先用AccessPort把协议搞清楚,至少在这个工具内做到能接收到单片机返回的正确数据.
selffight 2014-04-01
  • 打赏
  • 举报
回复
调试发现程序根本没有进入到“void __fastcall TForm1::MSComm1Comm(TObject *Sender)”函数中,结果把那段代码加到button1click事件响应函数中去,能收到数据;只不过不是很理想;
  • 打赏
  • 举报
回复
进不到串口接收事件函数,很可能还是你的串口通信设置不对
selffight 2014-03-31
  • 打赏
  • 举报
回复
引用 4 楼 sunxingzhesun 的回复:
你看看下位机的设置和上位机的设置是否匹配,如果匹配,使用串口调试助手看看能不能收到正常的数据

现在我的Unit1.cpp程序为:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "MSCommLib_OCX"
#pragma resource "*.dfm"
String temp;
byte buff[100];
int j=0,ByteNum;//收到的字节数;
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{

}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
if(MSComm1->PortOpen!=true)
{
MSComm1->CommPort=15; //设置通信端口号为COM15
MSComm1->InputMode=1; //设置串口传入数据为二进制
MSComm1->Settings = "4800,e,8,1"; //设置串口参数
MSComm1->InBufferSize=2048;
MSComm1->OutBufferSize=1024;
MSComm1->RThreshold=1;
MSComm1->SThreshold=1;
MSComm1->PortOpen=true; //打开通信端口1
Memo1->Text="";
}
else
{
ShowMessage("串口已经打开");
return;
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{
MSComm1->PortOpen=false;
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Memo1->Text="";
temp="";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
buff[0]=StrToInt(0xFE);
buff[1]=StrToInt(0xFE);
buff[2]=StrToInt(0xFE);
buff[3]=StrToInt(0xFE);
buff[4]=StrToInt(0x68);
buff[5]=StrToInt(0xAA);
buff[6]=StrToInt(0xAA);
buff[7]=StrToInt(0xAA);
buff[8]=StrToInt(0xAA);
buff[9]=StrToInt(0xAA);
buff[10]=StrToInt(0xAA);
buff[11]=StrToInt(0x68);
buff[12]=StrToInt(0x13);
buff[13]=StrToInt(0x00);
buff[14]=StrToInt(0xDF);
buff[15]=StrToInt(0x16);

OleVariant Txbuff;
Txbuff=VarArrayCreate(OPENARRAY(int,(0,15)),varByte);
for(int i=0;i<=15;i++)
{
Txbuff.PutElement(buff[i],i);
temp+=IntToHex(buff[i],2)+" ";
}
MSComm1->Output=Txbuff;
//Memo1->Lines->Strings[j++];
Memo1->Text=temp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
MSComm1->PortOpen=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
String s=IntToStr(MSComm1->CommEvent);
String s1=IntToStr(ByteNum);
Memo1->Text="CommEvent的值是:"+s+" 收到的字节数是:"+s1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MSComm1Comm(TObject *Sender)
{
OleVariant RxBuff;
if(MSComm1->CommEvent==comEvReceive)//表示接收缓冲区内有字符
{
if(MSComm1->InBufferCount>=0)
{
RxBuff=MSComm1->Input;//如果缓冲区中有多于一个字节的数据
ByteNum=RxBuff.ArrayHighBound();
for(int i=0;i<ByteNum;i++)
{
buff[i]=RxBuff.GetElement(i);
temp+=IntToHex(buff[i],2);
}
Memo1->Text=temp;
}
else
{
Memo1->Text="只有1个字节数据";
Memo1->Font->Color=clRed;
}
}
else
{
Memo1->Text="数据未收到?";
Memo1->Font->Color=clRed;
} /* */
}

目前的情况是PC能把数据帧正确的发送给单片机,但是单片机应答的数据帧PC也能收到,只是提取错误:接收缓冲区内有字符,但是用ArrayHighBound()函数查明收到的字节数却是0
selffight 2014-03-28
  • 打赏
  • 举报
回复
引用 8 楼 hyz_cs 的回复:
byte buff[15]; buff[0]=StrToInt(0xFE); buff[1]=StrToInt(0xFE); buff[2]=StrToInt(0xFE); buff[3]=StrToInt(0xFE); 为什么要这样写,不是应该直接 buff[0]=0xFE; buff[1]=0xFE; ... 这样的吗? 给你推荐个串口监视软件AccessPort,先打开相应的串口监视,然后在你软件打开这个串口后可以看到串口发送,和接收的数据,你看看是你发的和返回的数据都对了没有.
那样改,应该可以的。我试着改后能编译通过,昨天也下了AccessPort,发现收不到单片机发回的数据
selffight 2014-03-28
  • 打赏
  • 举报
回复
引用 7 楼 sunxingzhesun 的回复:
你的程序中( MSComm1->Settings = "4800,n,8,1"; ),第二个参数是n表示无校验,修改成e就是偶校验
是的,改成“4800,e,8,1”,能发数据帧给单片机,但是收不到单片机发回的数据帧,我用别人做的软件能收到,现在在分析原因呢
  • 打赏
  • 举报
回复
上位机发给下位机,下位机接收到数据有反应吗? 你用的单片机的串口通信有多种模式吧,尝试用最常用的模式试试。
lhy 2014-03-26
  • 打赏
  • 举报
回复
引用 3 楼 hjk216 的回复:
[quote=引用 2 楼 lhylhy 的回复:]

    Memo1->text=Memo1->Text+"\n";
这个程序能编译通过,现在发现是这里错了:“MSComm1->Settings = "4800,n,8,1"; //设置串口参数”; 我用别人写的测试软件给单片机发数据帧,发现只有在“偶校验”的情况下,才能通信成功,但是我手动改对象监视器中MSComm1的settings属性发现不能改成“4800,0,8,1”或者“4800,1,8,1”[/quote] MSComm我不熟,你试试调用API通讯吧。
hyz_cs 2014-03-26
  • 打赏
  • 举报
回复
byte buff[15]; buff[0]=StrToInt(0xFE); buff[1]=StrToInt(0xFE); buff[2]=StrToInt(0xFE); buff[3]=StrToInt(0xFE); 为什么要这样写,不是应该直接 buff[0]=0xFE; buff[1]=0xFE; ... 这样的吗? 给你推荐个串口监视软件AccessPort,先打开相应的串口监视,然后在你软件打开这个串口后可以看到串口发送,和接收的数据,你看看是你发的和返回的数据都对了没有.
  • 打赏
  • 举报
回复
你的程序中( MSComm1->Settings = "4800,n,8,1"; ),第二个参数是n表示无校验,修改成e就是偶校验
selffight 2014-03-25
  • 打赏
  • 举报
回复
引用 4 楼 sunxingzhesun 的回复:
你看看下位机的设置和上位机的设置是否匹配,如果匹配,使用串口调试助手看看能不能收到正常的数据
是不匹配的,单片机是偶校验才行,上位机我目前还不知道怎么改成偶校验,不知道您遇到过此类问题没
  • 打赏
  • 举报
回复
你看看下位机的设置和上位机的设置是否匹配,如果匹配,使用串口调试助手看看能不能收到正常的数据
selffight 2014-03-25
  • 打赏
  • 举报
回复
引用 2 楼 lhylhy 的回复:

    Memo1->text=Memo1->Text+"\n";
这个程序能编译通过,现在发现是这里错了:“MSComm1->Settings = "4800,n,8,1"; //设置串口参数”; 我用别人写的测试软件给单片机发数据帧,发现只有在“偶校验”的情况下,才能通信成功,但是我手动改对象监视器中MSComm1的settings属性发现不能改成“4800,0,8,1”或者“4800,1,8,1”
lhy 2014-03-25
  • 打赏
  • 举报
回复

    Memo1->text=Memo1->Text+"\n";
selffight 2014-03-25
  • 打赏
  • 举报
回复
还有一个问题是如何在Memo中输入回车,即如果我要先后发几帧数据,在不手动清除上面的数据帧的情况下,如何实现下一帧数据在下一行显示

703

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder ActiveX/COM/DCOM
社区管理员
  • ActiveX/COM/DCOM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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