下面介绍Unit1主界面的实现。
1.Timer2
Timer2是用来显示系统时间用的时钟,每30秒刷新一次,因此系统时间只能显示到分钟了……
procedure TForm1.Timer2Timer(Sender: TObject);{---------------------显示系统时间的 定时中断2} var //定时30s Time:TDateTime;//系统时间 begin Time:=now; if copy(TimetoStr(time),5,1)=':' then TeStatusBar1.Panels[4].Text := Datetostr(time)+' '+leftstr(TimeToStr(Time),4) else TeStatusBar1.Panels[4].Text := Datetostr(time)+' '+leftstr(TimeToStr(Time),5);//在状态栏显示系统时间 end;
为了完整的取出系统时间,在delphi中要使用now函数,参考用Delphi获取当前系统时间_乌拉大喵喵-CSDN博客_delphi获取当前时间
使用DatetoStr来取出time中的日期,即年月日,使用TimeToStr取出time中的时间,即时分秒。
copy函数举例:Copy(Str,2,2)=el;//从Str字符串变量的中第2个字符开始取长度为2个字符的字符串,即一个从指定位置截取指定长度字符的函数。
举例两种时间:18:26:00和12:3:4,对于第一个时间值,直接使用leftstr(TimeToStr(Time),4);即可直接取出time的时分为18:26,但可以看到第二个时间中的“分”为个位数,要是依然使用前面的语句,那就会取出12:3:这样的显示是不行的,所以要判断time的“分”是不是为个位,即使用语句if copy(TimetoStr(time),5,1)=':' then来判断。
注:copy函数数字符串,起始计数为1,即对于时间18:26中的8是第2位。
2.Timer1
Timer1用来每5分钟刷新一次继电器状态。
procedure TForm1.Timer1Timer(Sender: TObject);{----------------------------------定时器中断1} var //定时5分钟 Time:TDateTime;//系统时间 nowDate,nowTime : string; nowMinute : integer; begin Time:=now;//只有now才正确,参考http://blog.csdn.net/yorkworlddream/article/details/17500683 nowTime := TimeToStr(Time); //5分钟自动扫描继电器状态 nowMinute := strtoint(copy(nowTime,4,2));//copy用于截取 http://blog.csdn.net/yorkworlddream/article/details/17500855 if nowMinute > lastMinute then//lastMinute全局变量 begin sysSendState := 0;//设置全局变量sysSendState为0,即发送 查询继电器状态 帧 timer3.Enabled:=true;//开定时器3,让它负责发送,发完让它自己关掉自己 lastMinute := nowMinute; end; // tememo1.Lines.Add(b0cxjdq);//对memo进行操作使用add方法 end;
Timer1只负责到时开timer3,自己不负责查询帧的发送,查询帧数据是由Timer3来发送的。
3.Timer3
Timer3用来发送继电器的查询命令帧、继电器的控制命令帧,每500ms被触发一次,每触发一次发送一个表的查询或控制命令帧。Timer3由其他定时器开启,发送完成后被自身关闭。
procedure TForm1.Timer3Timer(Sender: TObject);{------用于串口发数,每500ms触发一次 定时中断3} begin //定时500ms {0} if sysSendState =0 then//发送 查询继电器状态 帧 begin if bhindex = 9 then begin comport1.WriteStr(Hexstrtostr(b9cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b9cxjdq;//显示要发出的数据 bhIndex := 0;//表号归0,=0表示下次要发送表号0的帧数据,即从新开始了 timer3.Enabled:=false;//自己关断自己,它的开要由timer1来决定 timer1.Enabled:=true;//打开timer1 end else if bhindex = 8 then begin comport1.WriteStr(Hexstrtostr(b8cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b8cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=9表示下次要发送表号9的帧数据 end else if bhindex = 7 then begin comport1.WriteStr(Hexstrtostr(b7cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b7cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=8表示下次要发送表号8的帧数据 end else if bhindex = 6 then begin comport1.WriteStr(Hexstrtostr(b6cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b6cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=7表示下次要发送表号7的帧数据 end else if bhindex = 5 then begin comport1.WriteStr(Hexstrtostr(b5cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b5cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=6表示下次要发送表号6的帧数据 end else if bhindex = 4 then begin comport1.WriteStr(Hexstrtostr(b4cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b4cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=5表示下次要发送表号5的帧数据 end else if bhindex = 3 then begin comport1.WriteStr(Hexstrtostr(b3cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b3cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=4表示下次要发送表号4的帧数据 end else if bhindex = 2 then begin comport1.WriteStr(Hexstrtostr(b2cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b2cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=3表示下次要发送表号3的帧数据 end else if bhindex = 1 then begin comport1.WriteStr(Hexstrtostr(b1cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b1cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=2表示下次要发送表号2的帧数据 end else if bhIndex = 0 then begin comport1.WriteStr(Hexstrtostr(b0cxjdq));//调用Hexstrtostr函数 tememo1.Text:= b0cxjdq;//显示要发出的数据 bhIndex := bhIndex +1;//表号加1,=1表示下次要发送表号1的帧数据 end; end; {1} if sysSendState = 1 then//发送 开关继电器 帧 begin if gI=0 then begin if jdqRadioBtn0k.Checked = true then//00表设置为开 begin comport1.WriteStr(Hexstrtostr(b0kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b0kjdq;//显示要发出的数据 end//---------------------------------------------------------------注意else前无分号 else begin comport1.WriteStr(Hexstrtostr(b0gjdq)); tememo1.Text:= b0gjdq; end; end else if gI=1 then begin if jdqRadioBtn1k.Checked = true then//01表设置为开 begin comport1.WriteStr(Hexstrtostr(b1kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b1kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b1gjdq)); tememo1.Text:= b1gjdq; end; end else if gI=2 then begin if jdqRadioBtn2k.Checked = true then//02表设置为开 begin comport1.WriteStr(Hexstrtostr(b2kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b2kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b2gjdq)); tememo1.Text:= b2gjdq; end; end else if gI=3 then begin if jdqRadioBtn3k.Checked = true then//03表设置为开 begin comport1.WriteStr(Hexstrtostr(b3kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b3kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b3gjdq)); tememo1.Text:= b3gjdq; end; end else if gI=4 then begin if jdqRadioBtn4k.Checked = true then//04表设置为开 begin comport1.WriteStr(Hexstrtostr(b4kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b4kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b4gjdq)); tememo1.Text:= b4gjdq; end; end else if gI=5 then begin if jdqRadioBtn5k.Checked = true then//05表设置为开 begin comport1.WriteStr(Hexstrtostr(b5kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b5kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b5gjdq)); tememo1.Text:= b5gjdq; end; end else if gI=6 then begin if jdqRadioBtn6k.Checked = true then//06表设置为开 begin comport1.WriteStr(Hexstrtostr(b6kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b6kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b6gjdq)); tememo1.Text:= b6gjdq; end; end else if gI=7 then begin if jdqRadioBtn7k.Checked = true then//07表设置为开 begin comport1.WriteStr(Hexstrtostr(b7kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b7kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b7gjdq)); tememo1.Text:= b7gjdq; end; end else if gI=8 then begin if jdqRadioBtn8k.Checked = true then//08表设置为开 begin comport1.WriteStr(Hexstrtostr(b8kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b8kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b8gjdq)); tememo1.Text:= b8gjdq; end; end else if gI=9 then begin if jdqRadioBtn9k.Checked = true then//09表设置为开 begin comport1.WriteStr(Hexstrtostr(b9kjdq)); //调用Hexstrtostr函数 tememo1.Text:= b9kjdq;//显示要发出的数据 end else begin comport1.WriteStr(Hexstrtostr(b9gjdq)); tememo1.Text:= b9gjdq; end; timer1.Enabled:=true;//发送完成,打开timer1 timer3.Enabled:=false;//发送完成,timer3关闭自己 gI := 0; sysSendState :=0;//初始的系统发送状态归为0,即 查询继电器 帧 end; gI := gI + 1; end; end;
由于查询继电器状态和控制继电器是由不同的控件触发的,所以为了区分是查询还是控制,使用了一个全局变量sysSendState来进行判断,当sysSendState=0时代表查询,=1时为控制。
gI的左右就是Timer3被触发一次,自己加1,可以保证每次发送的只是一个表的数据,因为我在刚开始写这段程序的时候怕上位机发的太快,下面下位机抢占485总线,使发送与应答冲突,就想着隔500ms发一个帧,由于开始用的不熟练,只想到了这个办法,现在看,只要编写一个delay函数即可。函数如下:
procedure Delay(dwMilliseconds:DWORD);//Longint var iStart,iStop:DWORD; begin iStart := GetTickCount; repeat iStop := GetTickCount; Application.ProcessMessages; until (iStop - iStart) >= dwMilliseconds; end;
在Timer3中发送的帧代码使用的全局字符串变量,直接将帧写好,发的时候直接发字符串名即可,当然,这个方法也很浪费代码,没办法,最先写的Form1的程序,才入门也只能这样了,帧的字符串变量如下:
b0gjdq : string[44]= '68 00 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b0kjdq : string[44]= '68 00 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b0cxjdq : string[41]= '68 00 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b0cxdn : string[41]= '68 00 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b0cxgl : string[41]= '68 00 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表1 b1gjdq : string[44]= '68 01 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b1kjdq : string[44]= '68 01 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b1cxjdq : string[41]= '68 01 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b1cxdn : string[41]= '68 01 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b1cxgl : string[41]= '68 01 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表2 b2gjdq : string[44]= '68 02 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b2kjdq : string[44]= '68 02 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b2cxjdq : string[41]= '68 02 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b2cxdn : string[41]= '68 02 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b2cxgl : string[41]= '68 02 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表3 b3gjdq : string[44]= '68 03 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b3kjdq : string[44]= '68 03 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b3cxjdq : string[41]= '68 03 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b3cxdn : string[41]= '68 03 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b3cxgl : string[41]= '68 03 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表4 b4gjdq : string[44]= '68 04 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b4kjdq : string[44]= '68 04 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b4cxjdq : string[41]= '68 04 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b4cxdn : string[41]= '68 04 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b4cxgl : string[41]= '68 04 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表5 b5gjdq : string[44]= '68 05 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b5kjdq : string[44]= '68 05 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b5cxjdq : string[41]= '68 05 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b5cxdn : string[41]= '68 05 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b5cxgl : string[41]= '68 05 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表6 b6gjdq : string[44]= '68 06 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b6kjdq : string[44]= '68 06 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b6cxjdq : string[41]= '68 06 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b6cxdn : string[41]= '68 06 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b6cxgl : string[41]= '68 06 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表7 b7gjdq : string[44]= '68 07 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b7kjdq : string[44]= '68 07 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b7cxjdq : string[41]= '68 07 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b7cxdn : string[41]= '68 07 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b7cxgl : string[41]= '68 07 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表8 b8gjdq : string[44]= '68 08 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b8kjdq : string[44]= '68 08 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b8cxjdq : string[41]= '68 08 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b8cxdn : string[41]= '68 08 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b8cxgl : string[41]= '68 08 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率 //表9 b9gjdq : string[44]= '68 09 30 00 00 00 00 68 04 03 e6 83 00 13 16';//关继电器 b9kjdq : string[44]= '68 09 30 00 00 00 00 68 04 03 e6 83 01 13 16';//开继电器 b9cxjdq : string[41]= '68 09 30 00 00 00 00 68 01 02 e7 83 13 16'; //查询继电器 b9cxdn : string[41]= '68 09 30 00 00 00 00 68 01 02 44 c3 13 16'; //查询电能 b9cxgl : string[41]= '68 09 30 00 00 00 00 68 01 02 64 e9 13 16'; //查询功率
由于帧字符串是用字符串来表示十六进制,即“68”表示0x68,这样直接下传是不对的,所以要使用到HexStrToStr函数,将“68”真正的转为0x68
HexStrToStr:
{16进制字符串转换成字符串} function HexStrToStr(const S:string):string;//16进制字符串转换成字符串 var t:Integer; ts:string; M,Code:Integer; begin t:=1; Result:=''; while t<=Length(S) do begin while not (S[t] in ['0'..'9','A'..'F','a'..'f']) do inc(t); if (t+1>Length(S))or(not (S[t+1] in ['0'..'9','A'..'F','a'..'f'])) then ts:='$'+S[t] else ts:='$'+S[t]+S[t+1]; Val(ts,M,Code); if Code=0 then Result:=Result+Chr(M); inc(t,2); end; end;
4.Timer4
Timer4用于记录存储用户的电量到数据库中。
4.1若数据库中没有本日的数据,那么就要在每个表的数据表Table中新建一行当日的数据。
ibquery1.SQL.Clear; ibquery1.SQL.Add('select count(*) from BH0 where U_year=:A and U_month=:B and U_day=:D'); ibquery1.Params.ParamByName('A').Value := pNowYear; ibquery1.Params.ParamByName('B').Value := pNowMonth; ibquery1.Params.ParamByName('D').Value := pNowDay; ibquery1.Open; tempInt1 := ibquery1.FieldByName('count').Asinteger;//查询看是否有用现在的年月做的行 if tempInt1 = 0 then //如果等于0 说明没有现在年月日的行 begin for i := 0 to 9 do begin tempStr1 := inttoStr(i);//i代表表号 ibquery1.SQL.Clear; ibquery1.SQL.Add('Insert into BH'+tempStr1+' Values(:B,:C,:D,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'); ibquery1.Params.ParamByName('B').Value := pNowYear; ibquery1.Params.ParamByName('C').Value := pNowMonth; ibquery1.Params.ParamByName('D').Value := pNowDay; ibquery1.ExecSQL; end;//部分代码,不全
其中,为SQL语句输入变量的方法如上代码段
ibquery1.SQL.Add('Insert into BH'+tempStr1+' Values(:B,:C,:D,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'); ibquery1.Params.ParamByName('B').Value := pNowYear; ibquery1.Params.ParamByName('C').Value := pNowMonth; ibquery1.Params.ParamByName('D').Value := pNowDay; ibquery1.ExecSQL;
语句ibquery1.Params.ParamByName('B').Value :=?;中的?只需与数据表中的类型一致即可,不要求必须是字符型。
举例来看:
Form1.IBQuery1.sql.Add('Insert into loadmatrix(loadIndex,loadname,phase,har1,har3,har5,har7,har9)'); Form1.IBQuery1.sql.Add('Values(:A,:B,:C,:D,:E,:F,:G,:H)'); Form1.IBQuery1.Params.ParamByName('A').Value:=(maxIndex+1) ;//integer型 Form1.IBQuery1.Params.ParamByName('B').Value:=editname.Text ;//char型 Form1.IBQuery1.Params.ParamByName('C').Value:=strtofloat(editphase.Text) ;//float型
从这段代码中不仅可以看出ibquery1.Params.ParamByName('B').Value :=?;语句的使用,也可以发现,使用IBQuery进行SQL语句传输时,还可以拆成两句来书写。
5.“开始”
工具栏中的“开始”按钮,用来开启串口,并且使能那些与串口有关的控件。
//========================================================================================== procedure TForm1.toolButtonkaishiClick(Sender: TObject);{-----------------工具栏 开始 button} begin comport1.Port := form4.ckCombo.Items[form4.ckCombo.ItemIndex];//由unit4选择串口号 comport1.BaudRate := br9600; ComPort1.Open; TeStatusBar1.Panels[1].Text := '运行';//在状态栏显示运行状态 timer3.Enabled:=true; timer4.enabled:=true; jdqButton.Enabled:=true; glckButton.Enabled:=true; glckjdqButton.Enabled:=true; //timer1.Enabled:=true; //上面这句在timer3中实现,即首次点击“开始”,先发送一次数据,由timer3打开timer1 end;
因为软件串口的COM口和波特率是在form4(软件设置)中设置的,因此串口控件Comport的port号要从form4中获取,这里我们看到了如何去下拉菜单的参数的方法。
从整体看,语句为 Items[ ItemIndex ];
6.串口中断
参考:Comport4 CPort for delphi2010串口应用程序_乌拉大喵喵-CSDN博客
即自己编写一个过程,将这个过程与ComPort1.ComPRxChar进行连接
之后在这个过程中对串口接收到的数进行处理即可。
这里需要注意一下几点:
1.若串口接收的是16进制数据,那么使用ComPort1.ReadStr(Str, Count);语句将comport自动计数的count个数据存入了str中,comport的存储方法是转每一个16进制数为一个字符,即收到十六进制68,存入str中的为字符h,而不是字符串68。因此在后面使用copy的时候,要copy出68,只要copy(?,1);即可。
举例,按照645规约的帧结构,取出表号的代码为:
ComPort1.ReadStr(Str, Count); bhStr := copy(Str,2,1);//获取表号。68算一个数,从第2个计算一个数,即为表号00或01
2.对于功率等传过来的4个字节16进制数,要转为float型,要使用一下函数:
//64 e9 查功率帧返回 if ansiSameText('64 e9',StrtoHexStr(orderStr)) then begin dataStr := copy(str,13,4);//取得该表数据字段,即功率 dataStr := spaceprocess(StrToHexStr(dataStr));//先将16进制转成字符串,之后去空格 teedit1.Text := floattostr(HextoFloat(dataStr));//将十六进制字符转成float,再成字符型进行显示 end;
先取出4字节的十六进制数据,之后将字符串转成十六进制字符串,因为就像上面说的,得到的十六进制68存的是h,并不是字符串68,因此要转换一下,使用StrToHexStr,
之后去除字符串中的空格,比如C1 48 00 00字符串即被转为C1480000,
之后再使用十六进制字符串转float函数,HexToFloat,将十六进制转为浮点型,
为了显示用,可以再将float转为字符串。
用流程表示上述转换过程:
收到的16进制数据---comport1.readStr---->
ascii对应的字符串----StrToHexStr----->
“68 00”这样的字符串---spaceprocess---->
"6800"这样的字符串----HexToFloat---->
float型数据------floatToStr------->
将float转成字符串用于显示
粘上各个函数的代码:
StrToHexStr:
{字符串转换成16进制字符串} function StrToHexStr(const S:string):string;//字符串转换成16进制字符串 var I:Integer; begin for I:=1 to Length(S) do begin if I=1 then Result:=IntToHex(Ord(S[1]),2) else Result:=Result+' '+IntToHex(Ord(S[I]),2); end; end;
spaceprocess:
{去字符串中的空格} function SpaceProcess(S: String): String; var i : Integer; begin Result := ''; for i := 1 to Length(S) do begin if S[i] <> ' ' then begin Result := Result + S[i]; end; end; end;
HexToFloat
{二进制 to 十进制} function BintoInt(Value: String): LongInt; var i,Size: Integer; begin Result:=0; Size:=Length(Value); for i:=Size downto 1 do begin if Copy(Value,i,1)='1' then Result:=Result+(1 shl (Size-i)); end; end; function floatBintoInt(Value: String): real; var i,Size: Integer; begin Result:=0; Size:=Length(Value); for i:=Size downto 1 do begin if Copy(Value,i,1)='1' then Result:=Result+1/(1 shl i); end; end; {十六进制 to 二进制} function HextoBinary(Hex:string):string; const BOX: array [0..15] of string = ('0000','0001','0010','0011', '0100','0101','0110','0111', '1000','1001','1010','1011', '1100','1101','1110','1111'); var i:integer; begin for i:=Length(Hex) downto 1 do Result:=BOX[StrToInt('$'+Hex[i])]+Result; end; {十六进制 to 十进制 浮点型} function HextoFloat(s:string):real; var b,temp:string; e:integer; f:real; begin b:=HextoBinary(s); temp := copy(b,2,8); e:=BintoInt(temp)-127; temp := copy(b,10,23); f := 1+floatBintoInt(temp); if(copy(b,1,1)='0')then result := power(2,e)*f //------------------------------------------------要引用单元math else result :=-power(2,e)*f; end;
7.数据库连接
参考:InterBase7.0数据库的建立且与Delphi2010的连接_乌拉大喵喵-CSDN博客
Char显示数据参考:使用TDBChart显示InterBase数据库的一行数据_乌拉大喵喵-CSDN博客
还是笨方法:
//========================================================================================== procedure TForm1.dlcxButtonClick(Sender: TObject);{-----------------电量曲线查询 确定 button} var i : integer; adayhour : array [1..24] of real;//设一个数组,用来放24小时的数据 Time:TDateTime;//系统时间 nowDate,nowYear,nowMonth,nowDay : string;//用来存放当前的系统时间 begin Time := now;//取当前时间 nowDate := DateToStr(Time); nowYear:=leftStr(nowDate,4);//取年 nowMonth:=copy(nowDate,6,2);//取月 nowDay:=copy(nowDate,9,2);//取日 // tememo2.Text := nowDate; // tememo1.Text := nowYear+nowMonth+nowDay; IBdatabase1.Connected:=true; IBquery1.Close; ibquery1.SQL.Clear; case dlcxCombo.ItemIndex of 0:ibquery1.SQL.Add('select * from BH0 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear);//查询当年月日的数据 1:ibquery1.SQL.Add('select * from BH1 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 2:ibquery1.SQL.Add('select * from BH2 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 3:ibquery1.SQL.Add('select * from BH3 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 4:ibquery1.SQL.Add('select * from BH4 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 5:ibquery1.SQL.Add('select * from BH5 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 6:ibquery1.SQL.Add('select * from BH6 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 7:ibquery1.SQL.Add('select * from BH7 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 8:ibquery1.SQL.Add('select * from BH8 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); 9:ibquery1.SQL.Add('select * from BH9 where u_day='+ nowDay + 'and u_month=' + nowMonth + 'and u_year=' + nowYear); end; ibquery1.Open; //这时值已经放到IBQuery中了 adayhour[1] := ibquery1.FieldByName('H1').AsFloat ;//按字段名取出数据,分别放到数组中 adayhour[2] := ibquery1.FieldByName('H2').AsFloat ;//因为数据类型不一样,所以要加.asfloat adayhour[3] := ibquery1.FieldByName('H3').AsFloat ; adayhour[4] := ibquery1.FieldByName('H4').AsFloat ; adayhour[5] := ibquery1.FieldByName('H5').AsFloat ; adayhour[6] := ibquery1.FieldByName('H6').AsFloat ; adayhour[7] := ibquery1.FieldByName('H7').AsFloat ; adayhour[8] := ibquery1.FieldByName('H8').AsFloat ; adayhour[9] := ibquery1.FieldByName('H9').AsFloat ; adayhour[10] := ibquery1.FieldByName('H10').AsFloat ; adayhour[11] := ibquery1.FieldByName('H11').AsFloat ; adayhour[12] := ibquery1.FieldByName('H12').AsFloat ; adayhour[13] := ibquery1.FieldByName('H13').AsFloat ; adayhour[14] := ibquery1.FieldByName('H14').AsFloat ; adayhour[15] := ibquery1.FieldByName('H15').AsFloat ; adayhour[16] := ibquery1.FieldByName('H16').AsFloat ; adayhour[17] := ibquery1.FieldByName('H17').AsFloat ; adayhour[18] := ibquery1.FieldByName('H18').AsFloat ; adayhour[19] := ibquery1.FieldByName('H19').AsFloat ; adayhour[20] := ibquery1.FieldByName('H20').AsFloat ; adayhour[21] := ibquery1.FieldByName('H21').AsFloat ; adayhour[22] := ibquery1.FieldByName('H22').AsFloat ; adayhour[23] := ibquery1.FieldByName('H23').AsFloat ; adayhour[24] := ibquery1.FieldByName('H24').AsFloat ; series1.Clear;//要先清空series,要不他会总add with series1 do begin for i := 1 to 24 do add(adayhour[i]); end; end;
取出数据库返回的值使用语句 ibquery1.FieldByName('?'),要是返回的是 float 则加入 .AsFloat 即可。
8.IOComp工控指示灯
这个指示灯的关闭状态和激发状态是由
和来控制的
使用语句
jdqled0.Active:=ansiSameText('01',strtohexstr(dataStr));//若数据字段为01则说明jdq开
就可以开关指示灯,函数ansiSameText是字符串比较函数,返回值为true或者false。