串口接收数据并处理显示的问题.

jinghonglei 2005-03-20 11:53:23
串口接收数据并处理显示的问题.
我做了一个环行缓冲,串口数据用write指针不停地往里面写,而取数据则要等到缓冲里的数据满1000了才可以去取,我原来设置了1个信号量,写1000了置为真;取数据则是用了while(1)的永真循环,在循环里面不停地判信号量是否为真,(循环在主函数里面).
我师傅说这样不好,让我用消息机制,写满1000了,就给取数据的进程发送消息.
我不懂的是,该如何实现呢?用sendmessage?还是用多线程实现?另外你们说我师傅说的有道理吗,为什么消息机制比我的方法好呢?
如果是多线程的话,是不是要搞个主线程,写缓冲线程和读缓冲线程,等满1000了,写线程给读线程发消息?具体怎么实现,请高手给说说吧!
...全文
470 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
krakan 2005-05-16
  • 打赏
  • 举报
回复
1.BCB 菜单: Project->Options->Packages->Add
如果是BCB6: 选择安装的文件夹 yb_base_c6.bpl 和 yb_comm_c6.bpl, 然后按“打开”按钮
如果是BCB5: 选择安装的文件夹 yb_base_c5.bpl 和 yb_comm_c5.bpl, 然后按“打开”按钮

2.BCB 菜单: Project->Options->Directories/Conditionals
Include Path 和 Library Path 都要添上安装路径(包含*.h和*.lib的文件夹)
①Include Path 右面的“…”按钮,添加包含 *.h 文件的文件夹
②Library Path 右面的“…”按钮,添加包含 *.lib 文件的文件夹

3.如果是 Windows 9x 需要在 C:\AUTOEXEC.BAT 文件里面的 PATH=后面添加包含 *.bpl 文件的文件夹
①如果是 Windows NT/2000/2003/XP 需要在:我的电脑->属性->高级->环境变量->系统变量:
②列表里面的“变量”为 Path 的“值”按:“编辑”按钮,添加包含 *.bpl 文件的文件夹
无论是①还是②,文件夹之间的间隔都是用分号隔开。

其中2.非常重要,直接影响编译
其中3.是用来保证使用动态库编译的程序运行找到动态库, 用静态库编译不使用。这个步骤需要重新启动电脑才可生效。
建议大家安装控件时1-3的步都要做。
skphoebe 2005-04-19
  • 打赏
  • 举报
回复
那位大哥叫叫我,控件怎么装得,
为什么我每次装都装不成,complie得时候就有错误,什么少BPI文件啊,什么的,
怎么回事啊??
ghyd 2005-04-19
  • 打赏
  • 举报
回复
用控件就很简单了 ,用事件来通知你的程序来从接收缓冲区中读取数据.我记得好象有这样的成员函数:就是设定接收缓冲区里满了N(这个数值由你来设定)个数据后,触发事件,然后调用你写的回调函数,来读取数据. 类似软中断.
clong320 2005-04-04
  • 打赏
  • 举报
回复
用Victor的串口控件
Maconel 2005-03-29
  • 打赏
  • 举报
回复

你的write在写的时候,肯定是要判断一下是否到1000了的,
也就是说,你的write已经在不停的判断了,而你又用另一个线程又去不停判断,不是很浪费吗。

所以在write发现满1000了后,去执行一个启动读线程的函数比较好。
自己程序里还用消息传来传去,也不见得有什么高明。
jinghonglei 2005-03-28
  • 打赏
  • 举报
回复
我是用控件做的,TComm.我改天把代码贴上来,请大家继续关注,我的意思是,现在数据已经由控件接收到了一个环行缓冲区了.现在读线程要每等缓冲区里写好了1000个才去一次性地读1000个出来.怎么通知读线程呢,用消息机制吗?
UTzlpower 2005-03-24
  • 打赏
  • 举报
回复
你师傅说得有道理,主要处理机制不同.
MEFULEU 2005-03-22
  • 打赏
  • 举报
回复
unit KComm;

interface

uses
SysUtils, Classes,Messages, Windows, Forms;
const
EM_ONREAD = WM_USER + 101;
type
ECommError = class(Exception)
ErrorCode: Integer;
end;
TBaudrate =(br110, br300, br600, br1200, br2400, br4800, br9600, br14400,
br19200, br38400, br56000, br57600, br115200, br128000, br256000);
TParity = (paNone, paOdd, paEven, paMark, paSpace);
TStopbits = (sb10, sb15, sb20);
TDatabits=(da4, da5, da6, da7, da8);
TFlowControl = (fcNone, fcCTS, fcDTR, fcSoftware, fcDefault);
TReceiveDataEvent = procedure(Sender: TObject; Buffer: PChar;
Count: Word) of object;
TCommEvent = procedure(Sender: TObject; Count: integer) of object;
TOnStateEvent = procedure(Sender: TObject; State: DWord) of object;
TKComm = class;

TReadThread = class( TThread )
private
hCommFile: THandle;
kcomm: TKcomm;
hEvent: THandle;
FOnState: TOnStateEvent;
procedure ReadPort;
protected
procedure BreakEvent; //终止事件等等,结束Execute
procedure Execute; override;
public
constructor Create(Handle: THandle;comm: TKComm);
destructor Destroy; override;
property OnState:TOnStateEvent read FOnState write FOnState;
end;

