C++Builder 程序员博客
5 Sep
只需要接收数据这个功能就可以,接收的数据来自适配器里
void __fastcall TForm1::MSComm1Comm(TObject *Sender)
{
//AnsiString str;
OleVariant s;
if(MSComm1->CommEvent==comEvReceive)
if(MSComm1->InBufferCount)
{
s=MSComm1->Input;
strComBuffer= strComBuffer + s.AsType(varString);
for (int i = 0; i < s.ArrayHighBound(1); i++)
{
strComBuff[m_iComBuff_Len++] = s.GetElement(i);
}
}
}
}
MSComm1->CommPort=PortNum;
MSComm1->Settings="9600,n,8,1";
MSComm1->InputMode=0;
MSComm1->PortOpen=true;
串口设置
搜一搜,MSCOMM32的文章多的很
它的麻烦就是模式1用变体,模式0是文本,用WideString简单
进一步解释下怎么样?
我可以给个例子
==
邮箱时什么?
4 Sep
如串口调试助手,在输入框中输入字节数据,如:FF 02 33 28 FA AD,然后以十六进制将其发出,输入框无输入量限制。如何实现?请写出尽量完整的代码,谢!!!由于家境贫寒,所以是以才会友,送上1分,意思意思。请见谅!!!
极度感谢i_love_pc(杰子)同志对本帖的大力支持。我已经找到办法了。谢谢!
呵呵。。。昨天忘了和大家共享代码了:)
如下:
String buf;
byte bytebuf[20];
buf = Edit1-> Text;
for (int i = 1; i <= buf.Length(); i++)
if (buf.SubString(i,1) == " ")
{
buf.Delete(i,1);
i–;
}
for (int i = 0; i < buf.Length()/2; i++)
Memo1-> Lines-> Add(StrToInt( "0x " + buf.SubString(i*2+1,2)));
大致就是这样了。感谢大家的关注!
LZ太有才了!
呵呵。。。
请多指教:)
不错,谢谢!
22 Aug
俺弄个程序把接收到的数据放到RichEdit上(动态接收,一收到数据就放在RichEdi上),
发现RichEdit存放一定数据后,后来接收的数据就乱套了,Memo就没有这样的问题,这
是怎么回事,就连那个很有名的软件—串口调试助手V2.2 也有类似的问题。
哪位能人指点一下是什么原因造成的吗?
不知道你怎么做的
以前我也遇到过,你看你是不是变量的size设置大点,试试
以前我的问题是因为接收数据的位数超过变量的最大限,看看是不是同样的原因引起的
接收缓冲够大了,
后来乱是把该一行的数字攫断成几行。
接收到的数据数目是对的,反而Memo自己有时候也把 [效验和] 和回车换行去掉了,造成该换行的时候不换行,
接收的字节数量是对。这想不明白。
具体问题说清楚下,也许我能替你解答
如本来应该这样显示的(-代表任何英文字母;?为效验和(值1到255之间); \n表示回车换行):
————————–?\n //
————————–?\n
————————–?\n
————————–?\n
………………………. //后面的类似
/////////////////////////////////////////////////////
Memo(设置为长度过长会自动换行的)接收有时候显示为:
—————————————————-?\n
—————————————————-?\n ——–
——————?\n
————————–?\n
————————–?\n
—————————————————-?\n———–
—————?\n————————–?\n ///很明显某行的效验和、回车换行被省略掉了。
————————–?\n
————————–?\n
………………………. //后面的类似
RichEdit更离谱:
————————–?\n //
————————–?\n
————————–?\n
————————–?\n
……………………….. //一百多行后变为
——–
———–
——-?\n
——–
———–
——-?\n
———
———
——–?\n //很明显把一行截取三行了。
………………………. //后面的类似
RichEdit里面的内容不是纯文字,里面带格式的,把RichEdit里面的内容当二进制文件传输就没问题了。
俺弄个程序把接收到的数据放到RichEdit上(动态接收,一收到数据就放在RichEdi上),
发现RichEdit存放一定数据后,后来接收的数据就乱套了,Memo就没有这样的问题,这
是怎么回事,就连那个很有名的软件—串口调试助手V2.2 也有类似的问题。
哪位能人指点一下是什么原因造成的吗?
你的意思是不是说只有接受少量数据时才正常,接受多了就不乱是不是这样?
说明你收的的数据中夹杂着二进制数据(非显示字符或空格),
如果应该没有,说明你的通讯线路可能有不稳定的地方,
不要怀疑这些用了很久的东西,找自己的原因
接收的数据是从其他设备送上来的,当然是二进制数据,而且每个字节有可能是0×00–0xFF的任何,
我想就算是非显示字符,Memo或RichEdit都不要自作主张把它删除了,然后我可以把这些非显示字符翻译
成对应的16进制。
不对,Memo或RichEdit是文本窗口,不能显示非显示字符(除了少量,TAB等),遇到了这些字符不会显示,
另外他们还有一个按单词分割换行的功能,非显示字符被认为是单词分割符,造成行显示不正确。
你可以用 Notepad 打开一个二进制文件看看,就明白了。
21 Aug
这是一个串口通讯的程序(网上下的),可是我不知道她从串口接受的数据方在哪里的?我要想串口写数据,该怎么写?请哪位大侠帮一下小弟。说的越详细越好!!!非常感谢了。急急急啊!!!!!!
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <fstream>
using namespace std;
#include <io.h>
#include <string.h>
#include <process.h>
HANDLE hCom ; // 准备打开的串口的句柄
HANDLE hCommWatchThread ; //辅助线程的全局函数
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
UINT CommWatchProc(HWND hSendWnd)
{
DWORD dwEvtMask=0 ;
COMSTAT ComStat ;
DWORD dwErrorFlags,dwLength,dwError;
BOOL fReadStat = FALSE;
LPSTR lpBuffer = NULL;
SetCommMask( hCom, EV_RXCHAR ¦EV_TXEMPTY );//有哪些串口事件需要监视?
WaitCommEvent( hCom, &dwEvtMask, NULL );// 等待串口通信事件的发生
//检测返回的dwEvtMask,知道发生了什么串口事件
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) // 缓冲区中有数据到达
{
ClearCommError(hCom, &dwErrorFlags, &ComStat ) ;
dwLength = ComStat.cbInQue ; //输入缓冲区有多少数据?
if (dwLength > 0)
{
fReadStat = ReadFile(hCom, lpBuffer, dwLength, &dwLength ,NULL); //读数据
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(hCom,NULL, & dwLength, TRUE))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE) continue;
}
}
}
//::PostMessage((HWND)hSendWnd,WM_NOTIFYPROCESS,0,0);//通知主线程,串口收到数据
}
}
return 0;
}
int SerialInit( ) ; //串口初始化
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
static TCHAR szAppName[]=TEXT("HelloWorld");
static TCHAR szClassName[]=TEXT("HelloWorldClass");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
unsigned long * p=NULL;
wndclass.style = CS_HREDRAW ¦ CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
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(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szClassName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,TEXT("This program requires Windows NT !"),
"szAppName",MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szClassName,
TEXT("My Input Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL );
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
SerialInit( );//串口初始化
//*****************开辟新线程********************************************
hCommWatchThread=CreateThread((LPSECURITY_ATTRIBUTES) NULL,//安全属性
0, //初始化线程栈大小,却省为与主线程大小相同
(LPTHREAD_START_ROUTINE)CommWatchProc, //线程的全局函数
NULL, //此处传入了主框架的句柄
0,p);
//*****************开辟新线程********************************************
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
int SerialInit( ) //初始化串口
{
// DWORD dwError;
DCB dcb;
COMMTIMEOUTS to;
BOOL fSuccess;
//**************************打开串口***************************
hCom = CreateFile("COM1", GENERIC_READ ¦ GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hCom == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,TEXT("打开串口错误!"),
"ok",MB_ICONERROR);
}
//***************************打开串口****************************
//***************************配置串口****************************
GetCommState(hCom,&dcb);
dcb.BaudRate = 9600; //波特率为9600
dcb.ByteSize = 8; //数据位数为8位
dcb.Parity = NOPARITY; //无校验
dcb.StopBits = ONESTOPBIT; //一个停止位
dcb.fBinary = FALSE;
if(!SetCommState(hCom,&dcb))
{
MessageBox(NULL, TEXT("设置错误"), "OK", MB_ICONERROR);
}
SetupComm(hCom, 1024, 1024);
//PurgeComm(hCom, PURGE_TXCLEAR);
PurgeComm( hCom, PURGE_TXABORT ¦ PURGE_RXABORT ¦ PURGE_TXCLEAR ¦ PURGE_RXCLEAR ); //清干净输入、输出缓冲区
//***************************配置串口****************************
//******************将串口读操作的超时设定为10 毫秒**************
memset(&to, 0, sizeof(to));
to.ReadIntervalTimeout = 10000;
SetCommTimeouts(hCom, &to);
//******************将串口读操作的超时设定为10 毫秒**************
//******************设置事件掩模来监视指定通信端口上的事件(监视串口的错误和接收到字符两种事件)********
fSuccess=SetCommMask(hCom, EV_RXCHAR ¦EV_TXEMPTY );//设置事件驱动的类型
if (!fSuccess)
{
MessageBox(NULL, TEXT("SetCommMask 错误"), "OK", MB_ICONERROR);
}
//******************设置事件掩模来监视指定通信端口上的事件(监视串口的错误和接收到字符两种事件)********
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
char temp[128];
switch(message)
{
case WM_CREATE:
return 0;
//获取键盘输入
case WM_KEYDOWN:
switch(wParam)
{
//按Esc键推出
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
//其余按键发声
MessageBeep(MB_OK);
return 0;
//按下鼠标左键发声
case WM_LBUTTONDOWN:
MessageBeep(MB_OK);
return 0;
//按下鼠标右键退出
case WM_RBUTTONDOWN:
PostQuitMessage(0);
return 0;
//鼠标位置改变,显示坐标
case WM_MOUSEMOVE:
hdc = GetDC(hwnd);
sprintf(temp,"x: %d , y: %d",LOWORD(lParam),HIWORD(lParam));
TextOut(hdc,10,10,temp,strlen(temp));
ReleaseDC(hwnd,hdc);
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&rect);
EndPaint(hwnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
我给你个例子,你自己看看
发过去了
非常感谢,还有哪些大哥能帮我啊?请快点吧。。
小弟非常着急啊。。。
请哪位帮我分析一下这个程序。。。
不胜感激!!!
怎么没有人说话呢????
5 Aug
我用MSCOMM控件做一个串口通讯程序,发送没问题,接收的时候,我是想把接收到的16进制数据转换成字符形式,并在文本框里显示,下位机发上来的数据是发送的字符的ASCII码值,最后一个是"!",上位机给下位机发送的查询命令不同,下位机每次返回来的数据字节数也不同,但是每次最后都会有一个"!",做为结束标志,我“!”作为结束判断标志,但我程序也未能实现,另外一个就是当我发送一个数据后,关闭窗体,却提示如下错误:“Project Project1.exe raised exception class EAccessViolation with message 'Accessviolation at address 0041A55B.Read of address 0000034'.Process stopped.Use Step or Run to continue.”错误,请问这是什么错误啦?我该怎么写程序去判断那个“!”符号啦?
我的串口接收程序如下:
void __fastcall TForm1::Uart_RecevieByte(TObject *Sender)
{
OleVariant RxBuff;
unsigned int ByteNum;
switch (MSComm1->CommEvent)
{
case comEvReceive:
{
if(MSComm1->InBufferCount>0)
{
RxBuff=MSComm1->Input;//如果缓冲区中有多于一个字节的数据
}
ByteNum=RxBuff.ArrayHighBound(1);//将实际读的字节数取出
for(int i=0;i <=ByteNum;i++)
{
ReBuff[BuffPtr++] = RxBuff.GetElement(i);//将接收数据读入自己的缓冲区
}
//if(UpCase(ReBuff[BuffPtr-1])=='!')
if(BuffPtr == 17)
{
for(int i=0;i <BuffPtr;i++)
{
Edit1->Text +=char(ReBuff[i]);
}
BuffPtr=0;
MSComm1->InBufferCount=0;
//success = true;
//Beep();
}
}
}
}
如果我把这段接收程序屏蔽掉,关闭窗口的时候就不提示以上错误,请问我这程序该如何实现比较好?
5 Aug
大虾们:
问题是这样的,我用的仪表采集到数据显示后有RS485通讯接口,我把这几个仪表的485口串接
起来,然后用一个485转232接头接到PC机上。仪表是采用ModBus协议:从站地址 功能代码 数据区 CRC16
我用API函数写的串口打开和发送数据的命令,但是不知道如何控制他们显示在软件上呢?
我写的串口接受程序和硬件连也显示不出来ⷂ𗂷ⷂ𗠼br> 求助啊~~~~~~~~~~~~~
30 Jul
通讯协议包括头文件(Soh) 地址码(Addr) 数据块长(Len) 数据块(Data) 检验和(Checksum) 尾块(LF)
其中Checksum为从Addr开始到数据快捷素所有字节之和(即字符的ASC码之和),取14位(最高2为丢弃),分高、低两个7bit字节,将bit8置1.低字节在前,高字节在后。
例如 ,从Addr开始到数据块结束所有字节之和为32341(7E55H),则对其2 位最高位后为3E55H,氛围两个7字节7CH和55H,最高位置1后为FCH和D5H,所以检验和为D5H,FCH(低字节在前)。
请问这个检验和的计算如何实现?
BYTE Data[8];
WORD wCheckSum;
BYTE b1,b2;
wCheckSum = 0;
for ( int i = 0; i < 8; i++ )
{
wCheckSum += Data[i];
}
wCheckSum &= 0×3FFF; // 去掉最高的两位
b1 = (BYTE)wCheckSum; // 低字节
b1 ¦= 0×80; // 将最高位置1
b2 = (BYTE)((wCheckSum >> 7); // 高字节
b2 = ¦= 0×80; // 将最高位置1
wCheckSum = ((WORD)b1) < < 8;
wCheckSum ¦= b2; // 最后的校验值
写的非常清楚,很是感谢。
我还想问下,发送到串口缓冲区的数据是十六进制的形式,我想吧接受到的数据在解析以前先在Memo控件里显示,请问这个格式应该怎么样转化呢?
谢谢!
答者必有分!
20 Jul
关于串口用C++ builder 编程,请问RS232 与RS485 软件编程上有否区别?如果一端为232,另一端为485,能否实现通讯?是不是要加一个硬件转换的玩意?RS232可以用MSCOMM32控件编程,RS485可以用吗?
rs-232-485转换器,有卖的。
RS485可以使用 Victor串口VCL控件 第三方控件
http://www.ccrun.com/view.asp?id=157
232和485只是电气特性不同而已,编程是一样的
232和485之间需要一个转换,市面上有转换器,很便宜的
232 跟 485编程是有区别的,485 需要改变 RTS 值控制读或者写状态
但是如果是从 232 出来通过 232-485 转换器的话,转换器会自动控制,不用编程管理 232 端口
工业级的 485 转换器要 200 多 RMB的
顶顶。
个人推荐,控件用SPComm,比MSComm好用。至于485和232的问题,PC的程序只与232接口,所以跟232下面是否转的485没有关系。
自己弄个也很快.
要用串口想某设备写入所谓的两字节ASCII命令,是否直接向其写入两字节字符串即可?因为字符串在算机中就是以ASCII码存放的,这样理解是否正确?请高手们指点迷津。
16 Jul
向串口发送一个字符串a,
Rd_232是串口句柄
nNumberOfBytesToWrite=a.Length();
程序执行WriteFile(Rd_232,&a,nNumberOfBytesToWrite,&lpNumberOfBytesWrite,NULL);
结果:lpNumberOfBytesWrite 和 nNumberOfBytesToWrite 不一致,
比方说:向串口发送了100个字符,可函数WriteFile实际发送了99个
我试过清空串口输入、输出缓冲区,可没用。各位大虾,怎么解决?
查你的SetCommState参数,可能是参数设置的问题
怎么知道是哪些字符没有发送?
应该是: nNumberOfBytesToWrite=a.Length()+1; 因为对于字符串来说实际长度是和字符数组长度不一样的,串比数组长度多一个字符长度,即'\0',实际串口发送是一个一个字符发送,它会认为最后一个字符是'\0',而不发送最后一个字符。
nNumberOfBytesToWrite=a.c_str();//这是发送字符串,a.Length()发的是a字符串的字节数,结果肯定不一样了。
8 Jul
我同学要从单片机通过串口,传输数据给电脑,我如何利用BCB做个软件,接收那些数据
http://www.ccrun.com
这个网站有victor下载的,感觉还不错!
我想在BCB上实现。。。又这类函数么
用MSCOMM控件,再加个定时器,每100MS读一次串中就行 了,很稳定,百试不爽!
自己写太麻烦,用控件好