原版程序(死机版)
Private Sub Timer1_Timer()
Dim a
Dim CheckValue As Integer
Timer1.Enabled = False '关闭定时器
'**********************先检测通信是否正常
'处理上下位机第一次通信就失败的情况
If (FirstReceive = True) Then '表明上下位机第一次通信,此时Rbyte()中为空
FirstReceive = False
Dim i As Integer
'因为现在单机1号,所以可以这么写,并联运行则不能如此了!!!
For ResetNum = 0 To 2
For i = 0 To 10
SendData1
Delay (0.015)
'将下位机发送来的数据收到Rbyte中,因为现在单机1号,所以可以这么写,并联运行则不能如此了!!!
ReceiveData1
If (Rlength = 26) Then
i = 0
Exit For
End If
Next i
If (i = 0) Then '说明接收到正确数据了
ResetNum = 0
Exit For
End If
ResetLowerMachine (1)
Next ResetNum
If (ResetNum <> 0) Then '说明复位3次下位机都没有用!!!
Timer4.Enabled = False
MsgBox "下位机没有采到数据或通信模块出错!!"
' App.End
End If
End If
'******************************
'指示下位机发送数据
ComServer (1)
Current_L_Level = Load_L_Level(1, 1000) '每次都刷新开关档位
If Current_L_Level = 16 Then
MsgBox "有载开关异常,请检查" '提示框的出现不影响Timer的运行,即,即使出来了提示框,照样进定时器中断!!!!!
App.End
End If
init_level_1.Caption = Current_L_Level '粗调档位
now_middle_voltage_1.Caption = Round(MidV_Amplitude1(0)) '中性点电压
Real_C_Level = Load_C_Level(1, 1000) '真实电容级数'
If (LostSignal) Then 'receivedata1中的标志
System_status_1.Caption = "信号输入不正确" '这个优先级最高!!放在最前!!
ElseIf (Ground_Status) Then '接地调节状态中
GroundServer
ElseIf (Recalculation_Status) Then '重新计算档位中
ReCalculationLevel
ElseIf (Change_L_Flag <> 0) Then '在投档调节状态中
'在改变档位的过程中,有载开关要过很长的时间才能够调到下一档,这段时间不能死等,要判接地并动作
'如果此间判到接地,那么马上运行GroundSever,GroundSever中置Ground_Status=true,直至接地解除,
'否则会一直进入GroundSever,此时Change_L_Flag保持原来的值,接地解除后继续进入(Change_L_Flag <> 0)
'的分支,接地处理就像51单片机中的中断一样,先中止当前运行的程序去处理中断,中断处理完毕后继续从断点处
'往下运行
'****************************
If (CheckMiddleVoltageStatus = 1) Then
GroundServer
End If
'****************************
Current_L_Level = Load_L_Level(1, 1000)
If Current_L_Level = 16 Then
MsgBox "有载开关异常,请检查"
App.End
End If
If (Current_L_Level > Next_L_Level) Then '要下调
a = Output_L_Level(1, 2)
ElseIf (Current_L_Level < Next_L_Level) Then '要上调
a = Output_L_Level(1, 1)
Else '已经到达下一档,重算最优档位
If (UpStatus) Then
UpStatus = False
a = Send_Current_Status(1, 0, 0, 0) '调节完毕后通知主控台档位上调1档了
End If
If (DownStatus) Then
DownStatus = False
a = Send_Current_Status(0, 1, 0, 0) '调节完毕后通知主控台档位下调1档了
End If
init_level_1.Caption = Current_L_Level '刷新电感档位显示
Delay (0.1) '延时等待电感变化稳定下来
'**************防止在两个档位之间来回调个不停*******************************
If (SwitchFlag = False) Then '没有发生来回调个不停!!
ReCalculationLevel '重新计算最优档位
Else '出现了来回调个不停的情况
SwitchFlag = False
Change_L_Flag = 0 '不需调节
Previous_L_Level = Current_L_Level
'选择全投或全切方式
If (Optimum_C_Level < 8) Then '全切
a = Output_C_Level(1, QUANTOU)
QuanQieTou_Status = False
Else '全投
a = Output_C_Level(1, QUANQIE)
QuanQieTou_Status = True
'以全投时的电压为重计算的标准
End If
Delay (0.1) '投切之后延时5周波,保证稳定!!!!!!
'问下位机要数据!!
ComServer (1)
MidV_Amplitude1(1) = MidV_Amplitude1(0)
MidV_Phase1(1) = MidV_Phase1(0) 'Vca触发捕获的时候用到这个,因为此时中性点相位很大!!!!!
End If
'***********************************************************
End If
Else '一般状态下,开机启动首先进入该函数体
CheckValue = CheckMiddleVoltageStatus
Select Case (CheckValue) '检测中性点电压是否异常
Case 0: '稳定运行
ExceedNum = 0 '中性点超界时给主控台发信息的次数清0
SevereExceedNum = 0 '中性点严重超界时给主控台发信息的次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
HighVQie = False
HighVTou = False
System_status_1.Caption = "正常运行"
If (KaiJiStatus) Then
KaiJiStatus = False
Print_Page (1) '开机打印,每次开机只打印1次!!!
End If
Case 1: '发生接地
ExceedNum = 0 '中性点超界次数清0
SevereExceedNum = 0 '中性点严重超界次数清0
HighVQie = False
HighVTou = False
System_status_1.Caption = "发生接地"
GroundServer
Case 2: '中性点电压>15%相电压,发生超界,往主控制台送状态
SevereExceedNum = 0 '中性点严重超界次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
System_status_1.Caption = "中性点电压超界"
If (ExceedNum = 0) Then '只往主控台发送1次!!!!!!
ExceedNum = 1
a = Send_Current_Status(0, 0, 1, 0)
End If
HighVoltageServer
Case 3: '需重新计算档位
ExceedNum = 0 '中性点超界次数清0
SevereExceedNum = 0 '中性点严重超界次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
HighVQie = False
HighVTou = False
If (Change_L_Flag = 0) Then ReCalculationLevel
Case 4: '中性点电压>35%相电压但没有线路发生接地,发生严重超界,往主控制台送状态
ExceedNum = 0 '中性点超界次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
HighVQie = False
HighVTou = False
System_status_1.Caption = "中性点电压严重超界"
If (SevereExceedNum = 0) Then '只往主控台发送1次!!!
SevereExceedNum = 1
a = Send_Current_Status(0, 0, 0, 1)
End If
End Select
End If
Timer1.Enabled = True
End Sub
Function ComServer(ByVal devicenum As Integer)
Dim MidV_Level As Integer
If (devicenum = 1) Then
SendData1
Delay (0.015) '延时10ms后收取下位机的数据
ReceiveData1 '将下位机发送来的数据收到Rbyte中
End If
If (Rbyte(1) = &H11) Then '说明数据正确!!!!
lostnum = 0
MidV_Level = Rbyte(4) '不同档位
If (MidV_Level = 0) Then
MidV_Amplitude1(0) = CDbl(Rbyte(2) + Rbyte(3) * 256) * 0.36053
ElseIf (MidV_Level = 1) Then
MidV_Amplitude1(0) = CDbl(Rbyte(2) + Rbyte(3) * 256) * 0.11493
ElseIf (MidV_Level = 2) Then
MidV_Amplitude1(0) = CDbl(Rbyte(2) + Rbyte(3) * 256) * 0.0261045
End If
'中性点电压频率
If (Rbyte(6) = 0 And Rbyte(7) = 0) Then
Rbyte(7) = &H12
Rbyte(6) = &H4F
End If
MidV_Freq1(0) = Round(234375# / CDbl(Rbyte(6) + Rbyte(7) * 256), 2)
'暂时用不到,所以先不用计算以节省时间
'中性点电流幅值(有效值),电流互感器变比:250:5,未修正!!!!
'MidC_Amplitude1(0) = CDbl(Rbyte(8) + Rbyte(9) * 256) * 1.41421 * 50 / 3830.112
'投切电容总电流幅值(有效值),电流互感器变比:750:5
'TotalCC_Amplitude1(0) = CDbl(Rbyte(10) + Rbyte(11) * 256) * 1.41421 * 150 / 5106.816
'三相线电压的幅值(有效值)和相位,10000:100,未修正!!!!约1.2左右,100/83=1.2
'Vab_Amplitude1(0) = CDbl(Rbyte(12) + Rbyte(13) * 256) * 1.41421 * 100 / 223.872
Vab_Amplitude1(0) = CDbl(Rbyte(12) + Rbyte(13) * 256) * 0.6317
Vab_Phase1(0) = CDbl(Rbyte(14) + Rbyte(15) * 256) / 100#
'Vbc_Amplitude1(0) = CDbl(Rbyte(16) + Rbyte(17) * 256) * 1.41421 * 100 / 223.872
Vbc_Amplitude1(0) = CDbl(Rbyte(16) + Rbyte(17) * 256) * 0.6317
Vbc_Phase1(0) = CDbl(Rbyte(18) + Rbyte(19) * 256) / 100#
'Vca_Amplitude1(0) = CDbl(Rbyte(20) + Rbyte(21) * 256) * 1.41421 * 100 / 223.872
Vca_Amplitude1(0) = CDbl(Rbyte(20) + Rbyte(21) * 256) * 0.6317
Vca_Phase1(0) = CDbl(Rbyte(22) + Rbyte(23) * 256) / 100#
'中性点电压相位
MidV_Phase1(0) = CDbl(Rbyte(24) + Rbyte(25) * 256) / 100#
ElseIf (Rbyte(1) = 0) Then '说明收到的数据都是零!!
lostnum = lostnum + 1
If (lostnum = 10) Then
lostnum = 0
Vab_Amplitude1(0) = CDbl(Rbyte(12) + Rbyte(13) * 256) * 0.6317
Vab_Phase1(0) = CDbl(Rbyte(14) + Rbyte(15) * 256) / 100#
Vbc_Amplitude1(0) = CDbl(Rbyte(16) + Rbyte(17) * 256) * 0.6317
Vbc_Phase1(0) = CDbl(Rbyte(18) + Rbyte(19) * 256) / 100#
Vca_Amplitude1(0) = CDbl(Rbyte(20) + Rbyte(21) * 256) * 0.6317
Vca_Phase1(0) = CDbl(Rbyte(22) + Rbyte(23) * 256) / 100#
If ((Vab_Amplitude1(0) < 4000) Or (Vbc_Amplitude1(0) < 4000) Or (Vca_Amplitude1(0) < 4000)) Then
LostSignal = True
End If
End If
End If
End Function
这个项目中的bug比较难找,这里只列出一些代码片断,其他省略。Dim a
Dim CheckValue As Integer
Timer1.Enabled = False '关闭定时器
'**********************先检测通信是否正常
'处理上下位机第一次通信就失败的情况
If (FirstReceive = True) Then '表明上下位机第一次通信,此时Rbyte()中为空
FirstReceive = False
Dim i As Integer
'因为现在单机1号,所以可以这么写,并联运行则不能如此了!!!
For ResetNum = 0 To 2
For i = 0 To 10
SendData1
Delay (0.015)
'将下位机发送来的数据收到Rbyte中,因为现在单机1号,所以可以这么写,并联运行则不能如此了!!!
ReceiveData1
If (Rlength = 26) Then
i = 0
Exit For
End If
Next i
If (i = 0) Then '说明接收到正确数据了
ResetNum = 0
Exit For
End If
ResetLowerMachine (1)
Next ResetNum
If (ResetNum <> 0) Then '说明复位3次下位机都没有用!!!
Timer4.Enabled = False
MsgBox "下位机没有采到数据或通信模块出错!!"
' App.End
End If
End If
'******************************
'指示下位机发送数据
ComServer (1)
Current_L_Level = Load_L_Level(1, 1000) '每次都刷新开关档位
If Current_L_Level = 16 Then
MsgBox "有载开关异常,请检查" '提示框的出现不影响Timer的运行,即,即使出来了提示框,照样进定时器中断!!!!!
App.End
End If
init_level_1.Caption = Current_L_Level '粗调档位
now_middle_voltage_1.Caption = Round(MidV_Amplitude1(0)) '中性点电压
Real_C_Level = Load_C_Level(1, 1000) '真实电容级数'
If (LostSignal) Then 'receivedata1中的标志
System_status_1.Caption = "信号输入不正确" '这个优先级最高!!放在最前!!
ElseIf (Ground_Status) Then '接地调节状态中
GroundServer
ElseIf (Recalculation_Status) Then '重新计算档位中
ReCalculationLevel
ElseIf (Change_L_Flag <> 0) Then '在投档调节状态中
'在改变档位的过程中,有载开关要过很长的时间才能够调到下一档,这段时间不能死等,要判接地并动作
'如果此间判到接地,那么马上运行GroundSever,GroundSever中置Ground_Status=true,直至接地解除,
'否则会一直进入GroundSever,此时Change_L_Flag保持原来的值,接地解除后继续进入(Change_L_Flag <> 0)
'的分支,接地处理就像51单片机中的中断一样,先中止当前运行的程序去处理中断,中断处理完毕后继续从断点处
'往下运行
'****************************
If (CheckMiddleVoltageStatus = 1) Then
GroundServer
End If
'****************************
Current_L_Level = Load_L_Level(1, 1000)
If Current_L_Level = 16 Then
MsgBox "有载开关异常,请检查"
App.End
End If
If (Current_L_Level > Next_L_Level) Then '要下调
a = Output_L_Level(1, 2)
ElseIf (Current_L_Level < Next_L_Level) Then '要上调
a = Output_L_Level(1, 1)
Else '已经到达下一档,重算最优档位
If (UpStatus) Then
UpStatus = False
a = Send_Current_Status(1, 0, 0, 0) '调节完毕后通知主控台档位上调1档了
End If
If (DownStatus) Then
DownStatus = False
a = Send_Current_Status(0, 1, 0, 0) '调节完毕后通知主控台档位下调1档了
End If
init_level_1.Caption = Current_L_Level '刷新电感档位显示
Delay (0.1) '延时等待电感变化稳定下来
'**************防止在两个档位之间来回调个不停*******************************
If (SwitchFlag = False) Then '没有发生来回调个不停!!
ReCalculationLevel '重新计算最优档位
Else '出现了来回调个不停的情况
SwitchFlag = False
Change_L_Flag = 0 '不需调节
Previous_L_Level = Current_L_Level
'选择全投或全切方式
If (Optimum_C_Level < 8) Then '全切
a = Output_C_Level(1, QUANTOU)
QuanQieTou_Status = False
Else '全投
a = Output_C_Level(1, QUANQIE)
QuanQieTou_Status = True
'以全投时的电压为重计算的标准
End If
Delay (0.1) '投切之后延时5周波,保证稳定!!!!!!
'问下位机要数据!!
ComServer (1)
MidV_Amplitude1(1) = MidV_Amplitude1(0)
MidV_Phase1(1) = MidV_Phase1(0) 'Vca触发捕获的时候用到这个,因为此时中性点相位很大!!!!!
End If
'***********************************************************
End If
Else '一般状态下,开机启动首先进入该函数体
CheckValue = CheckMiddleVoltageStatus
Select Case (CheckValue) '检测中性点电压是否异常
Case 0: '稳定运行
ExceedNum = 0 '中性点超界时给主控台发信息的次数清0
SevereExceedNum = 0 '中性点严重超界时给主控台发信息的次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
HighVQie = False
HighVTou = False
System_status_1.Caption = "正常运行"
If (KaiJiStatus) Then
KaiJiStatus = False
Print_Page (1) '开机打印,每次开机只打印1次!!!
End If
Case 1: '发生接地
ExceedNum = 0 '中性点超界次数清0
SevereExceedNum = 0 '中性点严重超界次数清0
HighVQie = False
HighVTou = False
System_status_1.Caption = "发生接地"
GroundServer
Case 2: '中性点电压>15%相电压,发生超界,往主控制台送状态
SevereExceedNum = 0 '中性点严重超界次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
System_status_1.Caption = "中性点电压超界"
If (ExceedNum = 0) Then '只往主控台发送1次!!!!!!
ExceedNum = 1
a = Send_Current_Status(0, 0, 1, 0)
End If
HighVoltageServer
Case 3: '需重新计算档位
ExceedNum = 0 '中性点超界次数清0
SevereExceedNum = 0 '中性点严重超界次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
HighVQie = False
HighVTou = False
If (Change_L_Flag = 0) Then ReCalculationLevel
Case 4: '中性点电压>35%相电压但没有线路发生接地,发生严重超界,往主控制台送状态
ExceedNum = 0 '中性点超界次数清0
GroundNum = 0 '接地时给主控台发送信息的次数清0
HighVQie = False
HighVTou = False
System_status_1.Caption = "中性点电压严重超界"
If (SevereExceedNum = 0) Then '只往主控台发送1次!!!
SevereExceedNum = 1
a = Send_Current_Status(0, 0, 0, 1)
End If
End Select
End If
Timer1.Enabled = True
End Sub
Function ComServer(ByVal devicenum As Integer)
Dim MidV_Level As Integer
If (devicenum = 1) Then
SendData1
Delay (0.015) '延时10ms后收取下位机的数据
ReceiveData1 '将下位机发送来的数据收到Rbyte中
End If
If (Rbyte(1) = &H11) Then '说明数据正确!!!!
lostnum = 0
MidV_Level = Rbyte(4) '不同档位
If (MidV_Level = 0) Then
MidV_Amplitude1(0) = CDbl(Rbyte(2) + Rbyte(3) * 256) * 0.36053
ElseIf (MidV_Level = 1) Then
MidV_Amplitude1(0) = CDbl(Rbyte(2) + Rbyte(3) * 256) * 0.11493
ElseIf (MidV_Level = 2) Then
MidV_Amplitude1(0) = CDbl(Rbyte(2) + Rbyte(3) * 256) * 0.0261045
End If
'中性点电压频率
If (Rbyte(6) = 0 And Rbyte(7) = 0) Then
Rbyte(7) = &H12
Rbyte(6) = &H4F
End If
MidV_Freq1(0) = Round(234375# / CDbl(Rbyte(6) + Rbyte(7) * 256), 2)
'暂时用不到,所以先不用计算以节省时间
'中性点电流幅值(有效值),电流互感器变比:250:5,未修正!!!!
'MidC_Amplitude1(0) = CDbl(Rbyte(8) + Rbyte(9) * 256) * 1.41421 * 50 / 3830.112
'投切电容总电流幅值(有效值),电流互感器变比:750:5
'TotalCC_Amplitude1(0) = CDbl(Rbyte(10) + Rbyte(11) * 256) * 1.41421 * 150 / 5106.816
'三相线电压的幅值(有效值)和相位,10000:100,未修正!!!!约1.2左右,100/83=1.2
'Vab_Amplitude1(0) = CDbl(Rbyte(12) + Rbyte(13) * 256) * 1.41421 * 100 / 223.872
Vab_Amplitude1(0) = CDbl(Rbyte(12) + Rbyte(13) * 256) * 0.6317
Vab_Phase1(0) = CDbl(Rbyte(14) + Rbyte(15) * 256) / 100#
'Vbc_Amplitude1(0) = CDbl(Rbyte(16) + Rbyte(17) * 256) * 1.41421 * 100 / 223.872
Vbc_Amplitude1(0) = CDbl(Rbyte(16) + Rbyte(17) * 256) * 0.6317
Vbc_Phase1(0) = CDbl(Rbyte(18) + Rbyte(19) * 256) / 100#
'Vca_Amplitude1(0) = CDbl(Rbyte(20) + Rbyte(21) * 256) * 1.41421 * 100 / 223.872
Vca_Amplitude1(0) = CDbl(Rbyte(20) + Rbyte(21) * 256) * 0.6317
Vca_Phase1(0) = CDbl(Rbyte(22) + Rbyte(23) * 256) / 100#
'中性点电压相位
MidV_Phase1(0) = CDbl(Rbyte(24) + Rbyte(25) * 256) / 100#
ElseIf (Rbyte(1) = 0) Then '说明收到的数据都是零!!
lostnum = lostnum + 1
If (lostnum = 10) Then
lostnum = 0
Vab_Amplitude1(0) = CDbl(Rbyte(12) + Rbyte(13) * 256) * 0.6317
Vab_Phase1(0) = CDbl(Rbyte(14) + Rbyte(15) * 256) / 100#
Vbc_Amplitude1(0) = CDbl(Rbyte(16) + Rbyte(17) * 256) * 0.6317
Vbc_Phase1(0) = CDbl(Rbyte(18) + Rbyte(19) * 256) / 100#
Vca_Amplitude1(0) = CDbl(Rbyte(20) + Rbyte(21) * 256) * 0.6317
Vca_Phase1(0) = CDbl(Rbyte(22) + Rbyte(23) * 256) / 100#
If ((Vab_Amplitude1(0) < 4000) Or (Vbc_Amplitude1(0) < 4000) Or (Vca_Amplitude1(0) < 4000)) Then
LostSignal = True
End If
End If
End If
End Function
反正总体说来本系统以10ms作一次循环,在每大概1个半月之后就会死机!
这段时期找bug就成了我的业余生活,在我坚持不懈的on error resume next下终于找到了错误的入口点-Timer1_Timer()主函数中的ComServer (1)函数出了问题!
于是进入ComServer ()函数体进行分析。
其实看看上面的ComServer()这个函数的程序就会发现程序很完美!