资源描述
武汉理工大学《测控系统应用软件实训》课程设计说明书
课程设计任务书
学生姓名: 李文瑶 专业班级: 测控1103班
指导教师: 胡剑 韩雪 工作单位: 机电学院测控系
题 目: 测控系统应用软件实训——产品质量监测系统设计
初始条件:
日光灯试验台是用来检测点亮日光灯的整流器或逆变器是否合格的装置,通过多次测量灯管两端的电压和电流,再通过分析,来验证整流器或逆变器工作是否正常。单个整流器或逆变器有不同功率之分,也有可以同时点亮日光灯个数多少之分。检测一个整流器或逆变器,下位机大概会产生30组左右的电压和电流数据。
本实训的目标是设计一个产品质量监测系统,保存日光灯试验台下位机产生的数据信息,并时行产品合格检查、产品质量查询、分类统计和报表打印操作,以期使产品的质量管理工作系统化、规范化、自动化,从而提高生产效率。
设计功能要求:
1、仪器检测结果的输入,包括记录号、检修日期、仪器编号、仪器类型、仪器功率、仪器点亮日光灯个数、检测人员、检测记录。除检测人员和检测记录由工作人员在计算机上直接输入外,其他项都通过串口读入。
2、仪器检测数据的输入,包括记录号、仪器编号、检测电压、检测电流。一条仪器检测结果对应多条检测数据。
3、仪器检测数据以图形方式显示变化趋势。
4、仪器检测信息的查询、修改和删除。
5、仪器类型和功率代码管理。
6、仪器检测信息的报表和打印处理。(选做)
7、密码和权限管理,不同权限用户具有不同的操作权力。(选做)
系统功能模块设计:
对上述各项功能进行集中分块,按结构化程序设计的要求,得到如图1所示的系统功能模块图。
要求完成的主要任务: (包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
1.合理进行数据库设计,数据项和数据结构包括以下部分:
1)仪器检测结果信息表,保存检测结果记录,包括:记录号、检测日期、仪器编号、仪器类型、仪器功率、仪器额定点亮日光灯个数、仪器温升、检测时间间隔、检测人员、检测记录。
2)仪器检测数据信息表,保存检测数据记录,包括:记录号、仪器编号、检测电压、检测电流。
3)仪器类型信息表:记录号、仪器类型。
4)仪器功率信息表:记录号、仪器功率。
5)记录号计数数据表,用于保存其他表格所需的记录号,包括:记录号名称、记录号计数值。
6) 用户信息表:工号、用户名、密码、权限。(选用)
图1 系统功能模块图
2.进行相应的功能模块设计,包括:
1)串口通信设计;(学习)
2)数据模块设计;
3)系统主窗体设计;
4)检测数据分析设计;
5)检测结果查询设计;
6)报表打印设计;(选做)
7) 安全管理设计。(选做)
3.设计并绘制各个模块与函数的软件流程图,流程图要模块化并具有可读性(根据流程图知道程序功能实现过程);编制模块化源程序;
4.编写并调试完整的程序代码 (所有自定义的单元文件名、控件名、函数名、变量名不能与示例程序同名);
5. 按学校课程设计说明书撰写规范提交一份课程设计说明书(6000字左右),设计说明书应详细说明设计思路、工作流程和软件设计与实现界面。
时间安排:
序 号
内 容
所 用 时 间
1
布置课程设计任务,查阅资料,总体方案设计
1天
2
设计软件流程图
1天
3
数据库设计
1天
4
软件编写
4天
5
撰写设计说明书
2天
6
答辩
1天
合 计
10天
指导教师签名: 年 月 日
系主任(或责任教师)签名: 年 月 日
目录
1. 绪论 4
2. 整体模块设计 4
3. 代码管理模块 5
3.1类型代码管理 5
3.2功率代码管理 5
4. 检测模块 6
5. 4.1开始检测 6
4.2停止检测 8
5.查询模块 9
5.1结果查询 9
5.2工位查询 19
6.数据表浏览模块 20
7.数据修改模块 22
8.打印报表模块 24
9.帮助模块 25
10.总结与体会 27
11.参考文献 28
1.绪论
自工业革命以来,人类已经越来越意识到机器性工作的可代替性是多么的重要。也正是由于这一点,自动化制造业得到了飞速的发展,到如今已经达到一个非常成熟的形态。而作为当代一名当代的中国大学生,尤其是像我们这样的与制造业有关的工科专业学生,在这样的时代大潮中自然不能落于人后。在自身专业知识学习过程中要全力以赴,抓住任何机会充实自己。
而恰好学校安排了测控系统软件设计这一课程让我们学习和锻炼,更要珍惜这样的机会。主题是制作一个质量检测软件,利用日光灯试验台来检测点亮日光灯的整流器或逆变器是否合格,并且通过多次测量灯管两端的电压和电流,再通过分析,来验证整流器或逆变器工作是否正常。单个整流器或逆变器有不同功率之分,也有可以同时点亮日光灯个数多少之分。检测一个整流器或逆变器,下位机大概会产生30组左右的电压和电流数据。
总结之,本实训的目标是设计一个产品质量监测系统,保存日光灯试验台下位机产生的数据信息,并时行产品合格检查、产品质量查询、分类统计和报表打印操作,以期使产品的质量管理工作系统化、规范化、自动化,从而体现自动化制造业带来的高效率和收益。
产品质量监测系统
安全管理模块
代码管理模块
检测模块
查询模块
打印预览模块
密码与权限管理
退出系统
类型代码
功率代码
开始检测
停止检测
结果查询
工位查询
数据表浏览模块
数据修改模块
2.整体模块设计
图1 程序总体设计结构图
3. 代码管理模块
3.1类型代码管理
(1)程序代码
void __fastcall TF_Main::M_TypeClick(TObject *Sender)
{
//类型代码编辑
F_Assist->ADOT_Count->First();//设定记录号计数数据表当前活动记录是第一条记录
F_Assist->ADOT_Count->MoveBy(2);//下移两条记录至计数表中的仪器类型
F_Assist->DBLookupListBox1->ListField="";//先赋空值以免系统抛出异常
F_Assist->DBLookupListBox1->KeyField="";//先赋空值以免系统抛出异常
F_Assist->DBLookupListBox1->ListSource=DataModule1->DS_Type;//赋仪器类型表
F_Assist->DBLookupListBox1->KeyField="Type_ID";//赋类型记录号字段
F_Assist->DBLookupListBox1->ListField="Type_Name";//赋类型名称字段
F_Assist->Label2->Caption="仪器类型代码表";
F_Assist->ShowModal(); //打开辅助资料窗体
}
(2)运行结果
图2 仪器类型代码界面
3.2功率代码管理
(1)程序代码
void __fastcall Ttcw::M_PowerClick(TObject *Sender)
{ x=2;
F_Assist->ADOT_Count->TableName="Industry_Power";//功率代码编辑
F_Assist->ADOT_Count->Open();
F_Assist->ADOT_Count->Edit();
DataModule1->AT_Power->Open();
DataModule1->AT_Power->Edit();
F_Assist->ADOT_Count->First();//设定记录号计数数据表当前活动记录是第一条记录
F_Assist->ADOT_Count->MoveBy(2);//下移两条记录至计数表中的仪器功率
F_Assist->DBLookupListBox1->ListField="";//先赋空值以免系统抛出异常
F_Assist->DBLookupListBox1->KeyField="";//先赋空值以免系统抛出异常
F_Assist->DBLookupListBox1->ListSource=DataModule1->DS_Power;//赋仪器功率代码表
F_Assist->DBLookupListBox1->KeyField="Power_ID";//赋功率记录号字段
F_Assist->DBLookupListBox1->ListField="Power_Name";//赋功率名称字段
F_Assist->Label2->Caption="仪器功率代码表";
F_Assist->Show(); //打开辅助资料窗体
}
(2)运行结果
图3 仪器功率代码界面
4.检测模块
4.1开始检测
(1)流程图
图4 流程图
(2)程序代码
void __fastcall Ttcw:M_StartClick(TObject *Sender)
{
//打开串口,开启JudgeTimer定时器定时测控串口
MainMenu->Items->Items[2]->Enabled=false;//使开始检测菜单项非能
MainMenu->Items->Items[3]->Enabled=True;//停止检测菜单项使能
if(Com1->PortOpen==True)//如果串口已打开,则关闭之
Com1->PortOpen=false;
Com1->PortOpen=True; //打开串口
Com1->InBufferCount=0;//消除输入缓冲区的内容
Com1->OutBufferCount=0;//消除输出缓冲区的内容
if(!Com1->PortOpen) //判断串口初始化是否失败并显示
ShowMessage("串口初始化失败");
JudgeTimer->Enabled=true; //开启串口监听定时器
RE_Mess->Lines->Add("串口初始化成功,正在监听");//在RichEdit控件显示串口状态
RE_Mess->Lines->Add("用户可以开始检测数据");
}
(3)运行结果
图5 开始检测后界面
4.2停止检测
(1)程序代码
void __fastcall Ttcw::M_PauseClick(TObject *Sender)
{
//关闭串口,关闭JudgeTimer定时器定时测控串口
MainMenu->Items->Items[2]->Enabled=True;//开始检测菜单项使能
MainMenu->Items->Items[3]->Enabled=false;//停止检测菜单项非能
JudgeTimer->Enabled=false; //关闭串口监听定时器
Com1->PortOpen=false; //关闭串口
RE_Mess->Lines->Add("串口已关闭,与下位机通信中断");//在RichEdit控件显示串口状态
}
(2)运行结果
图6 停止检测后界面
5.查询模块
5.1结果查询
(1)程序代码以及对应程序结果
#include <vcl.h>
#pragma hdrstop
#include "Query.h"
#include "DM.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TF_Query *F_Query;
//---------------------------------------------------------------------------
__fastcall TF_Query::TF_Query(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TF_Query::CB_TimeClick(TObject *Sender)
{ //判断时间查询复选框是否选中,以决定各单选按钮是否能使用
if(CB_Time->Checked)
{ //若时间框选中,则各单选按钮被激活
RadioButton1->Enabled= true ; //
RadioButton2->Enabled= true ; //
RadioButton3->Enabled= true ; //
}
else
{//否则,各单选按钮处于失效状态
RadioButton1->Enabled= false ; //
RadioButton2->Enabled= false ; //
RadioButton3->Enabled= false; //
}
}
//---------------------------------------------------------------------------
void __fastcall TF_Query::CB_CodeClick(TObject *Sender)
{//判断编号查询复选框是否被选中
if(CB_Code->Checked)
{
M_Code->Enabled=true ;//memo控件被激活
Label2->Enabled=true;//标签控件被激活
}
else
{ //memo与标签控件失效
M_Code->Enabled=false;
Label2->Enabled=false;
}
}
//---------------------------------------------------------------------------
图7 时间设定查询界面
图8时间设定查询结果
//---------------------------------------------------------------------------
void __fastcall TF_Query::CB_TypeClick(TObject *Sender)
{ //判断类型查询是否选中
if(CB_Type->Checked)
E_Type->Enabled=true;
else
E_Type->Enabled=false;
}
图9按类型查询界面
图10类型查询结果
void __fastcall TF_Query::CB_PowerClick(TObject *Sender)
{
//判断功率查询是否选中
if(CB_Power->Checked)
E_Power->Enabled=true;
else
E_Power->Enabled=false;
}//---------------------------------------------------------------------------
图11按功率查询界面
图12功率查询结果
void __fastcall TF_Query::CB_NumClick(TObject *Sender)
{
//判断管数查询是否选中
if(CB_Num->Checked)
{
E_Num->Enabled=true;
UpDown->Enabled=true;
}
else
{
E_Num->Enabled=false;
UpDown->Enabled=false;
}}
图13 按管数查询界面
图14 按管数查询结果
void __fastcall TF_Query::B_CancelClick(TObject *Sender)
{
DataModule1->AQ_Record->Close();//关闭检测记录数据源
DataModule1->AQ_Record->SQL->Clear();//清除SQL语句
DataModule1->AQ_Record->SQL->Add("SELECT * FROM Industry_Record");
DataModule1->AQ_Data->Close();//关闭检测数据数据源
DataModule1->AQ_Data->SQL->Clear();//清除SQL语句
DataModule1->AQ_Data->SQL->Add("SELECT * FROM Industry_Record,Industry_Data");
DataModule1->AQ_Record->Open();//执行SQL语句,打开检测记录表
DataModule1->AQ_Data->Open();//执行SQL语句,打开检测数据表
F_Query->Close();//关闭检测数据查看窗口
}
//---------------------------------------------------------------------------
void __fastcall TF_Query::B_QueryClick(TObject *Sender)
{//查询按钮单击事件
if(!CB_Time->Checked&&!CB_Type->Checked&&!CB_Power->Checked
&&!CB_Num->Checked&&!CB_Code->Checked) //若没有查询条件
{
Application->MessageBoxA("没有查询条件,请选择或输入","查询出错",MB_OKCANCEL);
return;
}
String str1="Industry_Record.Record_Type='" + E_Type->Text + "'",
str2="Record_Type='" + E_Type->Text + "'",
str3="Industry_Record.Record_Power='" + E_Power->Text + "'",
str4="Record_Power='" + E_Power->Text + "'";
DataModule1->AQ_Record->Close();//关闭检测记录数据源
DataModule1->AQ_Record->SQL->Clear();//清除SQL语句
DataModule1->AQ_Record->SQL->Add("SELECT * FROM Industry_Record WHERE ");
//增加一条SQL语句,从检测记录表中提取数据记录
DataModule1->AQ_Data->Close();//关闭检测数据数据源
DataModule1->AQ_Data->SQL->Clear();//清除SQL语句
DataModule1->AQ_Data->SQL->Add("SELECT * FROM Industry_Record,Industry_Data WHERE Industry_Record.Record_SNumber=Industry_Data.Data_SNumber AND ");
//增加一条SQL语句,从检测记录表、检测数据表中提取数据记录
//时间查询
if(CB_Time->Checked)
{
DataModule1->AQ_Record->SQL->Add(" Record_Date BETWEEN :timel1 AND :timel2");
DataModule1->AQ_Data->SQL->Add(" Record_Date BETWEEN :timer1 AND :timer2");
//timel1、2,timer1、2是在SQL语句中自定义的变量
if(RadioButton1->Checked) //当天查询
{
DataModule1->AQ_Record->Parameters->ParamByName("timel1")->Value=
StrToDateTime(DateToStr(Now())+" 00:00:00");
DataModule1->AQ_Record->Parameters->ParamByName("timel2")->Value=
StrToDateTime(DateToStr(Now())+" 23:59:59");
DataModule1->AQ_Data->Parameters->ParamByName("timer1")->Value=
StrToDateTime(DateToStr(Now())+" 00:00:00");
DataModule1->AQ_Data->Parameters->ParamByName("timer2")->Value=
StrToDateTime(DateToStr(Now())+" 23:59:59");
}
if(RadioButton2->Checked) //本周查询
{
TDateTime *DT=new TDateTime();
*DT=Now();
int convert[]={0,6,0,1,2,3,4,5};//国内外一周的起止不一样
TDateTime Monday=DT->operator-(convert[DT->DayOfWeek()]);
//DayofWeek()取得今天是一周内的第几天,再进行当前星期一的日期推算
DataModule1->AQ_Record->Parameters->ParamByName("timel1")->Value=
StrToDateTime(DateToStr(Monday)+" 00:00:00");
DataModule1->AQ_Record->Parameters->ParamByName("timel2")->Value=
StrToDateTime(DateToStr(Now())+" 23:59:59");
DataModule1->AQ_Data->Parameters->ParamByName("timer1")->Value=
StrToDateTime(DateToStr(Monday)+" 00:00:00");
DataModule1->AQ_Data->Parameters->ParamByName("timer2")->Value=
StrToDateTime(DateToStr(Now())+" 23:59:59");
}
if(RadioButton3->Checked) //本月查询
{
unsigned short i,j,k;
Now().DecodeDate(&i,&j,&k);//提取当前的年月日,分别存入变量i,j,k
DataModule1->AQ_Record->Parameters->ParamByName("timel1")->Value=
StrToDateTime(IntToStr(i)+'-'+IntToStr(j)+"-01 00:00:00");
DataModule1->AQ_Record->Parameters->ParamByName("timel2")->Value=
StrToDateTime(DateToStr(Now())+" 23:59:59");
DataModule1->AQ_Data->Parameters->ParamByName("timer1")->Value=
StrToDateTime(IntToStr(i)+'-'+IntToStr(j)+"-01 00:00:00");
DataModule1->AQ_Data->Parameters->ParamByName("timer2")->Value=
StrToDateTime(DateToStr(Now())+" 23:59:59");
}
}
//类型查询
if(CB_Type->Checked)
{ if(CB_Time->Checked)
{//如果前面已经添加了时间查询,则需要加AND条件同时成立运算符
DataModule1->AQ_Record->SQL->Add(" AND ");
DataModule1->AQ_Data->SQL->Add(" AND ");
}
DataModule1->AQ_Record->SQL->Add(str1);
DataModule1->AQ_Data->SQL->Add(str2);
}
//功率查询
if(CB_Power->Checked)
{ if(CB_Time->Checked||CB_Type->Checked)
{//如果前面已经添加了时间查询或类型查询,则需要加AND条件同时成立运算符
DataModule1->AQ_Record->SQL->Add(" AND ");
DataModule1->AQ_Data->SQL->Add(" AND ");
}
DataModule1->AQ_Record->SQL->Add(str3);
DataModule1->AQ_Data->SQL->Add(str4);
}
//编号查询
if(CB_Code->Checked)
{
if(M_Code->Text.IsEmpty())
{ //如果无编号
Application->MessageBoxA("请输入编号","查询出错",MB_OK);
M_Code->SetFocus();//焦点至编号输入框
return;
}
if(CB_Time->Checked||CB_Type->Checked||CB_Power->Checked)
{
//如果前面已经添加了其他查询,则需要加AND条件同时成立运算符
DataModule1->AQ_Record->SQL->Add(" AND ");
DataModule1->AQ_Data->SQL->Add(" AND ");
}
DataModule1->AQ_Record->SQL->Add("(");
DataModule1->AQ_Data->SQL->Add("("); //可能包含多个编号,需用括号括起来
for(int i=0;i<M_Code->Lines->Count;i++)
{
if(M_Code->Lines->Strings[i].IsEmpty())continue;
DataModule1->AQ_Record->SQL->Add(Format("Record_SNumber='%s%s%s'",
ARRAYOFCONST(("",M_Code->Lines->Strings[i],""))));
//利用format函数进行参数赋值
DataModule1->AQ_Data->SQL->Add(Format("Data_SNumber='%s%s%s'",
ARRAYOFCONST(("",M_Code->Lines->Strings[i],""))));
//利用format函数进行参数赋值
if(i!=M_Code->Lines->Count-1)
{
DataModule1->AQ_Record->SQL->Add(" OR ");
DataModule1->AQ_Data->SQL->Add(" OR ");
}
else
{
DataModule1->AQ_Record->SQL->Add(" )");
DataModule1->AQ_Data->SQL->Add(" ) ");
}
}
}
图15多编号查询界面
图16 多编号查询结果
//管数查询
if(CB_Num->Checked)
{
if(CB_Time->Checked||CB_Type->Checked||CB_Power->Checked||CB_Code->Checked)
{
//如果前面已经添加了其他查询,则需要加AND条件同时成立运算符
DataModule1->AQ_Record->SQL->Add(" AND ");
DataModule1->AQ_Data->SQL->Add(" AND ");
}
DataModule1->AQ_Record->SQL->Add(" Record_LNumber=:lightl1");
DataModule1->AQ_Record->Parameters->ParamByName("lightl1")->Value=E_Num->Text;
DataModule1->AQ_Data->SQL->Add(" Record_LNumber=:lightr1");
DataModule1->AQ_Data->Parameters->ParamByName("lightr1")->Value=E_Num->Text;
}
DataModule1->AQ_Record->Open();//执行SQL语句,打开检测记录表
DataModule1->AQ_Data->Open();//执行SQL语句,打开检测数据表
Close();//关闭查询窗口
DataModule1->AQ_RecordRecord_Date->DisplayFormat="yyyy-mm-dd";
//定义检测记录表中检测日期显示格式
((TDateTimeField *)(DataModule1->AQ_Data->FieldByName("Record_Date")))->DisplayFormat="yyyy-mm-dd";
//定义检测数据表中检测日期显示格式
}
(2) 运行结果分析:经过实际操作发现各个功能均正常,并且各函数对应的功能划分比较清晰。
5.2工位查询
(1)程序代码
void __fastcall TF_Main::M_LabNumberClick(TObject *Sender)
{ //对指定工位的检测装置进行数据获取
F_LabNo->ShowModal();//打开工位号输入窗口?
if(F_LabNo->ModalResult==mrOk)
{ //如果窗体操作结果是用户确定按钮
//通过串口发送用户所要获取的指定工位的请求数据
char buff[4];
buff[0]=0x02;
buff[1]=0x70+F_LabNo->E_Num->Text.ToInt();
buff[2]=0x03;
buff[3]=0x31;
SendData(StrPas(buff));
//在状态栏显示
RE_Mess->Lines->Add(F_LabNo->E_Num->Text+"号工位查询请求已发送");
}
}
(2)运行结果
图17 程序工位查询界面
图18 工位号查询结果
6.数据表浏览模块
(1)程序代码
#include <vcl.h>
#pragma hdrstop
#include "Data.h"
#include
展开阅读全文