TKComm = class(TComponent)
private
hCommFile: THandle;
ReadThread: TReadThread;
FWriteBufSize: Integer;
FReadBufSize: Integer;
FComPort: string;
FBaudRate: TBaudRate;
FDatabits: TDatabits;
FStopbits: TStopbits;
FParity: TParity;
FWriteTimeout: Integer;
FReadTimeout: Integer;
FOnRead: TReceiveDataEvent;
FOnState: TOnStateEvent;
procedure SetBaudRate(const Value: TBaudRate);
procedure SetComPort(const Value: string);
procedure SetDatabits(const Value: TDatabits);
procedure SetReadBufSize(const Value: Integer);
procedure SetStopbits(const Value: TStopbits);
procedure SetWriteBufSize(const Value: Integer);
procedure SetParity(const Value: TParity);
private
hEvent: THandle;
protected
function GetModemState(Index: Integer): Boolean;
procedure UpdateDataControlBlock;
procedure UpdateCommTimeouts;
procedure CreateHandle; virtual;
procedure DestroyHandle;
procedure ReadPort(Sender: TObject); //后台读数据
procedure ProcessOnState(Sender: TObject; State: DWord);
procedure Emread(var Message: TMessage); message EM_ONREAD;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function OPened: Boolean; //串口是否打开
function OpenComm: Boolean; //打开串口
procedure CloseComm; //关闭串口
function Write(var Buf; Count: Integer): Integer; //写数据
function InQueCount: Integer; //读缓冲区数据长度
function OutQueCount: Integer; //写缓冲区未发送数据长度
procedure ClearComm; //清除端口缓冲区
{Comm escape functions}
procedure SetDTRState(State: Boolean); //True 为高电压, false 为低电压
procedure SetRTSState(State: Boolean);
{Comm status flags}
property CTS: Boolean index 1 read GetModemState;
property DSR: Boolean index 2 read GetModemState;
published
property ReadTimeout: Integer read FReadTimeout write FReadTimeout default 200; //读超时
property WriteTimeout: Integer read FWriteTimeout write FWriteTimeout default 200; //写超时
property BaudRate: TBaudRate read FBaudRate write SetBaudRate default br9600; //波特率
property Databits: TDatabits read FDatabits write SetDatabits default da8; //数据位
property Stopbits: TStopbits read FStopbits write SetStopbits default sb10; //停止位
property Parity: TParity read FParity write SetParity default paNone; //奇偶较验
property ComPort: string read FComPort write SetComPort; //打开串口名
property ReadBufSize: Integer read FReadBufSize write SetReadBufSize default 2048; //读缓冲区大小
property WriteBufSize: Integer read FWriteBufSize write SetWriteBufSize default 2048; //写缓冲区大小
property OnRead: TReceiveDataEvent read FOnRead write FOnRead;
property OnState:TOnStateEvent read FOnState write FOnState;
end;

procedure Register;
implementation
const
sMsgExtention = ' (通讯错误: %d) ';
CommBaudRates: array[TBaudRate] of Integer =
( CBR_110,
CBR_300,
CBR_600,
CBR_1200,
CBR_2400,
CBR_4800,
CBR_9600,
CBR_14400,
CBR_19200,
CBR_38400,
CBR_56000,
CBR_57600,
CBR_115200,
CBR_128000,
CBR_256000);

CommDataBits: array[TDatabits] of Integer =
( 4, 5, 6, 7, 8);

CommParity: array[TParity] of Integer =
( NOPARITY, ODDPARITY, EVENPARITY, MARKPARITY, SPACEPARITY);

CommStopBits: array[TStopbits] of Integer =
( ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS );

procedure Register;
begin
RegisterComponents('KStand', [TKComm]);
end;

procedure RaiseCommError(Msg: string; ErrCode: Integer);
var
E: ECommError;
begin
E := ECommError.Create(Msg + Format(sMsgExtention, [ErrCode]));
E.ErrorCode := ErrCode;
raise E;
end; { RaiseCommError }
{ TKComm }

procedure TKComm.ClearComm;
begin
if OPened then begin
FlushFileBuffers(hCommFile); //完成未完成的传输操作
PurgeComm(hCommFile, PURGE_RXABORT + PURGE_RXCLEAR +
PURGE_TXABORT + PURGE_TXCLEAR)
end else RaiseCommError('串口没打开不能执行清空命令',-1);
end;

procedure TKComm.CloseComm;
var
t1, t2: DWord;
begin
if Opened then
begin
ReadThread.Terminate;
ReadThread.BreakEvent;
SetEvent(hEvent);
t1 := GetTickcount;
t2 := t1;
while (t2 - t1) < 200 do begin //用于等待线程中被等待同步执行的ReadPort函数可以得到执行,要不然会报IO错误.
Application.ProcessMessages;
t2 := GetTickCount;
end;
DestroyHandle;
CloseHandle(hEvent);
end;
end;

constructor TKComm.Create(AOwner: TComponent);
begin
inherited;
FComPort := 'Com1';
hCommFile := INVALID_HANDLE_VALUE;
FReadBufSize := 2048;
FWriteBufSize := 2048;
FReadTimeout := 500;
FWriteTimeout := 500;
FBaudRate := br9600;
FParity := paNone;
FStopbits := sb10;
FDatabits := da8;
ReadThread := nil;
end;

procedure TKComm.CreateHandle;
begin
hCommFile := CreateFile(PCHAR(FComPort),
GENERIC_READ or GENERIC_WRITE, 0, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);

if not Opened then RaiseCommError('串口不能打开', GetLastError);
if GetFileType(hCommFile) <> FILE_TYPE_CHAR then
begin
DestroyHandle;
RaiseCommError('打开文件类型不对', -1);
end;
end;
MEFULEU 2005-03-22
  • 打赏
  • 举报
回复
大哥,别人早就有写好了的串口控件,那一个使用不就ok了
GHOSTWY 2005-03-21
  • 打赏
  • 举报
回复
学习
jinghonglei 2005-03-21
  • 打赏
  • 举报
回复
自己顶一下
问题:是用消息机制还是用多线程?

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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