
代码
unit ScaleDialogForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.SerialPort, System.Generics.Collections;
type
TScaleDialog = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure CancelBtnClick(Sender: TObject);
private
FSerialPort: TSerialPort;
FRecentWeights: TList<Extended>;
FStableWeight: Extended;
FPortName: string;
lblCurrentWeight: TLabel;
lblStatus: TLabel;
CancelBtn: TButton;
procedure InitUI;
procedure InitSerial;
procedure SerialDataReceived(Sender: TObject; const Buffer: TBytes; var Handled: Boolean);
function TryParseWeight(const Data: string): Extended;
procedure CheckStableWeight(CurrentWeight: Extended);
function AllEqual: Boolean;
public
constructor Create(AOwner: TComponent; const APortName, ATitle: string); reintroduce;
property StableWeight: Extended read FStableWeight;
end;
var
ScaleDialog: TScaleDialog;
implementation
{$R *.dfm}
{ TScaleDialog }
constructor TScaleDialog.Create(AOwner: TComponent; const APortName, ATitle: string);
begin
inherited Create(AOwner);
FPortName := APortName;
Caption := ATitle;
FStableWeight := -1;
FRecentWeights := TList<Extended>.Create;
InitUI;
end;
procedure TScaleDialog.FormCreate(Sender: TObject);
begin
// 初始化串口
InitSerial;
end;
procedure TScaleDialog.InitUI;
begin
// 设置窗口属性
Width := 300;
Height := 200;
Position := poScreenCenter;
BorderStyle := bsDialog;
WindowState := wsNormal;
ShowInTaskbar := False;
// 当前重量标签
lblCurrentWeight := TLabel.Create(Self);
with lblCurrentWeight do
begin
Parent := Self;
Caption := '-- kg';
Left := 100;
Top := 30;
AutoSize := True;
end;
// 重量说明标签
with TLabel.Create(Self) do
begin
Parent := Self;
Caption := '当前重量:';
Left := 20;
Top := 30;
AutoSize := True;
end;
// 状态标签
lblStatus := TLabel.Create(Self);
with lblStatus do
begin
Parent := Self;
Caption := '等待数据稳定(连续6次相同值)...';
Left := 20;
Top := 70;
AutoSize := True;
end;
// 取消按钮
CancelBtn := TButton.Create(Self);
with CancelBtn do
begin
Parent := Self;
Caption := '取消';
Left := 180;
Top := 120;
Width := 75;
Height := 25;
OnClick := CancelBtnClick;
end;
end;
procedure TScaleDialog.InitSerial;
begin
FSerialPort := TSerialPort.Create(Self);
with FSerialPort do
begin
PortName := FPortName;
BaudRate := 9600;
Parity := TParity.None;
DataBits := 8;
StopBits := TStopBits.One;
OnDataReceived := SerialDataReceived;
try
Open;
lblStatus.Caption := Format('串口 %s 已打开,等待数据...', [FPortName]);
except
on E: Exception do
begin
ShowMessageFmt('串口 %s 打开失败:%s', [FPortName, E.Message]);
Close;
end;
end;
end;
end;
procedure TScaleDialog.SerialDataReceived(Sender: TObject; const Buffer: TBytes; var Handled: Boolean);
var
Data: string;
Weight: Extended;
begin
// 转换接收到的字节为字符串
Data := TEncoding.UTF8.GetString(Buffer).Trim;
if Data = '' then Exit;
// 解析重量
Weight := TryParseWeight(Data);
if Weight <> -1 then
begin
// 更新当前重量显示
TThread.Synchronize(nil, procedure
begin
lblCurrentWeight.Caption := Format('%.3f kg', [Weight]);
end);
CheckStableWeight(Weight);
end;
Handled := True;
end;
function TScaleDialog.TryParseWeight(const Data: string): Extended;
var
I, J: Integer;
NumericPart: string;
begin
Result := -1;
// 提取数字部分(包含小数点和正负号)
I := 1;
while (I <= Length(Data)) and not (Data[I] in ['0'..'9', '+', '-', '.']) do
Inc(I);
J := I;
while (J <= Length(Data)) and (Data[J] in ['0'..'9', '.']) do
Inc(J);
if I < J then
begin
NumericPart := Copy(Data, I, J - I);
try
Result := StrToFloat(NumericPart);
except
Result := -1;
end;
end;
end;
procedure TScaleDialog.CheckStableWeight(CurrentWeight: Extended);
begin
TThread.Synchronize(nil, procedure
begin
// 保持最近6次数据
if FRecentWeights.Count >= 6 then
FRecentWeights.Delete(0);
FRecentWeights.Add(CurrentWeight);
// 检查是否稳定
if (FRecentWeights.Count = 6) and AllEqual then
begin
FStableWeight := CurrentWeight;
FSerialPort.Close;
// 更新状态并关闭窗口
lblStatus.Caption := Format('数据稳定:%.3f kg,自动确认中...', [FStableWeight]);
Sleep(1000); // 延迟1秒让用户看到状态
ModalResult := mrOk;
Close;
end;
end);
end;
function TScaleDialog.AllEqual: Boolean;
var
First: Extended;
I: Integer;
begin
Result := False;
if FRecentWeights.Count = 0 then Exit;
First := FRecentWeights[0];
for I := 1 to FRecentWeights.Count - 1 do
begin
// 考虑浮点数精度问题,使用小范围误差判断
if not (FRecentWeights[I] >= First - 0.001) or not (FRecentWeights[I] <= First + 0.001) then
Exit;
end;
Result := True;
end;
procedure TScaleDialog.CancelBtnClick(Sender: TObject);
begin
if Assigned(FSerialPort) and FSerialPort.IsOpen then
FSerialPort.Close;
Close;
end;
procedure TScaleDialog.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeAndNil(FRecentWeights);
Action := caFree;
end;
// 主程序调用示例
procedure ShowScaleDialog;
var
Dlg: TScaleDialog;
begin
Dlg := TScaleDialog.Create(nil, 'COM3', '生鲜电子秤采集');
try
if Dlg.ShowModal = mrOk then
ShowMessageFmt('最终稳定重量:%.3f kg', [Dlg.StableWeight]);
finally
Dlg.Free;
end;
end;
end.
实现说明:
-
环境要求:
- Delphi XE8 及以上版本(支持
System.SerialPort单元) - Windows 操作系统(VCL 框架)
- Delphi XE8 及以上版本(支持
-
功能特点:
- 完全实现原 C# 版本的所有功能,包括串口通信、数据解析和稳定性检测
- 使用 VCL 组件库构建界面,保持与原程序相似的布局和风格
- 通过
TSerialPort组件处理串口通信,简化开发 - 采用线程同步机制(
TThread.Synchronize)确保 UI 安全更新 - 考虑浮点数精度问题,使用小范围误差判断相等性
-
使用方法:
- 创建新的 VCL 应用程序
- 将上述代码保存为单元文件并添加到项目
- 在主程序中调用
ShowScaleDialog过程 - 根据实际设备修改串口号(默认 "COM3")
-
注意事项:
- 数据解析逻辑(
TryParseWeight方法)可能需要根据电子秤的实际协议调整 - 串口参数(波特率等)需与电子秤匹配
- Linux/macOS 系统需要使用 FireMonkey 框架并调整串口访问方式
- 数据解析逻辑(
Delphi 电子秤读取:精准计量的得力工具与多元应用
在数字化计量领域,Delphi 凭借其强大的功能和丰富的库,为电子秤数据读取提供了高效且可靠的解决方案。通过上述代码示例,我们可以深入了解 Delphi 在电子秤读取方面的应用,以及其背后的重要意义和广泛的应用场景,同时为初学者提供上手指南。
Delphi 电子秤读取的重要意义
- 高效的数据处理与精度控制:Delphi 能够快速处理电子秤传输的数据,通过精心设计的数据解析函数,如
TryParseWeight,可以准确提取重量数值,并且在处理浮点数时,通过设定合理的误差范围来解决精度问题,确保了计量数据的可靠性。这对于需要精确称重的场景至关重要,能有效避免因数据误差导致的各种问题。 - 易于使用和集成:Delphi 提供了直观的可视化设计工具以及丰富的组件库,使开发者能够轻松创建用户界面,如代码中的
InitUI方法构建了简洁明了的电子秤数据展示界面。同时,它与 Windows 系统的兼容性良好,方便与其他 Windows 应用程序集成,进一步拓展了电子秤数据的应用范围。 - 强大的事件驱动模型:Delphi 采用事件驱动编程模型,代码中的
SerialDataReceived事件处理函数,当串口接收到数据时会自动触发,这种机制能够实时响应电子秤的数据传输,保证数据的及时处理和显示,提高了系统的实时性和交互性。
10 个应用场景
- 超市零售结算:在超市的生鲜区,电子秤与 Delphi 程序配合,快速读取商品重量,自动计算价格并生成标签,大大提高了结算效率,减少人工操作可能产生的误差,为顾客提供快速准确的服务。
- 工业零部件检测:在工业生产线上,利用电子秤对零部件进行称重检测,Delphi 程序读取重量数据,判断零部件是否符合质量标准。例如,汽车制造中发动机零部件的生产,通过精确称重确保产品质量的一致性。
- 物流包裹称重计费:物流行业中,电子秤用于称量包裹重量,Delphi 程序读取数据后与物流管理系统集成,自动计算运费、生成运单信息,优化物流流程,提高物流运营效率。
- 餐饮后厨食材管理:餐厅后厨使用电子秤控制食材用量,Delphi 程序读取重量数据,帮助厨师按照食谱准确配料,保证菜品口味的稳定性,同时实现食材库存的精细化管理,避免浪费。
- 珠宝鉴定与交易:珠宝行业对重量精度要求极高,Delphi 读取电子秤数据为珠宝鉴定和定价提供精确依据,确保珠宝交易的公平公正,维护买卖双方的利益。
- 药品生产质量控制:在制药过程中,Delphi 与电子秤结合,精确称量药品原料和成品,严格控制药品剂量,保障药品质量和安全性,符合药品生产的严格标准。
- 科研实验数据记录:科研实验中,电子秤用于精确称量化学试剂、生物样本等,Delphi 程序读取重量数据并自动记录,提高实验数据的准确性和记录效率,为科研工作提供有力支持。
- 农业农产品收购:在农产品收购环节,电子秤称重结合 Delphi 程序,快速统计农产品重量,计算收购价格,实现农产品收购的自动化和规范化管理。
- 环保废弃物回收计量:环保回收企业利用电子秤对回收的废弃物进行称重,Delphi 程序读取数据,统计回收量,为废弃物处理和资源再利用提供数据支持,同时便于环保监管。
- 实验室样品管理:各类实验室中,对样品进行称重是常见操作,Delphi 程序读取电子秤数据,实现样品重量的精确记录和管理,方便实验人员跟踪样品信息,确保实验的准确性和可重复性。
初学者如何利用
- 学习基础知识:
- Delphi 语言基础:初学者需要掌握 Delphi 的基本语法,包括数据类型、变量、运算符、控制语句、函数和过程等。深入理解面向对象编程的概念,如类、对象、封装、继承和多态,这对于理解和修改电子秤读取程序至关重要。
- 串口通信知识:了解串口通信的基本原理,包括波特率、奇偶校验、停止位和数据位等概念。学习
System.SerialPort库的使用方法,掌握如何配置和打开串口,以及处理串口数据接收事件。 - 可视化编程:熟悉 Delphi 的可视化设计工具,学习如何使用组件库创建用户界面。了解各种组件的属性和事件,如
TForm、TLabel、TButton等,学会布局管理和事件处理,以构建出实用且美观的电子秤数据展示界面。
- 实践与分析代码:
- 运行代码:将上述代码复制到 Delphi 开发环境中,确保相关库已正确安装,运行程序并观察其功能。通过实际操作,了解串口打开、数据读取、重量显示以及稳定性判断等功能的实现过程。
- 代码剖析:仔细分析代码结构,理解每个方法的作用和逻辑。例如,分析
InitSerial方法如何配置和打开串口,TryParseWeight方法怎样解析重量数据,以及CheckStableWeight方法如何判断数据的稳定性。逐步跟踪代码执行流程,掌握数据在各个模块之间的传递和处理方式。
- 扩展与创新:
- 简单修改:尝试对代码进行简单的修改和优化,例如调整串口参数,观察数据传输的变化;或者修改界面布局,让界面更加美观易用。通过这些实践,加深对代码和相关知识的理解。
- 功能扩展:根据实际需求对程序进行功能扩展,比如添加数据存储功能,将读取到的重量数据保存到文件或数据库中;或者增加网络通信功能,将电子秤数据发送到远程服务器,实现数据的远程监控和管理。在扩展过程中,不断提升自己的编程能力和解决实际问题的能力。
通过系统学习基础知识、认真实践分析代码以及积极进行扩展创新,初学者能够逐步掌握利用 Delphi 进行电子秤数据读取的技能,为在各个领域实现精准计量和数据处理奠定坚实基础。
阿雪技术观
让我们积极投身于技术共享的浪潮中,不仅仅是作为受益者,更要成为贡献者。无论是分享自己的代码、撰写技术博客,还是参与开源项目的维护和改进,每一个小小的举动都可能成为推动技术进步的巨大力量
Embrace open source and sharing, witness the miracle of technological progress, and enjoy the happy times of humanity! Let's actively join the wave of technology sharing. Not only as beneficiaries, but also as contributors. Whether sharing our own code, writing technical blogs, or participating in the maintenance and improvement of open source projects, every small action may become a huge force driving technological progress.
778

被折叠的 条评论
为什么被折叠?



