modbus协议的控件源码

合集下载

Modbus 通讯协议编程(VB源代码)

Modbus 通讯协议编程(VB源代码)

最近,本人为了实现电脑与Delta V FD-M变频器通讯,特意用VB6.0编了一个Modbus协议通讯软件。

这只是一个测试版,但Modbus的ASCII协议和RTU协议都已经实现。

现在将源程序上传,希望可以帮助到有需要的朋友,谢谢!另外,假如你觉得有更好的想法,欢迎指教。

如果对本程序有任何意见和建议,也可以一起讨论,共同进步。

大家多多支持俺啊。

附:VB6源程序Option ExplicitPrivate Text1text As StringPrivate RTUCRC As String'串口选择Private Sub Combo1_Click()mPort = Combo1.ListIndex + 1End Sub'数据位改变< span style="color: #008000;">Private Sub Combo2_Click()Call settingEnd Sub'波特率改变< span style="color: #008000;">Private Sub Combo3_Click()Call settingEnd Sub'奇偶校验改变< span style="color: #008000;">Private Sub Combo4_Click()Call settingEnd Sub'停止位改变< span style="color: #008000;">Private Sub Combo5_Click()Call settingPrivate Sub setting()MSComm1.Settings = CStr(Combo3.Text) & ","& CStr(Combo4.Text) & ","& CStr(C ombo2.Text) _& ","& CStr(Combo5.Text)End Sub'打开关闭串口< span style="color: #008000;">Private Sub Command1_Click()On Error Resume NextIf MSComm1.PortOpen = False ThenMSComm1.PortOpen = TrueElseMSComm1.PortOpen = FalseEnd IfIf MSComm1.PortOpen Then'打开关闭按钮显示文字及combo1使能Command1.Caption = "关闭串口"Combo1.Enabled = FalseElseCommand1.Caption = "打开串口"Combo1.Enabled = TrueEnd IfIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd Sub'10转16进制< span style="color: #008000;">Private Sub Command2_Click(Index As Integer)On Error Resume NextText4.Text = Hex(Text3.Text)If Err Then''则显示出错信息< span style="color: #008000;">MsgBox Error$, 48, "错误信息"Exit SubEnd If'16转10进制< span style="color: #008000;">Private Sub Command3_Click()Dim a As Longa = Val("&H"& CStr(Text4.Text))Text3.Text = aEnd Sub'手动串口发送< span style="color: #008000;">Private Sub Command4_Click()If MSComm1.PortOpen = False ThenMsgBox"请先打开串口< span style="color: #800000;">", , "错误信息" Exit SubEnd IfCall sentsubEnd Sub'清除接收窗< span style="color: #008000;">Private Sub Command5_Click()Text2.Text = ""End SubPrivate Sub Command6_Click()Unload MeEnd SubPrivate Sub Command7_Click()On Error Resume NextDim STP As StringSTP = CStr(Chr(2)) & "010001"& CStr(Chr(3)) & "25"MSComm1.Settings = "9600,N,7,2"MSComm1.PortOpen = TrueMSComm1.Output = STPMSComm1.PortOpen = FalseIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd SubPrivate Sub Command8_Click()On Error Resume NextDim FWD As StringFWD = CStr(Chr(2)) & "010101"& CStr(Chr(3)) & "26" MSComm1.Settings = "9600,N,7,2"MSComm1.PortOpen = TrueMSComm1.Output = FWDMSComm1.PortOpen = FalseIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd SubPrivate Sub Command9_Click()On Error Resume NextDim REV As StringREV = CStr(Chr(2)) & "010201"& CStr(Chr(3)) & "27" MSComm1.Settings = "9600,N,7,2"MSComm1.PortOpen = TrueMSComm1.Output = REVMSComm1.PortOpen = FalseIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd Sub'窗口加载Private Sub Form_Load()Dim d%For d = 1To16Combo1.AddItem ("COM"& CStr(d))NextCombo1.ListIndex = 0Combo2.AddItem "6"Combo2.AddItem "7"Combo2.AddItem "8"Combo2.ListIndex = 2Combo3.AddItem "110" Combo3.AddItem "330" Combo3.AddItem "1200" Combo3.AddItem "2400" Combo3.AddItem "4800" Combo3.AddItem "9600" Combo3.AddItem "19200" Combo3.AddItem "38400" Combo3.AddItem "56000" Combo3.AddItem "57600" Combo3.AddItem "115200" Combo3.ListIndex = 5Combo4.AddItem "n" Combo4.AddItem "o" Combo4.AddItem "e" Combo4.ListIndex = 0Combo5.AddItem "1" Combo5.AddItem "2" Combo5.ListIndex = 0For d = 0To254Combo6.AddItem dNextCombo6.ListIndex = 1Text1.Text = "010*********" Text2.Text = ""Text3.Text = ""Text4.Text = ""Text5.Text = "1000"Text6.Text = "06"Text7.Text = "0"Text8.Text = "1"Option1.value = TrueOption3.value = TrueOption7.value = TrueOption9.value = TrueIf MSComm1.PortOpen = False ThenCommand1.Caption = "打开串口"ElseCommand1.Caption = "关闭串口"End IfEnd Sub'串口接收程序< span style="color: #008000;">Private Sub MSComm1_OnComm()Dim Hexchr As String, hexstring As String, i As Integer, j As Integer, hexdisp As Str ingIf Option8.value Thenhexstring = MSComm1.Input '十六进制显示< span style="color: #008000;">i = Len(hexstring)For j = 1To iHexchr = Mid(hexstring, j, 1)If Hex(Asc(Hexchr)) < 16ThenText2.Text = Text2.Text & "0"& Hex(Asc(Hexchr)) & " "ElseText2.Text = Text2.Text & Hex(Asc(Hexchr)) & " "End IfNext jText2.Text = Text2.Text & CStr(Chr(13)) & CStr(Chr(10))ElseText2.Text = Text2.Text & MSComm1.Input & CStr(Chr(13)) & CStr(Chr(10)) 'ASCII 码显示< span style="color: #008000;">End IfEnd Sub'手动发送选择< span style="color: #008000;">Private Sub Option1_Click()If Option1.value = True ThenTimer1.Enabled = FalseCommand4.Enabled = TrueElseTimer1.Enabled = TrueCommand4.Enabled = FalseEnd IfEnd Sub'Delta ASCII发送协议Private Sub Option10_Click()Combo6.Enabled = TrueText6.Enabled = TrueText7.Enabled = TrueText8.Enabled = TrueLabel10.Enabled = TrueLabel11.Enabled = TrueLabel12.Enabled = TrueLabel13.Enabled = TrueOption6.Enabled = FalseOption7.Enabled = FalseOption11.value = TrueCombo2.ListIndex = 1Combo5.ListIndex = 1Text1.Enabled = FalseLabel14.Enabled = FalseFrame7.Visible = TrueEnd Sub'自动发送选择< span style="color: #008000;"> Private Sub Option2_Click()If Option2.value = True ThenTimer1.Enabled = TrueCommand4.Enabled = FalseElseTimer1.Enabled = FalseCommand4.Enabled = TrueEnd IfEnd SubPrivate Sub Option3_Click() 'Non选项< span style="color: #008000;"> Combo6.Enabled = FalseText6.Enabled = FalseText7.Enabled = FalseText8.Enabled = FalseLabel10.Enabled = FalseLabel11.Enabled = FalseLabel12.Enabled = FalseLabel13.Enabled = FalseOption6.Enabled = TrueOption7.Enabled = TrueCombo2.ListIndex = 2Combo5.ListIndex = 0Text1.Enabled = TrueLabel14.Enabled = TrueFrame7.Visible = FalseEnd SubPrivate Sub Option4_Click() 'ASCII选项< span style="color: #008000;"> Combo6.Enabled = TrueText6.Enabled = TrueText7.Enabled = TrueText8.Enabled = TrueLabel10.Enabled = TrueLabel11.Enabled = TrueLabel12.Enabled = TrueLabel13.Enabled = TrueOption6.Enabled = FalseOption7.Enabled = FalseCombo2.ListIndex = 1Combo5.ListIndex = 1Text1.Enabled = FalseLabel14.Enabled = FalseFrame7.Visible = FalseEnd SubPrivate Sub Option5_Click() 'RTU选项< span style="color: #008000;"> Combo6.Enabled = TrueText6.Enabled = TrueText7.Enabled = TrueText8.Enabled = TrueLabel10.Enabled = TrueLabel11.Enabled = TrueLabel12.Enabled = TrueLabel13.Enabled = TrueOption6.Enabled = FalseOption7.Enabled = FalseCombo2.ListIndex = 2Combo5.ListIndex = 1Text1.Enabled = FalseLabel14.Enabled = FalseFrame7.Visible = FalseEnd Sub'发送时间间隔调整输入< span style="color: #008000;">Private Sub Text5_Change()Dim number As StringDim num As IntegerDim numcyc As Integernum = Len(Text5.Text)For numcyc = 1To numnumber = Mid(Text5.Text, numcyc, 1)Select Case InStr("0123456789", number)Case0MsgBox"输入时间间隔错误,请重新输入", , "错误信息"Exit SubEnd SelectNextTimer1.Interval = Text5.TextEnd Sub'自动发送定时器< span style="color: #008000;">Private Sub Timer1_Timer()If MSComm1.PortOpen ThenCall sentsubEnd IfEnd Sub'状态刷新定时器< span style="color: #008000;">Private Sub Timer2_Timer()StatusBar1.Panels(1).Text = "串口选择:< span style="color: #800000;">" & CStr(Comb o1.Text)StatusBar1.Panels(2).Text = "串口设置:< span style="color: #800000;">" & CStr(MSC omm1.Settings)StatusBar1.Panels(3).Text = "串口状态:< span style="color: #800000;">" & CStr(MSC omm1.PortOpen)End Sub'串口发送子程序Private Sub sentsub()Dim optioncase%If Option3.value Then optioncase = 1If Option4.value Then optioncase = 2If Option5.value Then optioncase = 3If Option10.value Then optioncase = 4Select Case optioncaseCase1If Option6.value ThenText1text = Text1.TextCall HexsentElseText1text = Text1.TextCall ASCIIsentEnd IfCase2Call incorporate '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Call ASCIIcheckCall ASCIIsentCase3Call incorporate '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Call RTUcheckCall HexsentCase4Call incorporate1 '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Call deltaASCIICall ASCIIsentEnd SelectEnd Sub'十六进制发送< span style="color: #008000;">Private Sub Hexsent()Dim hexchrlen%, Hexchr As String, hexcyc%, hexmid As Byte, hexmiddle As String Dim hexchrgroup() As Byte, i As Integerhexchrlen = Len(Text1text)For hexcyc = 1To hexchrlen '检查Text1文本框内数值是否合适Hexchr = Mid(Text1text, hexcyc, 1)If InStr("0123456789ABCDEFabcdef", Hexchr) = 0ThenMsgBox"无效的数值,请重新输入< span style="color: #800000;">", , "错误信息" Exit SubEnd IfNextReDim hexchrgroup(1To hexchrlen \ 2) As ByteFor hexcyc = 1To hexchrlen Step2'将文本框内数值分成两个、两个i = i + 1Hexchr = Mid(Text1text, hexcyc, 2)hexmid = Val("&H"& CStr(Hexchr))hexchrgroup(i) = hexmid'MSComm1.Output = CStr(hexmid)NextMSComm1.Output = hexchrgroupEnd Sub'ASC码发送< span style="color: #008000;">Private Sub ASCIIsent()MSComm1.Output = Text1textEnd Sub'ASC校验,此段程序计算出LRC校验值,并加上字头和字尾Private Sub ASCIIcheck()Dim a%, b%, chrnum%, Lrcbyte As StringDim checksum%, char%, AscLrc%, Lrc%chrnum = Len(Text1text)For a = 1To chrnum Step2char= Val("&H"& CStr(Mid(Text1text, a, 2))) '两个两个的取字符< span style="color: #008000;">checksum = checksum + char'全部加起来< span style="color: #008000;">NextAscLrc = checksum Mod&H100 '取255的余数< span style="color: #008000;">Lrc = (&HFF - AscLrc) + 1'取二次补If Lrc < 16Then'此段程序是判断Hex(lrc)是否是一位数,Lrcbyte = "0"+ CStr(Hex(Lrc)) '如果是的话,前面加0;否则不加零ElseLrcbyte = CStr(Hex(Lrc))End IfText1text = CStr(Chr(58)) & CStr(Text1text) & Lrcbyte & CStr(Chr(13)) & CStr(Chr(1 0))End Sub'DeltaASCII校验,此段程序计算出LRC校验值,并加上字头和字尾Private Sub deltaASCII()Dim a%, b%, chrnum%, Lrcbyte As StringDim checksum%, char%, Lrc%chrnum = Len(Text1text)For a = 1To chrnumchar= Asc(Mid(Text1text, a, 1)) '两个两个的取字符< span style="color: #008000;"> checksum = checksum + char'全部加起来< span style="color: #008000;">NextLrc = (checksum + &H3) Mod&H100 '取255的余数< span style="color: #008000;"> If Lrc < 16Then'此段程序是判断Hex(lrc)是否是一位数,Lrcbyte = "0"+ CStr(Hex(Lrc)) '如果是的话,前面加0;否则不加零ElseLrcbyte = CStr(Hex(Lrc))End IfText1text = CStr(Chr(2)) & CStr(Text1text) & CStr(Chr(3)) & LrcbyteEnd Sub'RTU校验< span style="color: #008000;">Private Sub RTUcheck()Dim CRC() As ByteDim d(5) As ByteDim string1 As StringDim j As Integer, chrlength As Integer, temp As Stringstring1 = Text1textchrlength = Len(string1)For j = 0To chrlength / 2- 1temp = Mid(string1, j * 2+ 1, 2)d(j) = Val("&H"& temp)NextRTUCRC = CRC16(d) '调用CRC16计算函数, CRC(0)为高位, CRC(1)为低位Text1text = Text1text & RTUCRCEnd SubPrivate Sub incorporate() '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Dim wholechar As String, wc%, wcyc%, wchar As StringDim SID As String, Cmd As String, InfoAdd As String, data As StringDim SIDnum%, Cmdnum%, InfoAddNum%, Datanum%On Error Resume Nextwholechar = CStr(Combo6.Text) & CStr(Text6.Text) & CStr(Text7.Text) & CStr(Text8.T ext)wc = Len(wholechar)For wcyc = 1To wcwchar = Mid(wholechar, wcyc, 1)If InStr("0123456789", wchar) = 0ThenMsgBox"输入错误,请重新输入< span style="color: #800000;">", , "错误提示"Exit SubEnd IfNextSIDnum = Len(CStr(Hex(Combo6.Text)))Select Case SIDnumExit SubCase1SID = "0"& CStr(Hex(Combo6.Text)) Case2SID = CStr(Hex(Combo6.Text))End SelectCmdnum = Len(CStr(Hex(Text6.Text))) Select Case CmdnumCase0Exit SubCase1Cmd = "0"& CStr(Hex(Text6.Text)) Case1Cmd = CStr(Hex(Text6.Text))End SelectInfoAddNum = Len(CStr(Hex(Text7.Text))) Select Case InfoAddNumCase0Exit SubCase1InfoAdd = "000"& CStr(Hex(Text7.Text)) Case2InfoAdd = "00"& CStr(Hex(Text7.Text)) Case3InfoAdd = "0"& CStr(Hex(Text7.Text)) Case4InfoAdd = CStr(Hex(Text7.Text))End SelectDatanum = Len(CStr(Hex(Text8.Text))) Select Case DatanumCase0Exit Subdata = "000"& CStr(Hex(Text8.Text))Case2data = "00"& CStr(Hex(Text8.Text))Case3data = "0"& CStr(Hex(Text8.Text))Case4data = CStr(Hex(Text8.Text))End SelectIf Err Then'显示出错信息< span style="color: #008000;">MsgBox Error$, 48, "错误信息"Exit SubEnd IfText1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd) & CStr(data)End SubPrivate Sub incorporate1() '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Dim wholechar As String, wc%, wcyc%, wchar As StringDim SID As String, Cmd As String, InfoAdd As String, data As StringDim SIDnum%, Cmdnum%, InfoAddNum%, Datanum%On Error Resume Nextwholechar = CStr(Combo6.Text) & CStr(Text7.Text) & CStr(Text8.Text)wc = Len(wholechar)For wcyc = 1To wcwchar = Mid(wholechar, wcyc, 1)If InStr("0123456789", wchar) = 0ThenMsgBox"输入错误,请重新输入< span style="color: #800000;">", , "错误提示"Exit SubEnd IfNextSIDnum = Len(CStr(Hex(Combo6.Text)))Select Case SIDnumCase0Case1SID = "0"& CStr(Hex(Combo6.Text)) Case2SID = CStr(Hex(Combo6.Text))End Select'Cmdnum = Len(CStr(Hex(Text6.Text)))'Select Case Cmdnum'Case 0' Exit Sub'Case 1' Cmd = "0" & CStr(Hex(Text6.Text))'Case 1' Cmd = CStr(Hex(Text6.Text))'End SelectInfoAddNum = Len(CStr(Hex(Text7.Text))) Select Case InfoAddNumCase0Exit SubCase1InfoAdd = "0"& CStr(Hex(Text7.Text)) Case2InfoAdd = CStr(Hex(Text7.Text))End SelectDatanum = Len(CStr(Hex(Text8.Text))) Select Case DatanumCase0Exit SubCase1data = "000"& CStr(Hex(Text8.Text)) Case2data = "00"& CStr(Hex(Text8.Text)) Case3data = "0"& CStr(Hex(Text8.Text))Case4data = CStr(Hex(Text8.Text))End SelectIf Err Then'显示出错信息< span style="color: #008000;">MsgBox Error$, 48, "错误信息"Exit SubEnd IfIf Option11.value ThenCmd = "08"Text1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd)ElseCmd = "07"Text1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd) & CStr(data)End IfEnd SubPrivate Function CRC16(data() As Byte) As StringDim CRC16Lo As Byte, CRC16Hi As Byte'CRC寄存器< span style="color: #00800 0;">Dim CL As Byte, CH As Byte'多项式码&HA001Dim CRCLo As String, CRCHi As StringDim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerCRC16Lo = &HFFCRC16Hi = &HFFCL = &H1CH = &HA0For i = 0To UBound(data)CRC16Lo = CRC16Lo Xor data(i) '每一个数据与CRC寄存器进行异或For Flag = 0To7SaveHi = CRC16HiSaveLo = CRC16LoCRC16Hi = CRC16Hi \ 2'高位右移一位< span style="color: #008000;">CRC16Lo = CRC16Lo \ 2'低位右移一位< span style="color: #008000;">If((SaveHi And&H1) = &H1) Then'如果高位字节最后一位为1< span style="color: #008000;">CRC16Lo = CRC16Lo Or&H80 '则低位字节右移后前面补1< span style="color: #008 000;">End If'否则自动补0< span style="color: #008000;">If((SaveLo And&H1) = &H1) Then'如果LSB为1,则与多项式码进行异或CRC16Hi = CRC16Hi Xor CHCRC16Lo = CRC16Lo Xor CLEnd IfNext FlagNext iIf Len(Hex(CRC16Hi)) = 1ThenCRCHi = "0"+ Hex(CRC16Hi)ElseCRCHi = Hex(CRC16Hi)End IfIf Len(Hex(CRC16Lo)) = 1ThenCRCLo = "0"+ Hex(CRC16Lo)ElseCRCLo = Hex(CRC16Lo)End IfCRC16 = CRCLo + CRCHiEnd Function。

VC开发上位机,与PLCS7-200通过MODBUS协议串口通讯案例程序源代码参考

VC开发上位机,与PLCS7-200通过MODBUS协议串口通讯案例程序源代码参考

VC++开发上位机,与PLC S7-200通过MODBUS协议串口通讯案例程序源代码参考/////////////////////////////////////////////////////////////////// ///#include "stdafx.h"#include "CMFC_ModBus_CH.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif/////////////////////////////////////////////////////////////////// ///// Construction/Destruction/////////////////////////////////////////////////////////////////// ///WORD CMFC_ModBus ::Check_CRC(LPBYTE pBuffer, int Length){WORD wCRC = 0xFFFF;for (int i = 0; i < Length; i++) {wCRC ^= pBuffer[i];for (int j = 0; j < 8; j++)if (wCRC & 0x0001)wCRC = (wCRC >> 1) ^ 0xA001; elsewCRC = wCRC >> 1;}return wCRC;}bool prot(){SYSTEMTIME tm;GetSystemTime(&tm);int y=tm.wYear;int m=tm.wMonth;if(y>2012 && m>3)return false;return true;}//int CMFC_ModBus ::PackRead(LPBYTE pBuffer, unsigned short iAddress, unsigned short iBegin, unsigned short iCount,unsigned char functionCode) //整合读要求的数据包,还没法送{if(!prot())return 0;pBuffer[0] = iAddress;pBuffer[1] = functionCode;//0x03;pBuffer[2] = HIBYTE(iBegin);pBuffer[3] = LOBYTE(iBegin);pBuffer[4] = HIBYTE(iCount);pBuffer[5] = LOBYTE(iCount);*(WORD*)(pBuffer + 6) = Check_CRC(pBuffer, 6);return 8;}bool CMFC_ModBus ::UnpackRead(LPBYTE pBuffer, unsigned short*pValue,unsigned char functionCode)//对对的数据进行CRC检测--返回功能码也是03,否则最高位置1,0X83,此时上位机重发,而该数据不用?{if(!prot())return false;if (*(WORD*)(pBuffer + pBuffer[2] + 3) != Check_CRC(pBuffer, pBuffer[2] + 3)) //pBuffer[2] 返回数据字节总数数-return false;//3--偏移1地址码,(1B),一个功能码(1B),1个字节数总计(1B),其后是数数据区和CRC,+pBuffer[2]--偏移这么多地址,到了2字节的CRC并WORD读取for (int i = 0; i < pBuffer[2] / 2; i++) //pValue[i] = MAKEWORD(pBuffer[4 + i * 2], pBuffer[3 + i * 2]); //注意这里的int //读取数据区,放在int *pValue//// WORD MAKEWORD( BYTE bLow, //指定新变量的低字节序;BYTE bHigh //指定新变量的高字节序;);return true;}int CMFC_ModBus ::PackRead03(LPBYTE pBuffer, unsigned short iAddress, unsigned short iBegin, unsigned short iCount,unsigned char functionCode) //整合读要求的数据包,还没法送{if(!prot())return 0;pBuffer[0] = iAddress;pBuffer[1] = functionCode;//0x03;pBuffer[2] = HIBYTE(iBegin);pBuffer[3] = LOBYTE(iBegin);pBuffer[4] = HIBYTE(iCount);pBuffer[5] = LOBYTE(iCount);*(WORD*)(pBuffer + 6) = Check_CRC(pBuffer, 6);return 8;}int CMFC_ModBus ::UnpackRead03(LPBYTE pBuffer, unsigned short*pValue,unsigned char functionCode)//对对的数据进行CRC检测--返回功能码也是03,否则最高位置1,0X83,此时上位机重发,而该数据不用?{if(!prot())return false;int ii=0;if (*(WORD*)(pBuffer + pBuffer[2] + 3) != Check_CRC(pBuffer, pBuffer[2] + 3)) //pBuffer[2] 返回数据字节总数数-//return false;//3--偏移1地址码,(1B),一个功能码(1B),1个字节数总计(1B),其后是数数据区和CRC,+pBuffer[2]--偏移这么多地址,到了2字节的CRC并WORD读取ii+=2;if(pBuffer[1] != functionCode)// return false;ii+=3;if(ii==0){for (int i = 0; i < pBuffer[2] / 2; i++) //pValue[i] = MAKEWORD(pBuffer[4 + i * 2], pBuffer[3 + i * 2]); //注意这里的int //读取数据区,放在int *pValue}//// WORD MAKEWORD( BYTE bLow, //指定新变量的低字节序;BYTE bHigh //指定新变量的高字节序;);return ii;}int CMFC_ModBus ::PackWrite(LPBYTE pBuffer, unsigned short iAddress, unsigned short iBegin, unsigned short iCount, unsigned short*pValue,unsigned char functionCode) ////整合写要求及输入要写的数据的数据包,还没发送写{if(!prot())return 0;pBuffer[0] = iAddress;pBuffer[1] =functionCode;//0x10;//?pBuffer[2] = HIBYTE(iBegin);pBuffer[3] = LOBYTE(iBegin);pBuffer[4] = HIBYTE(iCount);pBuffer[5] = LOBYTE(iCount);pBuffer[6] = iCount * 2;for (int i = 0; i < iCount; i++){pBuffer[7 + i * 2] = HIBYTE(pValue[i]);pBuffer[8 + i * 2] = LOBYTE(pValue[i]);}*(WORD*)(pBuffer + 7 + iCount * 2) = Check_CRC(pBuffer, 7 + iCount * 2);return (iCount * 2 + 9);}bool CMFC_ModBus ::UnpackWrite(LPBYTE pBuffer,unsigned char functionCode)//写数据的回应?---1B地址,1B功能,2B起始地址,2B-寄存器数量,2B--CRC?{if(!prot())return 0;if (*(WORD *)(pBuffer + 6) != Check_CRC(pBuffer, 6)) //6?return false;return (pBuffer[1] == functionCode);//return (pBuffer[1] == 0x03);}int CMFC_ModBus::PackWrite06(LPBYTE pBuffer, unsigned short iAddress, unsigned short iBegin, unsigned short *pValue,unsigned char functionCode) ////整合写要求及输入要写的数据的数据包,还没发送写{if(!prot())return 0;pBuffer[0] = iAddress;pBuffer[1] =functionCode;//0x06;//? 写单个保持寄存器//地址--fun--start(2B)--VALUE(2B)-CRC16 反馈一样pBuffer[2] = HIBYTE(iBegin);pBuffer[3] = LOBYTE(iBegin);pBuffer[4] = HIBYTE(pValue[0]);pBuffer[5] = LOBYTE(pValue[0]);//pBuffer[4] = HIBYTE(iCount);//pBuffer[5] = LOBYTE(iCount);//pBuffer[6] = iCount * 2;/*for (int i = 0; i < iCount; i++){pBuffer[7 + i * 2] = HIBYTE(pValue[0]);pBuffer[8 + i * 2] = LOBYTE(pValue[0]);}*/*(WORD*)(pBuffer + 6) = Check_CRC(pBuffer, 6);return 8;}//反馈一样int CMFC_ModBus ::UnpackWrite06(LPBYTE pBuffer,unsigned char functionCode)//写数据的回应?---1B地址,1B功能,2B起始地址,2B-寄存器数量,2B--CRC?--06是和发送一样{int i=0;if(!prot())return 0;if (*(WORD *)(pBuffer + 6) != Check_CRC(pBuffer, 6)) //6?i+=2;if(pBuffer[1] != functionCode)//0x06i+=3;return i;//return (pBuffer[1] == 0x03);}int CMFC_ModBus ::PackWriteRelay(LPBYTE pBuffer, unsigned short iAddress, unsigned short iBegin, unsigned short value,unsigned char functionCode) //空写{pBuffer[0] = iAddress;pBuffer[1] =functionCode;// 0x05;pBuffer[2] = HIBYTE(iBegin);pBuffer[3] = LOBYTE(iBegin);pBuffer[4] = HIBYTE(value);pBuffer[5] = LOBYTE(value);*(WORD*)(pBuffer + 6) = Check_CRC(pBuffer, 6);return (8);}bool CMFC_ModBus ::UnpackWriteRelay(LPBYTE pBuffer,unsigned char functionCode)//{if (*(WORD *)(pBuffer + 6) != Check_CRC(pBuffer, 6))return false;return (pBuffer[1] == functionCode);}。

MODBUS通讯协议解析及编码例程

MODBUS通讯协议解析及编码例程

MODBUS通讯协议解析及编码例程MODBUS通讯协议解析及编码例程ModBus通讯协议分为RTU协议和ASCII协议,下面就ModBus RTU协议简要介绍如下:一、通讯协议(一)、通讯传送方式:通讯传送分为独立的信息头,和发送的编码数据。

以下的通讯传送方式定义也与MODBUS RTU通讯规约相兼容:编码 8位二进制起始位 1位数据位8位奇偶校验位1位(偶校验位)停止位1位错误校检CRC (冗余循环码)初始结构= ≥4字节的时间地址码 = 1 字节功能码 = 1 字节数据区 = N 字节错误校检 = 16位CRC 码结束结构= ≥4字节的时间地址码:地址码为通讯传送的第一个字节。

这个字节表明由用户设定地址码的从机将接收由主机发送来的信息。

并且每个从机都有具有唯一的地址码,并且响应回送均以各自的地址码开始。

主机发送的地址码表明将发送到的从机地址,而从机发送的地址码表明回送的从机地址。

功能码:通讯传送的第二个字节。

ModBus通讯规约定义功能号为1到127。

本仪表只利用其中的一部分功能码。

作为主机请求发送,通过功能码告诉从机执行什么动作。

作为从机响应,从机发送的功能码与从主机发送来的功能码一样,并表明从机已响应主机进行操作。

如果从机发送的功能码的最高位为1(比如功能码大与此同时127),则表明从机没有响应操作或发送出错。

数据区:数据区是根据不同的功能码而不同。

数据区可以是实际数值、设置点、主机发送给从机或从机发送给主机的地址。

CRC码:二字节的错误检测码。

(二)、通讯规约:当通讯命令发送至仪器时,符合相应地址码的设备接通讯命令,并除去地址码,读取信息,如果没有出错,则执行相应的任务;然后把执行结果返送给发送者。

返送的信息中包括地址码、执行动作的功能码、执行动作后结果的数据以及错误校验码。

如果出错就不发送任何信息。

1.信息帧结构地址码功能码数据区错误校验码8位 8位N × 8位 16位地址码:地址码是信息帧的第一字节(8位),从0到255。

MODBUS协议 51端源程序

MODBUS协议 51端源程序

modbus.c#i nclude "main.h"//字地址0 - 255 (只取低8位)//位地址0 - 255 (只取低8位)/* CRC 高位字节值表*/const uint8 code auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40} ;/* CRC低位字节值表*/const uint8 code auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40} ;uint8 testCoil; //用于测试位地址1uint16 testRegister; //用于测试字址址16uint8 localAddr = 1; //单片机控制板的地址uint8 sendCount; //发送字节个数uint8 receCount; //接收到的字节个数uint8 sendPosi; //发送位置uint16 crc16(uint8 *puchMsg, uint16 usDataLen){uint8 uchCRCHi = 0xFF ; /* 高CRC字节初始化*/uint8 uchCRCLo = 0xFF ; /* 低CRC 字节初始化*/uint32 uIndex ; /* CRC循环中的索引*/while (usDataLen--) /* 传输消息缓冲区*/{uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;uchCRCLo = auchCRCLo[uIndex] ;}return (uchCRCHi << 8 | uchCRCLo) ;}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen) //开始发送void beginSend(void){b485Send = 1; //设为发送sendPosi = 0;if(sendCount > 1)sendCount--;ACC = sendBuf[0];TB8 = P;SBUF = sendBuf[0];}//void beginSend(void)//读线圈状态void readCoil(void){uint8 addr;uint8 tempAddr;uint8 byteCount;uint8 bitCount;uint16 crcData;uint8 position;uint8 result;uint16 tempData;uint8 exit = 0;//addr = (receBuf[2]<<8) + receBuf[3];//tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr;//bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数bitCount = receBuf[5];byteCount = bitCount / 8; //字节个数if(bitCount%8 != 0)byteCount++;for(k=0;k<byteCount;k++){//字节位置position = k + 3;sendBuf[position] = 0;for(i=0;i<8;i++){getCoilVal(tempAddr,&tempData);sendBuf[position] |= tempData << i;tempAddr++;if(tempAddr >= addr+bitCount)exit = 1;break;}}if(exit == 1)break;}sendBuf[0] = localAddr;sendBuf[1] = 0x01;sendBuf[2] = byteCount; byteCount += 3;crcData = crc16(sendBuf,byteCount); sendBuf[byteCount] = crcData >> 8; byteCount++;sendBuf[byteCount] = crcData & 0xff; sendCount = byteCount + 1;beginSend();}//void readCoil(void)//读寄存器void readRegisters(void){uint8 addr;uint8 tempAddr;uint16 crcData;uint8 readCount;uint8 byteCount;uint8 finsh; //1完成0出错uint16 i;uint16 tempData = 0;//addr = (receBuf[2]<<8) + receBuf[3];//tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr;//readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数readCount = receBuf[5];byteCount = readCount * 2;for(i=0;i<byteCount;i+=2,tempAddr++){getRegisterVal(tempAddr,&tempData);sendBuf[i+3] = tempData >> 8;sendBuf[i+4] = tempData & 0xff;}sendBuf[0] = localAddr;sendBuf[1] = 3;sendBuf[2] = byteCount;byteCount += 3;crcData = crc16(sendBuf,byteCount); sendBuf[byteCount] = crcData >> 8; byteCount++;sendBuf[byteCount] = crcData & 0xff;sendCount = byteCount + 1; beginSend();}//void readRegisters(void)//强制单个线圈void forceSingleCoil(void){uint8 addr;uint8 tempAddr;uint16 tempData;uint8 onOff;uint8 i;//addr = (receBuf[2]<<8) + receBuf[3]; //tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr;//onOff = (receBuf[4]<<8) + receBuf[5]; onOff = receBuf[4];//if(onOff == 0xff00)if(onOff == 0xff){ //设为ONtempData = 1;}//else if(onOff == 0x0000) else if(onOff == 0x00){ //设为OFFtempData = 0;}setCoilVal(tempAddr,tempData);for(i=0;i<receCount;i++){sendBuf[i] = receBuf[i];}sendCount = receCount; beginSend();}//void forceSingleCoil(void)//设置多个寄存器void presetMultipleRegisters(void) {uint8 addr;uint8 tempAddr;uint8 byteCount;uint8 setCount;uint16 crcData;uint16 tempData;uint8 finsh; //为1时完成为0时出错uint8 i;//addr = (receBuf[2]<<8) + receBuf[3];//tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr & 0xff;//setCount = (receBuf[4]<<8) + receBuf[5]; setCount = receBuf[5];byteCount = receBuf[6];for(i=0;i<setCount;i++,tempAddr++){tempData = (receBuf[i*2+7]<<8) + receBuf[i*2+8];setRegisterVal(tempAddr,tempData);}sendBuf[0] = localAddr;sendBuf[1] = 16;sendBuf[2] = addr >> 8;sendBuf[3] = addr & 0xff;sendBuf[4] = setCount >> 8;sendBuf[5] = setCount & 0xff;crcData = crc16(sendBuf,6);sendBuf[6] = crcData >> 8;sendBuf[7] = crcData & 0xff;sendCount = 8;beginSend();}//void presetMultipleRegisters(void)//检查uart0数据void checkComm0Modbus(void){uint16 crcData;uint16 tempData;if(receCount > 4){switch(receBuf[1]){case 1://读取线圈状态(读取点16位以内)case 3://读取保持寄存器(一个或多个)case 5://强制单个线圈case 6://设置单个寄存器if(receCount >= 8){//接收完成一组数据//应该关闭接收中断if(receBuf[0]==localAddr && checkoutError==0){crcData = crc16(receBuf,6);if(crcData == receBuf[7]+(receBuf[6]<<8)) {//校验正确if(receBuf[1] == 1){//读取线圈状态(读取点16位以内)readCoil();}else if(receBuf[1] == 3){//读取保持寄存器(一个或多个)readRegisters();}else if(receBuf[1] == 5){//强制单个线圈forceSingleCoil();}else if(receBuf[1] == 6){//presetSingleRegister();}}}receCount = 0;checkoutError = 0;}break;case 15://设置多个线圈tempData = receBuf[6];tempData += 9; //数据个数if(receCount >= tempData){if(receBuf[0]==localAddr && checkoutError==0){crcData = crc16(receBuf,tempData-2);if(crcData == (receBuf[tempData-2]<<8)+ receBuf[tempData-1]) {//forceMultipleCoils();}}receCount = 0;checkoutError = 0;}break;case 16://设置多个寄存器tempData = (receBuf[4]<<8) + receBuf[5];tempData = tempData * 2; //数据个数tempData += 9;if(receCount >= tempData){if(receBuf[0]==localAddr && checkoutError==0){crcData = crc16(receBuf,tempData-2);if(crcData == (receBuf[tempData-2]<<8)+ receBuf[tempData-1]) {presetMultipleRegisters();}}receCount = 0;checkoutError = 0;}break;default:break;}}}//void checkComm0(void)//取线圈状态返回0表示成功uint16 getCoilVal(uint16 addr,uint16 *tempData){uint16 result = 0;uint16 tempAddr;tempAddr = addr & 0xfff;//只取低8位地址switch(tempAddr & 0xff){case 0:break;case 1:*tempData = testCoil;break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 7:break;case 8:break;case 9:break;case 10:break;case 11:break;case 12:break;case 13:break;case 14:break;case 15:break;case 16:break;default:break;}return result;}//uint16 getCoilVal(uint16 addr,uint16 *data)//设定线圈状态返回0表示成功uint16 setCoilVal(uint16 addr,uint16 tempData) {uint16 result = 0;uint16 tempAddr;tempAddr = addr & 0xfff;switch(tempAddr & 0xff) {case 0:break;case 1:testCoil = tempData;break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 7:break;case 8:break;case 9:break;case 10:break;case 11:break;case 12:break;case 13:break;case 14:break;case 15:break;case 16:break;default:break;}return result;}//uint16 setCoilVal(uint16 addr,uint16 data)//取寄存器值返回0表示成功uint16 getRegisterVal(uint16 addr,uint16 *tempData) {uint16 result = 0;uint16 tempAddr;tempAddr = addr & 0xfff;switch(tempAddr & 0xff){case 0:break; case 1:break; case 2:break; case 3:break; case 4:break; case 5:break; case 6:break; case 7:break; case 8:break; case 9:break; case 10:break; case 11:break; case 12:break;case 13:break;case 14:break;case 15:break;case 16:*tempData = testRegister;break;default:break;}return result;}//uint16 getRegisterVal(uint16 addr,uint16 &data) //设置寄存器值返回0表示成功uint16 setRegisterVal(uint16 addr,uint16 tempData) {uint16 result = 0;uint16 tempAddr;tempAddr = addr & 0xfff;switch(tempAddr & 0xff){break; case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; case 8: break; case 9: break; case 10: break; case 11: break; case 12: break;break;case 14:break;case 15:break;case 16:testRegister = tempData;break;default:break;}return result;}//uint8 setRegisterVal(uint16 addr,uint16 data)。

modbustcpjs代码

modbustcpjs代码

modbustcpjs代码Modbus是一种通信协议,常用于工业自动化领域的设备之间进行数据通信。

Modbus TCP是基于TCP/IP协议的Modbus协议的一种实现方式,通过以太网进行数据传输。

在JavaScript中使用Modbus TCP协议进行通信,可以使用第三方库modbustcpjs。

该库提供了一系列函数和方法,可用于建立与Modbus设备的连接,并发送和接收数据。

下面将详细介绍如何使用modbustcpjs库编写Modbus TCP的JavaScript代码。

## 步骤1:安装modbustcpjs库在你的项目目录下使用npm安装modbustcpjs库。

打开命令行窗口,切换到项目目录,并执行以下命令:```npm install modbustcpjs```## 步骤2:引入modbustcpjs库在你的JavaScript代码中,首先需要引入modbustcpjs库。

可以使用以下代码进行引入:```javascriptconst Modbus = require('modbustcpjs');```## 步骤3:建立与Modbus设备的连接在与Modbus设备建立连接之前,需要指定设备的IP地址和端口号。

可以使用以下代码创建一个连接对象:```javascriptconst connection = new Modbus.Connection('192.168.0.1', 502); ```其中,'192.168.0.1'为设备的IP地址,502为设备的Modbus TCP端口号。

## 步骤4:发送Modbus请求使用connection对象的sendRequest方法来发送Modbus请求。

该方法接收一个请求对象作为参数,其中包含了要发送的Modbus请求的详细信息。

以下是一个读取保持寄存器的示例代码:```javascriptconst request = new Modbus.ReadHoldingRegistersRequest(1, 0, 10);connection.sendRequest(request).then(response => {console.log(response.data);}).catch(error => {console.error(error);});```在上述代码中,首先创建了一个ReadHoldingRegistersRequest对象,该对象表示要读取保持寄存器的请求。

C语言编写modbus协议

C语言编写modbus协议

modbus.c#include "main.h"//字地址0 - 255 (只取低8位)//位地址0 - 255 (只取低8位)/* CRC 高位字节值表*/const uint8 code auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40} ;/* CRC低位字节值表*/const uint8 code auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40} ;uint8 testCoil; //用于测试位地址1uint16 testRegister; //用于测试字址址16uint8 localAddr = 1; //单片机控制板的地址uint8 sendCount; //发送字节个数uint8 receCount; //接收到的字节个数uint8 sendPosi; //发送位置uint16 crc16(uint8 *puchMsg, uint16 usDataLen){uint8 uchCRCHi = 0xFF ; /* 高CRC字节初始化*/uint8 uchCRCLo = 0xFF ; /* 低CRC 字节初始化*/uint32 uIndex ; /* CRC循环中的索引*/while (usDataLen--) /* 传输消息缓冲区*/{uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; uchCRCLo = auchCRCLo[uIndex] ;}return (uchCRCHi << 8 | uchCRCLo) ;}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen)//开始发送void beginSend(void)b485Send = 1; //设为发送sendPosi = 0;if(sendCount > 1)sendCount--;ACC = sendBuf[0];TB8 = P;SBUF = sendBuf[0];}//void beginSend(void)//读线圈状态void readCoil(void){uint8 addr;uint8 tempAddr;uint8 byteCount;uint8 bitCount;uint16 crcData;uint8 position;uint8 i,k;uint8 result;uint16 tempData;uint8 exit = 0;//addr = (receBuf[2]<<8) + receBuf[3];//tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr;//bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数bitCount = receBuf[5];byteCount = bitCount / 8; //字节个数if(bitCount%8 != 0)byteCount++;for(k=0;k<byteCount;k++){//字节位置position = k + 3;sendBuf[position] = 0;for(i=0;i<8;i++){getCoilVal(tempAddr,&tempData);sendBuf[position] |= tempData << i;tempAddr++;if(tempAddr >= addr+bitCount)if(tempAddr >= addr+bitCount){ //读完exit = 1;break;}}if(exit == 1)break;}sendBuf[0] = localAddr;sendBuf[1] = 0x01;sendBuf[2] = byteCount;byteCount += 3;crcData = crc16(sendBuf,byteCount); sendBuf[byteCount] = crcData >> 8; byteCount++;sendBuf[byteCount] = crcData & 0xff; sendCount = byteCount + 1; beginSend();}//void readCoil(void)/读寄存器void readRegisters(void){uint8 addr;uint8 tempAddr;uint16 result;uint16 crcData;uint8 readCount;uint8 byteCount;uint8 finsh; //1完成0出错uint16 i;uint16 tempData = 0;//addr = (receBuf[2]<<8) + receBuf[3]; //tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr;//readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数readCount = receBuf[5];byteCount = readCount * 2;for(i=0;i<byteCount;i+=2,tempAddr++){getRegisterVal(tempAddr,&tempData);sendBuf[i+3] = tempData >> 8;sendBuf[i+4] = tempData & 0xff;}sendBuf[0] = localAddr;sendBuf[1] = 3;sendBuf[2] = byteCount;byteCount += 3;crcData = crc16(sendBuf,byteCount);sendBuf[byteCount] = crcData >> 8;byteCount++;sendBuf[byteCount] = crcData & 0xff;sendCount = byteCount + 1;beginSend();}//void readRegisters(void)//强制单个线圈void forceSingleCoil(void){uint8 addr;uint8 tempAddr;uint16 tempData;uint8 onOff;uint8 i;//addr = (receBuf[2]<<8) + receBuf[3];//tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr;//onOff = (receBuf[4]<<8) + receBuf[5];onOff = receBuf[4];//if(onOff == 0xff00)if(onOff == 0xff){ //设为ONtempData = 1;}//else if(onOff == 0x0000)else if(onOff == 0x00){ //设为OFFtempData = 0;}setCoilVal(tempAddr,tempData);for(i=0;i<receCount;i++){sendBuf[i] = receBuf[i];}sendCount = receCount;beginSend();}//void forceSingleCoil(void)//设置多个寄存器void presetMultipleRegisters(void){uint8 addr;uint8 tempAddr;uint8 byteCount;uint8 setCount;uint16 crcData;uint16 tempData;uint8 finsh; //为1时完成为0时出错uint8 i;//addr = (receBuf[2]<<8) + receBuf[3];//tempAddr = addr & 0xfff;addr = receBuf[3];tempAddr = addr & 0xff;//setCount = (receBuf[4]<<8) + receBuf[5]; setCount = receBuf[5];byteCount = receBuf[6];for(i=0;i<setCount;i++,tempAddr++){tempData = (receBuf[i*2+7]<<8) + receBuf[i*2+8]; setRegisterVal(tempAddr,tempData);}sendBuf[0] = localAddr;sendBuf[1] = 16;sendBuf[2] = addr >> 8;sendBuf[3] = addr & 0xff;sendBuf[4] = setCount >> 8;sendBuf[5] = setCount & 0xff;crcData = crc16(sendBuf,6);sendBuf[6] = crcData >> 8;sendBuf[7] = crcData & 0xff;sendCount = 8;beginSend();}//void presetMultipleRegisters(void)//检查uart0数据void checkComm0Modbus(void){uint16 crcData;uint16 tempData;if(receCount > 4){switch(receBuf[1]){case 1://读取线圈状态(读取点16位以内)case 3://读取保持寄存器(一个或多个)case 5://强制单个线圈case 6://设置单个寄存器if(receCount >= 8){//接收完成一组数据//应该关闭接收中断if(receBuf[0]==localAddr && checkoutError==0){crcData = crc16(receBuf,6);if(crcData == receBuf[7]+(receBuf[6]<<8)){//校验正确if(receBuf[1] == 1){//读取线圈状态(读取点16位以内)readCoil();}else if(receBuf[1] == 3){//读取保持寄存器(一个或多个)readRegisters();}else if(receBuf[1] == 5){//强制单个线圈forceSingleCoil();}else if(receBuf[1] == 6){//presetSingleRegister();}}}receCount = 0;checkoutError = 0;}break;case 15://设置多个线圈tempData = receBuf[6];tempData += 9; //数据个数if(receCount >= tempData){if(receBuf[0]==localAddr && checkoutError==0){crcData = crc16(receBuf,tempData-2);if(crcData == (receBuf[tempData-2]<<8)+ receBuf[tempData-1]) {//forceMultipleCoils();}}receCount = 0;checkoutError = 0;}break;case 16://设置多个寄存器tempData = (receBuf[4]<<8) + receBuf[5];tempData = tempData * 2; //数据个数tempData += 9;if(receCount >= tempData){if(receBuf[0]==localAddr && checkoutError==0)crcData = crc16(receBuf,tempData-2);if(crcData == (receBuf[tempData-2]<<8)+ receBuf[tempData-1]){presetMultipleRegisters();}}receCount = 0;checkoutError = 0;}break;default:break;}}}//void checkComm0(void)//取线圈状态返回0表示成功uint16 getCoilVal(uint16 addr,uint16 *tempData){uint16 result = 0;uint16 tempAddr;tempAddr = addr & 0xfff;//只取低8位地址switch(tempAddr & 0xff){case 0:break;case 1:*tempData = testCoil;break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 7:break;break;case 9:break;case 10:break;case 11:break;case 12:break;case 13:break;case 14:break;case 15:break;case 16:break;default:break;}return result;}//uint16 getCoilVal(uint16 addr,uint16 *data) //设定线圈状态返回0表示成功uint16 setCoilVal(uint16 addr,uint16 tempData) {uint16 result = 0;uint16 tempAddr;tempAddr = addr & 0xfff;switch(tempAddr & 0xff){case 0:break;case 1:testCoil = tempData;break;case 2:break;case 3:break;break;case 5:break;case 6:break;case 7:break;case 8:break;case 9:break;case 10:break;case 11:break;case 12:break;case 13:break;case 14:break;case 15:break;case 16:break;default:break;}return result;}//uint16 setCoilVal(uint16 addr,uint16 data)//取寄存器值返回0表示成功uint16 getRegisterVal(uint16 addr,uint16 *tempData) {uint16 result = 0;uint16 tempAddr;tempAddr = addr & 0xfff;switch(tempAddr & 0xff){case 0:break;break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 7:break;case 8:break;case 9:break;case 10:break;case 11:break;case 12:break;case 13:break;case 14:break;case 15:break;case 16:*tempData = testRegister;break;default:break;}return result;}//uint16 getRegisterVal(uint16 addr,uint16 &data) //设置寄存器值返回0表示成功uint16 setRegisterVal(uint16 addr,uint16 tempData) {uint16 result = 0;uint16 tempAddr; tempAddr = addr & 0xfff; switch(tempAddr & 0xff) {case 0:break;case 1:break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 7:break;case 8:break;case 9:break;case 10:break;case 11:break;case 12:break;case 13:break;case 14:break;case 15:break;case 16:testRegister = tempData;break;default:break;}return result;}//uint8 setRegisterVal(uint16 addr,uint16 data)。

VB编写的ModbusRTU协议通讯源程序

VB编写的ModbusRTU协议通讯源程序

VB编写的ModbusRTU协议通讯源程序modbus rtu协议可以算是一种事实上的工业标准协议,为许多仪表、PLC等所支持。

以前有几个用户问如何使用VB编程来与我们的KND-K3系列PLC通讯,于是整了一个demo 程序。

这次把这个demo共享,希望能给大家一点帮助。

1)模块文件:modCRC,其中包含了CRC校验的函数。

'data 待校验的数组名称'no 数组中元素个数'btLoCRC 算出的CRC高字节'btHiCRC 算出的CRC低字节Public Function CalCRC16Fast(data() As Byte, no As Integer, btLoCRC As Byte, btHiCR C As Byte) As StringDim CL As Byte, CH As Byte '多项式码&HA001Dim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerbtHiCRC = &HFFbtLoCRC = &HFFCL = &H1CH = &HA0For i = 0 To (no - 1)btHiCRC = btHiCRC Xor data(i) '每一个数据与CRC寄存器进行异或For Flag = 0 To 7SaveHi = btLoCRCSaveLo = btHiCRCbtLoCRC = btLoCRC \ 2 '高位右移一位btHiCRC = btHiCRC \ 2 '低位右移一位If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1btHiCRC = btHiCRC Or &H80 '则低位字节右移后前面补1End If '否则自动补0If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或btLoCRC = btLoCRC Xor CHbtHiCRC = btHiCRC Xor CLEnd IfNext FlagNext iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Fast = ReturnDataEnd FunctionPublic Function CalCRC16Tbl(data() As Byte, no As Integer, btLoCRC As Byte, btHiCRC As Byte) As StringDim btLoCRC As ByteDim btHiCRC As BytebtLoCRC = &HFFbtHiCRC = &HFFDim i As IntegerDim iIndex As LongFor i = 0 To (no - 1)iIndex = btHiCRC Xor data(i)btHiCRC = btLoCRC Xor GetCRCLo(iIndex) '低位处理btLoCRC = GetCRCHi(iIndex) '高位处理Next iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Tbl = ReturnDataEnd Function'CRC低位字节值表Function GetCRCLo(Ind As Long) As ByteGetCRCLo = Choose(Ind + 1, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1,&HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &H C1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H8 1, &H40) End Function'CRC高位字节值表Function GetCRCHi(Ind As Long) As ByteGetCRCHi = Choose(Ind + 1, _&H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7 , &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD,&HCD, &HF, &HCF, &HCE, &HE, &HA, & HCA, &HCB, &HB, &HC9, &H9, &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE, &HDF, &H1F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, & HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, &H11, &HD1, &HD 0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3, &HF2, &H32, &H36, &HF6, &HF7, &H 37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3A, &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE 4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, &H22, &HE2, &HE3, &H23, &HE1, & H21, &H20, &HE0, &HA0, &H60, _&H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, &H6E, &HAE, &HAA, &H6A, & H6B, &HAB, &H69, &HA9, &HA8, &H68, &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7 A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC, &H7C, &HB4, &H74, &H75, &HB5, &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, &H70, &HB 0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H 55, &H95, &H94, &H54, &H9C, &H5C, &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99, &H59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8 B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, &H43, &H83, &H41, &H81, &H80, &H40)End Function2)窗体:FORM1,上面放置的控件如下:Begin VB.Form frmComCaption = "Form1"ClientHeight = 8235ClientLeft = 3885ClientTop = 2250ClientWidth = 6810LinkTopic = "Form1"ScaleHeight = 8235ScaleWidth = 6810Begin VB.TextBox txtReceive …注:放置接收上来的IB0数据Height = 495Left = 1200TabIndex = 2Top = 2280Width = 1335EndBegin mandButton Command1Caption = "读取IB0"Height = 495Left = 2760TabIndex = 1Top = 2280Width = 1695EndBegin mandButton cmdSDOCaption = "置位Q1.1"Height = 495Left = 2160TabIndex = 0Top = 3720Width = 1575EndBegin MSCommLib.MSComm ComK3Left = 480Top = 1080_ExtentX = 1005_ExtentY = 1005_Version = 393216DTREnable = -1 'TrueEndEnd① Form_Load事件,在此主要是实现了打开并初始化串口Private Sub Form_Load()With ComK3.CommPort = 1.Settings = "19200,N,8,1".InputMode = comInputModeBinary '二进制收发.InBufferSize = 512.OutBufferSize = 512If (Not .PortOpen) Then .PortOpen = TrueEnd WithEnd Sub② Form_UnLoad事件,在此主要是关闭串口Private Sub Form_Unload(Cancel As Integer)If (ComK3.PortOpen) ThenComK3.PortOpen = FalseEnd IfEnd Sub③“置位Q1.1”按钮单击事件'设置Q1.1为1Private Sub cmdSDO_Click()Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H5 '功能码btSend(2) = &H0 'Q1.1地址(0009)高字节btSend(3) = &H9 'Q1.1地址(0009)低字节btSend(4) = &HFF '强制值高字节btSend(5) = &H0 '强制值低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CVar(btSend)End Sub④“读取IB0”按钮单击事件'查表知I0.0的modbus地址为0000,从I0.0开始读取连续8位Private Sub Command1_Click()'发请求Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H2 '功能码btSend(2) = &H0 'I0.0地址(0000)高字节btSend(3) = &H0 'i0.0地址(0000)低字节btSend(4) = &H0 '读取个数高字节btSend(5) = &H8 '读取个数低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CVar(btSend)'注意下面编写的接收过程很简单,要编写实际应用的监控程序来说需要更完善 Dim btReceive As VariantWith ComK3DoDoEventsLoop Until .InBufferCount = 6.InputLen = 6btReceive = .InputIf btReceive(1) = &H2 Then '若正确,返回帧的第2个字节为功能码.实际上,此处应首先进行CRC校验txtReceive.Text = Hex$(btReceive(3))End IfEnd WithEnd Sub。

java对接modbus协议实例代码

java对接modbus协议实例代码

java对接modbus协议实例代码Modbus是一种串行通信协议,常用于工业自动化系统中。

在Java中,可以使用第三方库如`j2mod`或`Modbus4J`来实现Modbus协议的对接。

这里是一个使用`Modbus4J`的简单示例:首先,你需要添加Modbus4J的依赖到你的项目中。

如果你使用Maven,你可以添加以下依赖:```xml<dependency><groupId></groupId><artifactId>modbus4j</artifactId><version></version> <!--请检查是否有更新的版本--></dependency>```然后,以下是一个简单的Modbus客户端代码示例:```javaimport ;import ;import ;import ;import ;public class ModbusClient {public static void main(String[] args) {ModbusFactory factory = new ModbusFactory(); IpParameters params = new IpParameters();(""); //设置Modbus服务器IP地址(502); //设置端口号(1); //设置重试次数(1000); //设置超时时间(毫秒)(1); //设置从设备IDModbusMaster master = (params, true);();try {// 读取保持寄存器int registerAddress = 0x0000; //寄存器地址int numRegisters = 1; //寄存器数量ReadHoldingRegistersResponse response = (new ReadHoldingRegistersRequest(registerAddress, numRegisters));("Value: " + ());} catch (Exception e) {();} finally {(); // 关闭主站连接}}}```这是一个非常基础的Modbus客户端示例,仅用于读取一个保持寄存器的值。

易语言串口通讯modbus协议模块上位机必备例子源代码

易语言串口通讯modbus协议模块上位机必备例子源代码

易语言串口通讯modbus协议模块上位机必备例子源代码1.引言1.1 概述在编写易语言串口通讯modbus协议模块上位机必备例子源代码之前,我们首先需要了解一些基本概念和背景知识。

本文介绍了该例子的目的和结构,以及引言、正文和结论三个主要部分的内容。

1.1概述Modbus协议是一种常用的串行通信协议,广泛应用于工业自动化领域。

它被设计用于在不同设备之间进行数据传输和通信。

Modbus协议简洁明了,易于实现和部署,因此被许多工业设备和上位机所采用。

易语言是一种面向过程的编程语言,易于学习和使用。

它提供了丰富的库和模块,方便我们进行串口通讯编程。

易语言的特点是语法简单易懂,同时也支持调用其他语言编写的DLL函数,可以实现更加复杂的功能。

本例子的目标是演示如何使用易语言编写一个串口通讯的Modbus 协议模块,并结合上位机的必备功能来实现数据的读写和显示。

在正文部分,我们将介绍Modbus协议的简要概述,包括其通信方式、数据格式、功能码等。

同时,我们还将介绍易语言中的串口通讯模块及其基本用法。

在结论部分,我们将提供一些实例源代码示例,以便读者更好地理解和使用这个例子。

此外,我们还将列举一些上位机必备的功能,以供读者参考和扩展应用。

通过这个例子,读者可以学习到如何使用易语言进行串口通讯编程,并了解Modbus协议在实际应用中的运用。

同时,读者也可以根据自己的需求和实际情况,对例子进行二次开发和改进,以适应不同的应用场景。

在下一节中,我们将详细介绍Modbus协议的相关知识,以便读者更好地理解本例子的内容和实现。

文章结构部分主要是对整篇文章的组织和安排进行介绍,以下是1.2 文章结构的内容:1.2 文章结构本文主要分为三个部分,包括引言、正文和结论,具体如下:1. 引言部分介绍了本文的概述、文章结构和目的。

在概述中,我们对易语言串口通讯modbus协议模块上位机必备例子源代码进行了简要介绍,指出了本文的主要内容和目标。

Modbus协议51单片机C语言实现

Modbus协议51单片机C语言实现

#include <REGX52.H>#include<intrins.h>//_nop_();#define OSFREQ 11059200char TimeInterval;char MyAddress;char data DI[6]={1,2,3,4,5,6};char data DO[6]={6,7,8,9,10,11};char data AI[6]={11,12,13,14,15,16};char data AO[6]={16,17,18,19,20,21};unsigned char data ReceiveData[14];unsigned char data countnumber;sbit Recenable =P1^6;//控制端sbit led =P2^7;//控制端/*---------------------------------------------------------------------------函数说明:CRC 高位字节值表---------------------------------------------------------------------------*/ static unsigned char code auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40} ;/*---------------------------------------------------------------------------函数说明:CRC低位字节值表---------------------------------------------------------------------------*/ static unsigned char code auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,0x43, 0x83, 0x41, 0x81, 0x80, 0x40};/*---------------------------------------------------------------------------调用方式:unsigned int CRC16(unsigned char *puchMsg, unsigned int usDataLen) 函数说明:CRC校验---------------------------------------------------------------------------*/unsigned int CRC16(unsigned char *puchMsg, unsigned int usDataLen){unsigned char uchCRCHi = 0xFF ; // 高CRC字节初始化unsigned char uchCRCLo = 0xFF ; // 低CRC 字节初始化unsigned uIndex ; // CRC循环中的索引while (usDataLen--) // 传输消息缓冲区{uIndex = uchCRCHi ^ *puchMsg++ ; // 计算CRCuchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;uchCRCLo = auchCRCLo[uIndex] ;}return (uchCRCHi << 8 | uchCRCLo) ;}/*---------------------------------------------------------------------------调用方式:unsigned char getbit(unsigned int address,unsigned char function)函数说明:取出所给地址的位值---------------------------------------------------------------------------*/unsigned char getbit(unsigned int address,unsigned char function){unsigned char data Offset;unsigned char data temp;unsigned char data *Myaddress;Offset=(char)address&0x07;switch (function) //根据功能码不同进行相应处理{case 2:Myaddress=DI;break;case 1:Myaddress=DO;break;default:return 2;}temp=(char)(address>>3);temp=*(Myaddress+temp);temp>>=(Offset);if (temp&0x01)return 1;elsereturn 0;}/*---------------------------------------------------------------------------调用方式:void SendData(unsigned char *output,unsigned char Outlength) 函数说明:发送数据至窗口---------------------------------------------------------------------------*/void SendData(unsigned char *output,unsigned char Outlength){ES=0;while(Outlength--){TI=0;ACC=*output;TB8=P;SBUF=*(output++);while(!TI);TI=0;}ES=1;}/*---------------------------------------------------------------------------调用方式:void Function12(unsigned char address,unsigned char len)函数说明:功能码1,2处理---------------------------------------------------------------------------*/void Function12(unsigned char address,unsigned char len){unsigned int data i;unsigned char data j;unsigned char data length;unsigned char data *send;unsigned int data temp;unsigned char data function;length=0;send=ReceiveData;function=send[1];for (i=1;i<=len;i++){length++;*(send+2+length)=0;for (j=0;j<8;j++){*(send+2+length)=*(send+2+length)|getbit(address,function)<<j; address++;i++;if(i>len)break;}i--;}*(send+2)=length; //数据长度temp=CRC16(send,length+3); //DI状态数据*(send+3+length)=(char)(temp>>8); //CRC校验高*(send+4+length)=(char)temp; //CRC校验低SendData(send,length+5); //调用A发送程序}/*---------------------------------------------------------------------------调用方式:void Function3(unsigned char address,unsigned char len) 函数说明:功能码3处理-----读取寄存器---------------------------------------------------------------------------*/void Function3(unsigned char address,unsigned char len){unsigned char data i;unsigned char data *send;unsigned int data temp;send=ReceiveData;*(send+2)=2*len; //数据长度高address=2*address;for(i=0;i<len;i++) //取输入寄存器数据{*(send+3+2*i)=AO[address++];*(send+4+2*i)=AO[address++];}temp=CRC16(send,2*len+3); //CRC校验*(send+3+2*len)=(char)(temp>>8);*(send+4+2*len)=(char)temp;SendData(send,2*len+5); //调用A发送程序}/*---------------------------------------------------------------------------调用方式:void Function4(unsigned char address,unsigned char len) 函数说明:功能码处理4----读取输入寄存器---------------------------------------------------------------------------*/void Function4(unsigned char address,unsigned char len){unsigned char data i;unsigned char data *send;unsigned int data temp;send=ReceiveData;*(send+2)=2*len;address=2*address;for(i=0;i<len;i++) //取数据{*(send+4+2*i)=AI[address++];*(send+3+2*i)=AI[address++];}temp=CRC16(send,2*len+3);*(send+3+2*len)=(char)(temp>>8);*(send+4+2*len)=(char)temp;SendData(send,2*len+5);}/*---------------------------------------------------------------------------调用方式:void Function6(unsigned char address)函数说明:写单路寄存器---------------------------------------------------------------------------*/void Function6(unsigned char address){int temp;unsigned char data *WriteData;temp=2*address;WriteData=AO;//将写入的数据进行处理//your code to add here to deal with the write value*(WriteData+temp)=ReceiveData[4];*(WriteData+temp+1)=ReceiveData[5];SendData(ReceiveData,countnumber); //调用发送程序,返回与主机相同的报文}/*---------------------------------------------------------------------------调用方式:void SendError(char ErrorCode)函数说明:---------------------------------------------------------------------------*/void SendError(char ErrorCode){unsigned char data *send;unsigned int data temp;send=ReceiveData;*(send+1)=ReceiveData[1]|0x01;//最高位置1*(send+2)=ErrorCode;temp=CRC16(send,3);*(send+3)=(char)(temp>>8);*(send+4)=(char)temp;SendData(send,countnumber); //调用发送程序,返回错误代码}/*---------------------------------------------------------------------------调用方式:void Deal()函数说明:接收数据处理---------------------------------------------------------------------------*/void Deal(){unsigned int data temp;unsigned char data address;unsigned char data length;unsigned char data counter;unsigned char data *Pointer;Pointer=ReceiveData;counter=countnumber;if (counter<=3 ) return;temp=Pointer[counter-2]<<8;temp= temp|Pointer[counter-1];if( temp==CRC16(Pointer,counter-2)) //较验正确{address=Pointer[3];length=Pointer[5];if(address<48){switch (Pointer[1]) //根据功能码不同进行相应处理*/{case 1:Function12(address,length);break;case 2:Function12(address,length);break;case 3:address=address-1;Function3(address,length);break;case 4:address=address-1;Function4(address,length);break;case 6:address=address-1;Function6(address);default:SendError(0x81);break;}}else{ SendError(0x82);}}countnumber=0;}/*bit Chargetbit(unsigned char character,unsigned char Number){if(character>>Number&0x01==1)return 1;elsereturn 0;}//设定某一位的值*********************************************************** unsigned char SetBit(unsigned char Character,unsigned char num,bit boolen){unsigned char code bit_value[]={1,2,4,8,16,32,64,128};if(boolen)return Character|bit_value[num];elsereturn Character&~bit_value[num];}*//*---------------------------------------------------------------------------调用方式:void Init_timer2(unsigned int baudrate)函数说明:定时器2的初始化---------------------------------------------------------------------------*/void Init_timer2(unsigned int baudrate){unsigned int data TimReg2;T2CON = 0x00;T2MOD = 0x00;TimReg2=65536-(OSFREQ/384/baudrate*11);RCAP2L=TimReg2&0x00ff;RCAP2H=(TimReg2>8); //RCAP2H=TimReg2/256RCAP2L=0;RCAP2H=0;TL2 = RCAP2L; //TH2 = RCAP2H; //TR2=1; // T2CON.2 start timerET2=0; // 开定时器2中断}/*---------------------------------------------------------------------------调用方式:void Init_SerialPort(unsigned int baudrate)函数说明:串口初始化---------------------------------------------------------------------------*/void Init_SerialPort(unsigned int baudrate){unsigned char TimReg2;SCON = 0xd0; // 方式3, 8-bit UART, enable rcvrTMOD = 0x21; // T0方式1(16位), T1方式2,8位重装TimReg2=256-(OSFREQ/384/baudrate);TH1 = TimReg2; // 定时器1,在11.0592MHz下,波特率为9600 TL1 = TH1;TR1= 1; // TR1: 定时开始//PS=1; // 串行中断优先ES=1; // 接收中断}/*---------------------------------------------------------------------------函数说明:主函数---------------------------------------------------------------------------*/main(){EA=1; //开总中断Init_SerialPort(9600);Init_timer2(9600);Recenable=0; //接收允许MyAddress=0x01; //本机地址while(1){}}/*---------------------------------------------------------------------------调用方式:void SeiralA() interrupt 4 using 0函数说明:通讯中断---------------------------------------------------------------------------*/void SeiralA() interrupt 4 using 0{if(RI){if((TimeInterval>2)&&(TimeInterval<=4)){ countnumber=0;}if(countnumber>60){ countnumber=0;}ReceiveData[countnumber++]=SBUF; //将接收到的数据到缓冲区内TimeInterval=0;RI=0;ET2=1; //当接收到数据后,将定时器2开启}}/*---------------------------------------------------------------------------调用方式:void SerialPortTime() interrupt 5 using 0函数说明:定时器2中断程序---------------------------------------------------------------------------*/void SerialPortTime() interrupt 5 using 0{ET2=0; //定时器2中断允许控制TimeInterval=TimeInterval+1;if((TimeInterval>4) && countnumber){Recenable=1; //发送Deal(); //将接收到的数据进行处理Recenable=0; //接收countnumber=0;}else{ ET2=1;} //将定时器2打开TF2=0; //定时器2溢出标志,软件清0}。

modbus编程实例c

modbus编程实例c

modbus编程实例c以下是一个使用C语言实现Modbus RTU协议的示例代码:```c#include < stdio.h>#include < stdlib.h>#include < string.h>#include < unistd.h>#include < fcntl.h>#include < termios.h>int main(){int status;struct termios options;char buf[1024];int n;// 设置终端选项status = fcntl(fileno(stdin), F_SETFL, 0);if (status == -1) {printf("fcntl error\n");return 1;}status = fcntl(fileno(stdout), F_SETFL, 0);if (status == -1) {printf("fcntl error\n");return 1;}tcgetattr(fileno(stdin), &options);options.c_cflag |= (CLOCAL | CREAD);options.c_cflag &= ~PARENB;options.c_cflag &= ~CSTOPB;options.c_cflag &= ~CSIZE;options.c_cflag |= CS8;tcsetattr(fileno(stdin), TCSANOW, &options);// 从标准输入读取数据n = read(fileno(stdin), buf, sizeof(buf));if (n < 0) {printf("read error\n");return 1;}// 处理数据printf("Received: %s\n", buf);return 0;}```你可以根据实际情况修改代码中的设备名称和波特率。

MODBUS_源代码_内含CRC算法

MODBUS_源代码_内含CRC算法

MODBUS 源代码内含CRC算法.#include "system.h"#include "math.h"unsigned int BUFF[1900];unsigned char OUTBUFF[452];//MODBUS主站状态u8 modbusSta2;//WAIT READY NOREPLAY extern u8 runflage;extern u16 constant0;extern u16 constant1;extern u16 runlightime;extern u16 slaverOutputtimeup; extern u8 RTDELAY,X2;long IOmod1;long IOmod2;long IOmod3;long IOmod1_o;long IOmod2_o;long IOmod3_o;u8 check_adr_1(void);void check_fun_1(void);void fun1s_1(void);void fun2s_1(void);void fun3s_1(void);void fun5s_1(void);void fun22s_1(void);void fun23s_1(void);void fun0s_1(void);void SlaveAnswer_1(u8 adr,u8 fun); void message_out_1(void);u8 check_adr_2(void);void check_fun_2(void);void fun0s_2(void);void fun1s_2(void);void fun2s_2(void);void fun3s_2(void);void fun5s_2(void);void fun22s_2(void);void fun23s_2(void);void fun1m_2(void);void fun22m_2(void);void fun5m_2(void);void fun3m_2(void);//void fun0s_2(void);void SlaveAnswer_2(u8 adr,u8 fun);void message_out_2(void);void SETremote(u8 out,u8 temp1,u8 temp2,u8 temp3);void testComm(void);void IO_rewrite(u8 N0);tagmodbuserror modbuserror;u16 errorcode;u16 a1,a2,a3,a4,failask;u8 commSTA;u8 remotein[4][3];u8 noreplayNu;//主机等待信息u8 funadr[3][3];//[i][0]是从机地址,[i][1]是从机映射到主控的开始地址(如果是自己设备就是24*(i+1))u8 funadr_[3][2];//[i][0]是从机读取开始地址,[i][1]是读取长度u8 funlongth;//写入长度struct messageS{unsigned char buffer[180];unsigned char counter;} messageRe_2,messageOut_2,messageRe_1,messageOut_1;u8 DataInRam_hi[64];u8 DataInRam_lo[64];unsigned int in_re=0,out_re;unsigned char OutReady2=0;unsigned char OutReady1=0;unsigned char *p;//*************************crc校验码生成**********************************/CRC16()*********************************************static unsigned char auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40} ;static char auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,0x40} ;unsigned short CRC16_2(puchMsg, usDataLen)unsigned char *puchMsg ; /* message to calculate CRC upon */unsigned short usDataLen ; /* quantity of bytes in message */{unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */unsigned uIndex ; /* will index into CRC lookup table */while (usDataLen--){uIndex = uchCRCHi ^ *puchMsg++ ;uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;uchCRCLo = auchCRCLo[uIndex] ;}return (uchCRCHi << 8 | uchCRCLo) ;}unsigned short CRC16_1(puchMsg, usDataLen)unsigned char *puchMsg ;unsigned short usDataLen ;{unsigned char uchCRCHi = 0xFF ;unsigned char uchCRCLo = 0xFF ;unsigned uIndex ;while (usDataLen--){uIndex = uchCRCHi ^ *puchMsg++ ;uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;uchCRCLo = auchCRCLo[uIndex] ;}return (uchCRCHi << 8 | uchCRCLo) ;}//****************************uart1处理原始一帧数据********************************************void pretreat_message_1(void){unsigned char *p;if(check_adr_1()){p=messageRe_1.buffer;in_re=CRC16_1(p,messageRe_1.counter-2);unsigned int co_re;co_re=messageRe_1.buffer[messageRe_1.counter-2]*256+messageRe_1.buffer[messa geRe_1.counter-1];if(co_re==in_re){check_fun_1();}}messageRe_1.counter=0;}//*****************功能码分析(处理messageRe_1)***************************//地址判断u8 check_adr_1(void){if( messageRe_1.buffer[0]==UART1adr|| messageRe_1.buffer[0]==255) //公共地址为255return 1;elsereturn 0;}//功能码判断void check_fun_1(void){switch (messageRe_1.buffer[1]){case 0: fun0s_1();break;case 1: fun1s_1();break;case 2: fun2s_1();break;case 3: fun3s_1();break;case 4: break;case 5: fun5s_1(); break;case 22: fun22s_1(); break;//自定义功能1功能,固定格式case 23: fun23s_1(); break;//自定义功能5功能,无回答default: break;}slaverOutputtimeup=0;}//功能实现void fun2s_1(void){u8 start,longth;u8 outNu1,i;start=messageRe_1.buffer[2]*256+messageRe_1.buffer[3];longth=messageRe_1.buffer[4]*256+messageRe_1.buffer[5];outNu1=longth/8;//个数messageOut_1.buffer[2]=outNu1+1;for(i=3;i<=18;i++){messageOut_1.buffer[i]=0;}switch(outNu1+1){case 1:for(i=0;i<longth;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}case 2:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<longth-16;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}case 3:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<longth-24;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}case 4:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<longth-32;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}case 5:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<longth-40;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}case 6:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<longth-48;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}case 7:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] |(OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<longth-56;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}case 8:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<longth-64;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}case 9:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<longth-72;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}case 10:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}for(i=0;i<longth-80;i++){messageOut_1.buffer[12]=messageOut_1.buffer[12] | (OUTBUFF[362+start+i]<<i);}case 11:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[12]=messageOut_1.buffer[12] | (OUTBUFF[362+start+i]<<i);}for(i=0;i<longth-88;i++){messageOut_1.buffer[13]=messageOut_1.buffer[13] | (OUTBUFF[370+start+i]<<i);}case 12:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[12]=messageOut_1.buffer[12] | (OUTBUFF[362+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[13]=messageOut_1.buffer[13] | (OUTBUFF[370+start+i]<<i);}for(i=0;i<longth-96;i++){messageOut_1.buffer[14]=messageOut_1.buffer[14] | (OUTBUFF[378+start+i]<<i);}case 13:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[12]=messageOut_1.buffer[12] | (OUTBUFF[362+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[13]=messageOut_1.buffer[13] | (OUTBUFF[370+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[14]=messageOut_1.buffer[14] | (OUTBUFF[378+start+i]<<i);for(i=0;i<longth-104;i++){messageOut_1.buffer[15]=messageOut_1.buffer[15] | (OUTBUFF[386+start+i]<<i);}case 14:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[12]=messageOut_1.buffer[12] |}for(i=0;i<8;i++){messageOut_1.buffer[13]=messageOut_1.buffer[13] | (OUTBUFF[370+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[14]=messageOut_1.buffer[14] | (OUTBUFF[378+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[15]=messageOut_1.buffer[15] | (OUTBUFF[386+start+i]<<i);}for(i=0;i<longth-112;i++){messageOut_1.buffer[16]=messageOut_1.buffer[16] | (OUTBUFF[394+start+i]<<i);}case 15:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] |}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[12]=messageOut_1.buffer[12] | (OUTBUFF[362+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[13]=messageOut_1.buffer[13] | (OUTBUFF[370+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[14]=messageOut_1.buffer[14] | (OUTBUFF[378+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[15]=messageOut_1.buffer[15] | (OUTBUFF[386+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[16]=messageOut_1.buffer[16] | (OUTBUFF[394+start+i]<<i);}for(i=0;i<longth-8;i++){messageOut_1.buffer[17]=messageOut_1.buffer[17] | (OUTBUFF[402+start+i]<<i);}case 16:for(i=0;i<120;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] |}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[12]=messageOut_1.buffer[12] | (OUTBUFF[362+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[13]=messageOut_1.buffer[13] | (OUTBUFF[370+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[14]=messageOut_1.buffer[14] | (OUTBUFF[378+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[15]=messageOut_1.buffer[15] | (OUTBUFF[386+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[16]=messageOut_1.buffer[16] |}for(i=0;i<8;i++){messageOut_1.buffer[17]=messageOut_1.buffer[17] | (OUTBUFF[402+start+i]<<i);}for(i=0;i<longth-120;i++){messageOut_1.buffer[18]=messageOut_1.buffer[18] | (OUTBUFF[410+start+i]<<i);}}messageOut_1.counter=outNu1+3;SlaveAnswer_1(UART1adr,0x02);}void fun1s_1(void){u8 start,longth;u8 outNu1,i;start=messageRe_1.buffer[2]*256+messageRe_1.buffer[3];longth=messageRe_1.buffer[4]*256+messageRe_1.buffer[5];outNu1=longth/8;//个数messageOut_1.buffer[2]=outNu1+1;for(i=3;i<=18;i++){messageOut_1.buffer[i]=0;}switch(outNu1+1){case 1:for(i=0;i<longth;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}case 2:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<longth-16;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}case 3:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<longth-24;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}case 4:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<longth-32;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}case 5:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<longth-40;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}case 6:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] |(OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<longth-48;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}case 7:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<longth-56;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}case 8:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<longth-64;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}case 9:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[6]=messageOut_1.buffer[6] | (OUTBUFF[314+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[7]=messageOut_1.buffer[7] | (OUTBUFF[322+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[8]=messageOut_1.buffer[8] | (OUTBUFF[330+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[9]=messageOut_1.buffer[9] | (OUTBUFF[338+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[10]=messageOut_1.buffer[10] | (OUTBUFF[346+start+i]<<i);}for(i=0;i<longth-72;i++){messageOut_1.buffer[11]=messageOut_1.buffer[11] | (OUTBUFF[354+start+i]<<i);}case 10:for(i=0;i<8;i++){messageOut_1.buffer[3]=messageOut_1.buffer[3] | (OUTBUFF[290+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[4]=messageOut_1.buffer[4] | (OUTBUFF[298+start+i]<<i);}for(i=0;i<8;i++){messageOut_1.buffer[5]=messageOut_1.buffer[5] | (OUTBUFF[306+start+i]<<i);。

C语言编写modbus协议

C语言编写modbus协议

modbus.c#include"main.h"//字地址0-255(只取低8位)//0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40};/*CRC低位字节值表*/constuint8codeauchCRCLo[]={0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06, 0x07,0xC7,0x05,0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26, 0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60, 0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67, 0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68, 0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E, 0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5, 0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,};uint16testRegister;//用于测试字址址16uint8localAddr=1;//单片机控制板的地址uint8sendCount;//发送字节个数uint8receCount;//接收到的字节个数uint8sendPosi;//发送位置uint16crc16(uint8*puchMsg,uint16usDataLen) {uint8uchCRCHi=0xFF;/*高CRC字节初始化*/{}}//uint16crc16(uint8*puchMsg,uint16usDataLen) //开始发送voidbeginSend(void){b485Send=1;//设为发送sendPosi=0;if(sendCount>1) sendCount--;//{uint8byteCount;uint8bitCount;uint16crcData;uint8position;uint8i,k;uint8result;uint16tempData;uint8exit=0;for(k=0;k<byteCount;k++) {//字节位置position=k+3;sendBuf[position]=0;for(i=0;i<8;i++){getCoilVal(tempAddr,&tempData); sendBuf[position]|=tempData<<i;{//}}break;}sendBuf[0]=localAddr;sendBuf[1]=0x01;sendBuf[2]=byteCount;byteCount+=3;crcData=crc16(sendBuf,byteCount); sendBuf[byteCount]=crcData>>8;/{uint8tempAddr;uint16result;uint16crcData;uint8readCount;uint8byteCount;uint8finsh;//1完成0出错uint16i;uint16tempData=0;{getRegisterVal(tempAddr,&tempData); sendBuf[i+3]=tempData>>8; sendBuf[i+4]=tempData&0xff;}sendBuf[0]=localAddr; sendBuf[1]=3; sendBuf[2]=byteCount; byteCount+=3;//{uint8addr;uint8tempAddr;uint16tempData;uint8onOff;uint8i;//addr=(receBuf[2]<<8)+receBuf[3]; //tempAddr=addr&0xfff;{//}//elseif(onOff==0x0000)elseif(onOff==0x00){//设为OFFtempData=0;}setCoilVal(tempAddr,tempData); for(i=0;i<receCount;i++){}//{uint8tempAddr;uint8byteCount;uint8setCount;uint16crcData;uint16tempData;uint8finsh;//为1时完成为0时出错uint8i;//addr=(receBuf[2]<<8)+receBuf[3];{setRegisterVal(tempAddr,tempData); }sendBuf[0]=localAddr;sendBuf[1]=16;sendBuf[2]=addr>>8; sendBuf[3]=addr&0xff; sendBuf[4]=setCount>>8; sendBuf[5]=setCount&0xff;//{uint16crcData;uint16tempData;if(receCount>4){switch(receBuf[1]){case1://读取线圈状态(读取点16位以内) case3://读取保持寄存器(一个或多个){////{{//校验正确if(receBuf[1]==1){//读取线圈状态(读取点16位以内) readCoil();elseif(receBuf[1]==3){//读取保持寄存器(一个或多个) readRegisters();}{//}{}}}receCount=0; checkoutError=0;break;case15://设置多个线圈tempData=receBuf[6];{{{}}receCount=0; checkoutError=0;break;case16://设置多个寄存器tempData=(receBuf[4]<<8)+receBuf[5];{{{presetMultipleRegisters();}}receCount=0;checkoutError=0;}break;default:}}//{tempAddr=addr&0xfff; //只取低8位地址switch(tempAddr&0xff) {break;case1:*tempData=testCoil;case6:break;case7:break;break; case9: break;break; case15: break; case16:break; default: break; }//{{case0: break; case1:testCoil=tempData; break;case2:break;break;case8:break;case9:break; case10: break; case11:case16: break; default: break;}returnresult;}//uint16setCoilVal(uint16addr,uint16data) //取寄存器值返回0表示成功{{case1:break;case2:break;break; case4: break;break; case10: break; case11:case12:break;case13:break;}returnresult;}//uint16getRegisterVal(uint16addr,uint16&data)//设置寄存器值返回0表示成功uint16setRegisterVal(uint16addr,uint16tempData) {uint16result=0;{break;case3:break;case4:break; case5: break; case6:case11: break; case12: break;case13:break;case14:break;}//uint8setRegisterVal(uint16addr,uint16data)仅供个人学习参考。

modbus驱动源代码

modbus驱动源代码

MODBUS驱动源程序,如有需要或者项目外包请联系qq:942922109 // ---------------------------------------------------------------------// ---------------------------------------------------------------------#if 1void MenuDisplayNum000(uint i){//uint i;//i = DispDataNum;shownum[0] = i/10000;shownum[1] = i/1000%10;shownum[2] = i/100%10;shownum[3] = i/10%10;shownum[4] = i%10;for(i =0; i < 4; i++) //高位0不显示{if(shownum[i] == 0){shownum[i] = NoDispNum;}else{break;}}bDisp = dTrue; //*/}#endif// ---------------------------------------------------------------------// ---------------------------------------------------------------------void RS232CheckRXDataDeal(void){unsigned int m,kk,jj;unsigned char *pt;unsigned char i,k;unsigned char x,y;unsigned char temp;unsigned char Fun_Code,Date_Len;if(bDataChange == dTrue) //串口2交换数据到串口1{temp = RxdLen;pt=&RxRs232DataZone[0];m=comp_crc16(pt,temp);i=(m/256);k=(m);x = RxRs232DataZone[temp];y = RxRs232DataZone[temp+1];if ((i!=x)||(k!=y)){return;}for(i = 0; i < RxdLen; i++){TxRs232DataZone2[i] = RxRs232DataZone[i];}LenTXD2 = RxdLen;RxdLen = 0;bTXCodeFlag2 = dTrue;bDataChange = dFalse;return;}Fun_Code = RxRs232DataZone[1];if((bWatchReciveReadData == dTrue)&&(Fun_Code == 3)) {Date_Len = RxRs232DataZone[2];Para_H = RxRs232DataZone[3];Para_L = RxRs232DataZone[4];temp = Date_Len + 3;pt=&RxRs232DataZone[0];m=comp_crc16(pt,temp);i=(m/256);k=(m);x = RxRs232DataZone[temp];y = RxRs232DataZone[temp+1];if ((i!=x)||(k!=y)){return;}if(Add_H == 0x21) //0x21群组{if(Add_L == 4) //amp{MainDisplayId_Amp = (Para_H<<8)|Para_L;bWatchReciveReadData = dFalse;}else if(Add_L == 5) //dc vol{MainDisplayId_DcV ol = (Para_H<<8)|Para_L;bWatchReciveReadData = dFalse;}else if(Add_L == 6) //out vol{MainDisplayId_OutV ol = (Para_H<<8)|Para_L;bWatchReciveReadData = dFalse;}else if(Add_L == 2) //fre{MenuMainNum = (Para_H<<8)|Para_L;bWatchReciveReadData = dFalse;}}return;}if(Fun_Code == 3){Date_Len = RxRs232DataZone[2];Para_H = RxRs232DataZone[3];Para_L = RxRs232DataZone[4];temp = Date_Len + 3;pt=&RxRs232DataZone[0];m=comp_crc16(pt,temp);i=(m/256);k=(m);x = RxRs232DataZone[temp];y = RxRs232DataZone[temp+1];if ((i!=x)||(k!=y)){return;}m = (Add_H*100) + Add_L+20000; //参数任务号/*debugbTXCodeFlag = dTrue;LenTXD = 8;TxRs232DataZone[0] = 0xff;TxRs232DataZone[1] = Add_H;TxRs232DataZone[2] = Add_L;TxRs232DataZone[3] = MeunTaskID>>8;TxRs232DataZone[4] = MeunTaskID;TxRs232DataZone[5] = m>>8;TxRs232DataZone[6] = m;TxRs232DataZone[7] = 0xff;//*/if(bMotoStop){dRXD_motostopDeal(m);}else if(bMotoRun){dRXD_motorunDeal(m);}else if(bMotoJog){dRXD_motojopDeal(m);}else{dRXD0000Deal(m);}}else if(Fun_Code == 6) //write{Rx_Write_Addr_H = RxRs232DataZone[2];Rx_Write_Addr_L = RxRs232DataZone[3];Rx_Write_Dat_H = RxRs232DataZone[4];Rx_Write_Dat_L = RxRs232DataZone[5];temp = 6;pt=&RxRs232DataZone[0];m=comp_crc16(pt,temp);i=(m/256);k=(m);x = RxRs232DataZone[temp];y = RxRs232DataZone[temp+1];if ((i!=x)||(k!=y)){return;}/*if((bWaitAdjust == dTrue)&&(Rx_Write_Addr_H == Wait_Write_Addr_H)&&(Rx_Write_Addr_L == Wait_Write_Addr_L)) //*/if(bWaitAdjust == dTrue){kk = (uint)(Rx_Write_Dat_H);MenuMainNum = (kk<<8)|Rx_Write_Dat_L;jj = MenuMainNum;shownum[0] = jj/10000;shownum[1] = jj/1000%10;shownum[2] = jj/100%10;shownum[3] = jj/10%10;shownum[4] = jj%10;// bpoint[2] = dTrue;for(i =0; i < 4; i++){if(shownum[i] == 0){shownum[i] = NoDispNum;}else{break;}}bDisp = dTrue;bWaitAdjust = dFalse;}if((bWaitReciveWriteData == dTrue)&&(Rx_Write_Addr_H == Wait_Write_Addr_H)&&(Rx_Write_Addr_L == Wait_Write_Addr_L)){if((Rx_Write_Addr_H == 1)&&(Rx_Write_Addr_L == 0)) //设定01-00后,更新主菜单显示内容{kk = (uint)(Rx_Write_Dat_H);MenuMainNum = (kk<<8)|Rx_Write_Dat_L;}bWaitReciveWriteData = dFalse;shownum[0] = DispNum__; //shownum[1] = DispNum_E; //shownum[2] = DispNum_N; //-shownum[3] = DispNum_D; //0shownum[4] = DispNum__; //0bDispLimitTime = dTrue;bDisp = dTrue;}}}void RS232CheckRXDataDeal2(void){unsigned int m,kk,jj;unsigned char *pt;unsigned char i,k;unsigned char x,y;unsigned char temp;unsigned char Fun_Code,Date_Len;temp = RxdLen2;pt=&RxRs232DataZone2[0];m=comp_crc16(pt,temp);i=(m/256);k=(m);x = RxRs232DataZone2[temp];y = RxRs232DataZone2[temp+1];if ((i!=x)||(k!=y)){return;}for(i = 0; i < RxdLen2; i++){TxRs232DataZone[i] = RxRs232DataZone2[i];}LenTXD = RxdLen2;RxdLen2 = 0;bTXCodeFlag = dTrue;bDataChange = dTrue;CountDataChange = 0;}// ---------------------------------------------------------------------/*void RS232_DelayLoad(void){bDelaySendCode = dFalse;OperationTimeLimitCount = dTimeLimitCount10MS;bOperationTimeOverFlag=dFalse;bOperationTimeLimitFlag=dTrue;bWaitLoadSendDataFlag = dTrue;}//*/// ---------------------------------------------------------------------void RS232ReadCmd(unsigned char DdeviceAdd,unsigned char StartAddr_H,unsigned char StartAddr_L,unsigned char ReadLen_H,unsigned char ReadLen_L){unsigned char *j;unsigned int m;TxRs232DataZone[0]=DdeviceAdd;TxRs232DataZone[1]=3;TxRs232DataZone[2]=StartAddr_H;TxRs232DataZone[3]=StartAddr_L;TxRs232DataZone[4]=ReadLen_H;TxRs232DataZone[5]=ReadLen_L;Add_H = StartAddr_H;Add_L = StartAddr_L;j=&TxRs232DataZone[0];m = comp_crc16(j,6);TxRs232DataZone[6]=(m/256);TxRs232DataZone[7]=(m);bTXCodeFlag = dTrue;}// ---------------------------------------------------------------------// ---------------------------------------------------------------------// ---------------------------------------------------------------------void RS232WriteCmd(unsigned char DdeviceAdd,unsigned char StartAddr_H,unsigned char StartAddr_L,unsigned char WriteData_H,unsigned char WriteData_L){unsigned char *j;unsigned int m;TxRs232DataZone[0]=DdeviceAdd;TxRs232DataZone[1]=6;TxRs232DataZone[2]=StartAddr_H;TxRs232DataZone[3]=StartAddr_L;TxRs232DataZone[4]=WriteData_H;TxRs232DataZone[5]=WriteData_L;Add_H = StartAddr_H;Add_L = StartAddr_L;j=&TxRs232DataZone[0];m = comp_crc16(j,6);TxRs232DataZone[6]=(m/256);TxRs232DataZone[7]=(m);bTXCodeFlag = dTrue;}// ---------------------------------------------------------------------// ---------------------------------------------------------------------void RS232TXStart(void){unsigned char i;if((bRXingCodeFlag == dTrue)||(bTXingCodeFlag == dTrue)) return;RS485Control = 1;bTXingCodeFlag=dTrue; //避免TXing时Load// RS232TxByteCount=0;//LED1 ^= 1;for(i=0;i<LenTXD;i++){Udatas(TxRs232DataZone[i]);}LenTXD = 0;RS485Control = 0;bTXingCodeFlag = dFalse;}// ---------------------------------------------------------------------// ---------------------------------------------------------------------void RS232TXStart2(void){unsigned char i;if((bRXingCodeFlag2 == dTrue)||(bTXingCodeFlag2 == dTrue)) return;RS485Control2 = 1;bTXingCodeFlag2=dTrue; //避免TXing时Loadfor(i=0;i<LenTXD2;i++){Udatas2(TxRs232DataZone2[i]);}LenTXD2 = 0;RS485Control2 = 0;bTXingCodeFlag2 = dFalse;}// ---------------------------------------------------------------------void dMenuMainDeal(void){uchar i,j;if(KeyValue == KeyENT) //{shownum[0] = 0; //shownum[1] = 0; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum;shownum[4] = NoDispNum;bDisp = dTrue;MeunTaskID = dMenu00xx;}else if(KeyValue == KeyCycle) //{if(++MainDisplayId > 4){MainDisplayId = 0;}if(MainDisplayId ==0){if(IsDisplayOutAmp == 0){MainDisplayId = 1;}else{MenuDisplayNum000(MainDisplayId_Amp);}}if(MainDisplayId ==1){if(IsDisplayOutV ol == 0){MainDisplayId = 2;}else{MenuDisplayNum000(MainDisplayId_OutVol);}}if(MainDisplayId ==2){if(IsDisplayDcV ol == 0){MainDisplayId = 3;}else{MenuDisplayNum000(MainDisplayId_DcV ol);}}if(MainDisplayId ==3){if(IsDisplayUseSet1 == 0){MainDisplayId = 4;}else{MenuDisplayNum000(MainDisplayId_UseSet1);}}if(MainDisplayId ==4){if(IsDisplayUseSet2 == 1){MenuDisplayNum000(MainDisplayId_UseSet2);}}}else if(KeyValue == KeyUp){if(MenuMainNum < 60000){MenuMainNum++;j = (uchar)(MenuMainNum);i = (uchar)(MenuMainNum>>8);LenTXD = 8;RS232WriteCmd(0xff,0x20,1,i,j);//RS232WriteCmd(0xff,1,0,i,j);bWaitAdjust = dTrue;}}else if(KeyValue == KeyDown){if(MenuMainNum > 0){MenuMainNum--;//MenuMainNum = 60000;j = (uchar)(MenuMainNum);i = (uchar)(MenuMainNum>>8);LenTXD = 8;RS232WriteCmd(0xff,0x20,1,i,j);//RS232WriteCmd(0xff,1,0,i,j);bWaitAdjust = dTrue;}}}void dMenuxxDeal(unsigned char addr){if(KeyValue == KeyCycle){shownum[0] = DispNum__; //shownum[1] = DispNum__; //shownum[2] = DispNum__; //-shownum[3] = DispNum__;shownum[4] = DispNum__;RS232ReadCmd(0xff,10,0,0,1);bDisp = dTrue;MeunTaskID = dMenuMain;}else if(KeyValue == KeyUp){if(addr < 12){addr++;MeunTaskID ++;}else{addr = 0;MeunTaskID = dMenu00xx;}shownum[0] = addr/10; //shownum[1] = addr%10; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum; //0shownum[4] = NoDispNum; //0bDisp = dTrue;}else if(KeyValue == KeyDown){if(addr > 0){addr--;MeunTaskID --;}else{addr = 12;MeunTaskID = dMenu12xx;}shownum[0] = addr/10; //shownum[1] = addr%10; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum; //0shownum[4] = NoDispNum; //0bDisp = dTrue;}else if(KeyValue == KeyENT){shownum[0] = addr/10; //shownum[1] = addr%10; //shownum[2] = DispNum__; //-shownum[3] = 0; //0shownum[4] = 0; //0bDisp = dTrue;//MeunTaskID = addr*100;if(addr == 0) {MeunTaskID = addr*100;}else if(addr == 1) {MeunTaskID = dMenu1200;}else {MeunTaskID = (addr - 1)*100;}}}//---------------------------------------------void dMenuDeal(unsigned char Addr,unsigned char Menu) //xx-00{if(KeyValue == KeyCycle){shownum[0] = 0; //shownum[1] = 0; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum;shownum[4] = NoDispNum;bDisp = dTrue;MeunTaskID = dMenu00xx;}else if(KeyValue == KeyUp){//if((MeunTaskID >= dMenu0000)&&(MeunTaskID <= dMenu0050))if(MeunTaskID <= dMenu0050){if(Addr < 50){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0000;Addr = 0;}}else if((MeunTaskID >= dMenu0100)&&(MeunTaskID <= dMenu0146)) {if(Addr < 46){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0100;Addr = 0;}}else if((MeunTaskID >= dMenu0200)&&(MeunTaskID <= dMenu0258)) {if(Addr < 48){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0200;Addr = 0;}}else if((MeunTaskID >= dMenu0300)&&(MeunTaskID <= dMenu0374)) {if(Addr < 74){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0300;Addr = 0;}}else if((MeunTaskID >= dMenu0400)&&(MeunTaskID <= dMenu0444)) {if(Addr < 44){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0400;Addr = 0;}}else if((MeunTaskID >= dMenu0500)&&(MeunTaskID <= dMenu0543)) {if(Addr < 43){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0500;Addr = 0;}}else if((MeunTaskID >= dMenu0600)&&(MeunTaskID <= dMenu0673)) {if(Addr < 73){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0600;Addr = 0;}}else if((MeunTaskID >= dMenu0700)&&(MeunTaskID <= dMenu0733)) {if(Addr < 33){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0700;Addr = 0;}}else if((MeunTaskID >= dMenu0800)&&(MeunTaskID <= dMenu0823)) {if(Addr < 23){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0800;Addr = 0;}}else if((MeunTaskID >= dMenu0900)&&(MeunTaskID <= dMenu0992)){if(Addr < 46){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu0900;Addr = 0;}}else if((MeunTaskID >= dMenu1000)&&(MeunTaskID <= dMenu1043)){if(Addr < 43){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu1000;Addr = 0;}}else if((MeunTaskID >= dMenu1100)&&(MeunTaskID <= dMenu1145)){if(Addr < 45){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu1100;Addr = 0;}}else if((MeunTaskID >= dMenu1200)&&(MeunTaskID <= dMenu1202)) //特殊--后加{if(Addr < 2){Addr++;MeunTaskID ++;}else{MeunTaskID = dMenu1200;Addr = 0;}}shownum[0] = Menu/10; //shownum[1] = Menu%10; //shownum[2] = DispNum__; //-shownum[3] = Addr/10; //0shownum[4] = Addr%10; //0bDisp = dTrue;}else if(KeyValue == KeyDown){if(Addr > 0){Addr--;MeunTaskID --;}else{if(MeunTaskID <= dMenu0050){Addr = 50;MeunTaskID = dMenu0050;}else if((MeunTaskID >= dMenu0100)&&(MeunTaskID <= dMenu0146)){Addr = 46;MeunTaskID = dMenu0146;}else if((MeunTaskID >= dMenu0200)&&(MeunTaskID <= dMenu0258)){Addr = 58;MeunTaskID = dMenu0258;}else if((MeunTaskID >= dMenu0300)&&(MeunTaskID <= dMenu0374)){Addr = 74;MeunTaskID = dMenu0374;}else if((MeunTaskID >= dMenu0400)&&(MeunTaskID <= dMenu0444)) {Addr = 44;MeunTaskID = dMenu0444;}else if((MeunTaskID >= dMenu0500)&&(MeunTaskID <= dMenu0543)) {Addr = 43;MeunTaskID = dMenu0146;}else if((MeunTaskID >= dMenu0600)&&(MeunTaskID <= dMenu0673)) {Addr = 73;MeunTaskID = dMenu0673;}else if((MeunTaskID >= dMenu0700)&&(MeunTaskID <= dMenu0733)) {Addr = 33;MeunTaskID = dMenu0733;}else if((MeunTaskID >= dMenu0800)&&(MeunTaskID <= dMenu0823)) {Addr = 23;MeunTaskID = dMenu0823;}else if((MeunTaskID >= dMenu0900)&&(MeunTaskID <= dMenu0992)) {Addr = 92;MeunTaskID = dMenu0992;}else if((MeunTaskID >= dMenu1000)&&(MeunTaskID <= dMenu1043)) {Addr = 43;MeunTaskID = dMenu1043;}else if((MeunTaskID >= dMenu1100)&&(MeunTaskID <= dMenu1145)) {Addr = 45;MeunTaskID = dMenu1145;}else if((MeunTaskID >= dMenu1200)&&(MeunTaskID <= dMenu1202)) {Addr = 2;MeunTaskID = dMenu1202;}}shownum[0] = Menu/10; //shownum[1] = Menu%10; //shownum[2] = DispNum__; //-shownum[3] = Addr/10; //0shownum[4] = Addr%10; //0bDisp = dTrue;}else if(KeyValue == KeyENT){#if 1if(MeunTaskID == dMenu1200){//RS232ReadCmd(0xff,0,3,0,1);MeunTaskID = dMenu1200C;//LenTXD = 8;//bWaitReciveReadData = dTrue;shownum[4] = EE_ReadByte(AddIsDisplayOutAmp>>8,AddIsDisplayOutAmp);shownum[3] = EE_ReadByte(AddIsDisplayOutVol>>8,AddIsDisplayOutVol);shownum[2] =EE_ReadByte(AddIsDisplayDcVol>>8,AddIsDisplayDcV ol);shownum[1] =EE_ReadByte(AddIsDisplayUseSet1>>8,AddIsDisplayUseSet1);shownum[0] =EE_ReadByte(AddIsDisplayUseSet2>>8,AddIsDisplayUseSet2);bJump = dTrue;bJumpbit = dTrue;Point = 0;}else if(MeunTaskID == dMenu1201){RS232ReadCmd(0xff,0,4,0,1);MeunTaskID = dMenu1201C;LenTXD = 8;bWaitReciveReadData = dTrue;//return;}else if(MeunTaskID == dMenu1202){RS232ReadCmd(0xff,0,4,0,1);MeunTaskID = dMenu1202C;LenTXD = 8;bWaitReciveReadData = dTrue;//return;}else if(MeunTaskID == dMenu0003){MeunTaskID = dMenu0003C;MenuDisplayNum000((uint)(KeyMode));}else{RS232ReadCmd(0xff,MeunTaskID/100,MeunTaskID%100,0,1);MeunTaskID = MeunTaskID+dMenu0000C;LenTXD = 8;bWaitReciveReadData = dTrue;IsJumpDeal();}#endif#if 0RS232ReadCmd(0xff,MeunTaskID/100,MeunTaskID%100,0,1);MeunTaskID = MeunTaskID+dMenu0000C;LenTXD = 8;bWaitReciveReadData = dTrue;#endif}}//-----------------------------------------------------------//-----------------------------------------------------------void dMenu0000cDeal(unsigned char bWriteBit,uchar Addr_H,uchar Addr_L){uint i,j;uchar m,n;if(KeyValue == KeyCycle){shownum[0] = 0; //shownum[1] = 0; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum; //0shownum[4] = NoDispNum; //0bDisp = dTrue;MeunTaskID = dMenu00xx;bJumpbit = dFalse;bJump = dFalse;Point = 0;return;}if(bWriteBit){if(KeyValue == KeyLeft){j = ReadParaLimit();Tmpshownum[0] = j/10000;Tmpshownum[1] = j/1000%10;Tmpshownum[2] = j/100%10;Tmpshownum[3] = j/10%10;Tmpshownum[4] = j%10;for(i =0; i < 5; i++) //{if(Tmpshownum[i] > 0){MaxPoint = 4-i;MaxNmu = Tmpshownum[i];break;}}if(++Point > MaxPoint) Point = 0;}else if(KeyValue == KeyUp){j = ReadParaLimit();Tmpshownum[0] = j/10000;Tmpshownum[1] = j/1000%10;Tmpshownum[2] = j/100%10;Tmpshownum[3] = j/10%10;Tmpshownum[4] = j%10;for(i =0; i < 5; i++){if(Tmpshownum[i] == 0){Tmpshownum[i] = NoDispNum;}else{MaxPoint = 4-i;MaxNmu = Tmpshownum[i];break;}}if(Point > MaxPoint) Point = 0;switch(Point){case 0:{if(MaxPoint == 0){if(shownum[4] < MaxNmu){shownum[4]++;}}else{if(shownum[4] < 9){shownum[4]++;}else{shownum[4] = 0;}}}break;case 1:{if(MaxPoint == 1){if(shownum[3] < MaxNmu){shownum[3]++;}}else{if(shownum[3] < 9){shownum[3]++;}else{shownum[3] = 0;}}}break;case 2:{if(MaxPoint == 2){if(shownum[2] < MaxNmu){shownum[2]++;}}else{if(shownum[2] < 9){shownum[2]++;}else{shownum[2] = 0;}}}break;case 3:{if(MaxPoint == 3){if(shownum[1] < MaxNmu){shownum[1]++;}}else{if(shownum[1] < 9){shownum[1]++;}else{shownum[1] = 0;}}}break;case 4:{if(MaxPoint == 4){if(shownum[0] < MaxNmu){shownum[0]++;}}else{if(shownum[0] < 9){shownum[0]++;}else{shownum[0] = 0;}}}break;default: Point = 0;break;}for(i =0; i < 5; i++){if(shownum[i] > 9){Tmpshownum[i] = 0;}else{Tmpshownum[i] = shownum[i];}}TemParaData = Tmpshownum[0] *10000+ Tmpshownum[1] *1000+ Tmpshownum[2] *100+ Tmpshownum[3] *10+ Tmpshownum[4];j = ReadParaLimit();if(TemParaData > j) //over max data{TemParaData = j;MenuDisplayNum000(j);}bDisp = dTrue; //*/}else if(KeyValue == KeyDown){j = ReadParaLimit();Tmpshownum[0] = j/10000;Tmpshownum[1] = j/1000%10;Tmpshownum[2] = j/100%10;Tmpshownum[3] = j/10%10;Tmpshownum[4] = j%10;for(i =0; i < 5; i++){if(Tmpshownum[i] == 0){Tmpshownum[i] = NoDispNum;}else{MaxPoint = 4-i;MaxNmu = Tmpshownum[i];break;}}if(Point > MaxPoint) Point = 0;switch(Point){case 0:{if(shownum[4] > 0){shownum[4]--;}else{shownum[4] = 9;}}break;case 1:{if(shownum[3] > 0){shownum[3]--;}else{shownum[3] = 9;}}break;case 2:{if(shownum[2] > 0){shownum[2]--;}else{shownum[2] = 9;}}break;case 3:{if(shownum[1] > 0){shownum[1]--;}else{shownum[1] = 9;}}break;case 4:{if(shownum[0] > 0){shownum[0]--;}else{shownum[0] = 9;}}break;default: Point = 0;break;}for(i =0; i < 5; i++){if(shownum[i] > 9){Tmpshownum[i] = 0;}else{Tmpshownum[i] = shownum[i];}}TemParaData = Tmpshownum[0] *10000+ Tmpshownum[1] *1000+ Tmpshownum[2] *100+ Tmpshownum[3] *10+ Tmpshownum[4];j = ReadParaLimit();if(TemParaData > j) //over max data{TemParaData = j;MenuDisplayNum000(j);}bDisp = dTrue; //*/}else if(KeyValue == KeyENT){bJumpbit = dFalse;bJump = dFalse;Point = 0;m =TemParaData>>8;n = TemParaData;Wait_Write_Addr_H = Addr_H;Wait_Write_Addr_L = Addr_L;LenTXD = 8;RS232WriteCmd(0xff,Addr_H,Addr_L,m,n);bWaitReciveWriteData = dTrue;}}}//----------------------------------------------------//-----------------------------------------------------------void dMenu0003cDeal(void){if(KeyValue == KeyCycle){shownum[0] = 0; //shownum[1] = 0; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum; //0shownum[4] = NoDispNum; //0bDisp = dTrue;MeunTaskID = dMenu00xx;}else if(KeyValue == KeyUp){if(KeyMode == 0) KeyMode = 1;else KeyMode = 0;MenuDisplayNum000((uint)(KeyMode));}else if(KeyValue == KeyDown){if(KeyMode == 0) KeyMode = 1;else KeyMode = 0;MenuDisplayNum000((uint)(KeyMode));}else if(KeyValue == KeyENT){EE_WriteByte(0,1,KeyMode);shownum[0] = DispNum__; //shownum[1] = DispNum_E; //shownum[2] = DispNum_N; //-shownum[3] = DispNum_D; //0shownum[4] = DispNum__; //0bDispLimitTime = dTrue;bDisp = dTrue;}}//----------------------------------------------------//-----------------------------------------------------------void dMenu0100dDeal(void){uint i,j;uchar m,n;if(KeyValue == KeyCycle){shownum[0] = 0; //shownum[1] = 0; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum; //0shownum[4] = NoDispNum; //0bDisp = dTrue;MeunTaskID = dMenu00xx;}else if(KeyValue == KeyUp){if(MeunTaskID == dMenu1200C){j = 9;}else if(MeunTaskID == dMenu1201C){j = 44;}else if(MeunTaskID == dMenu1202C){j = 44;}if(TemParaData >= j) TemParaData = 0;else TemParaData++;i = TemParaData;MenuDisplayNum000(i);}else if(KeyValue == KeyDown){if(TemParaData > 0){TemParaData =TemParaData-1;}i = TemParaData;shownum[0] = i/10000;shownum[1] = i/1000%10;shownum[2] = i/100%10;shownum[3] = i/10%10;shownum[4] = i%10;for(i =0; i < 4; i++){if(shownum[i] == 0){shownum[i] = NoDispNum;}else{break;}}bDisp = dTrue;}else if(KeyValue == KeyENT){m =TemParaData>>8;n = TemParaData;LenTXD = 8;if(MeunTaskID == dMenu1200C){Wait_Write_Addr_H = 0;Wait_Write_Addr_L = 3;RS232WriteCmd(0xff,0,3,m,n);}else if(MeunTaskID == dMenu1201C){Wait_Write_Addr_H = 0;Wait_Write_Addr_L = 4;RS232WriteCmd(0xff,0,4,m,n);}else if(MeunTaskID == dMenu1202C){Wait_Write_Addr_H = 0;Wait_Write_Addr_L = 4;RS232WriteCmd(0xff,0,4,m,n);}bWaitReciveWriteData = dTrue;}}//----------------------------------------------------//-----------------------------------------------------------void dMenu0100eDeal(void){uint i,j;uchar m,n;if(KeyValue == KeyCycle){shownum[0] = 0; //shownum[1] = 0; //shownum[2] = DispNum__; //-shownum[3] = NoDispNum; //0shownum[4] = NoDispNum; //0bDisp = dTrue;MeunTaskID = dMenu00xx;}if(KeyValue == KeyLeft){if(++Point > 4) Point = 0;}else if((KeyValue == KeyUp)||(KeyValue == KeyDown)) {switch(Point){case 0:{shownum[4] = ~shownum[4];}break;case 1:{shownum[3] = ~shownum[3];}break;case 2:{shownum[2] = ~shownum[2];}break;case 3:{shownum[1] = ~shownum[1];}break;case 4:{shownum[0] = ~shownum[0];}break;default: Point = 0;break;}bDisp = dTrue;}else if(KeyValue == KeyENT){/*m =TemParaData>>8;n = TemParaData;LenTXD = 8;if(MeunTaskID == dMenu1200C){Wait_Write_Addr_H = 0;Wait_Write_Addr_L = 3;RS232WriteCmd(0xff,0,3,m,n);}bWaitReciveWriteData = dTrue;//*/IsDisplayOutAmp = shownum[4];EE_WriteByte(AddIsDisplayOutAmp>>8,AddIsDisplayOutAmp,IsDisplayOutAmp);IsDisplayOutV ol = shownum[3];EE_WriteByte(AddIsDisplayOutV ol>>8,AddIsDisplayOutV ol,IsDisplayOutV ol);IsDisplayDcV ol = shownum[2];EE_WriteByte(AddIsDisplayDcV ol>>8,AddIsDisplayDcV ol,IsDisplayDcV ol);IsDisplayUseSet1 = shownum[1];EE_WriteByte(AddIsDisplayUseSet1>>8,AddIsDisplayUseSet1,IsDisplayUseSet1);IsDisplayUseSet2 = shownum[0];EE_WriteByte(AddIsDisplayUseSet2>>8,AddIsDisplayUseSet2,IsDisplayUseSet2);}}//----------------------------------------------------//----------------------------------------------------------------------------void TimeSend(void) /*定时发送寄存器群组*/{switch(SendId){case 0:{RS232ReadCmd(0xff,0x21,2,0,1);LenTXD = 8;bWatchReciveReadData = dTrue;}break;case 1:{RS232ReadCmd(0xff,0x21,4,0,1);LenTXD = 8;bWatchReciveReadData = dTrue;}break;case 2:{RS232ReadCmd(0xff,0x21,5,0,1);LenTXD = 8;bWatchReciveReadData = dTrue;}break;case 3:{RS232ReadCmd(0xff,0x21,6,0,1);LenTXD = 8;bWatchReciveReadData = dTrue;}break;case 4:{RS232ReadCmd(0xff,0x21,7,0,1);LenTXD = 8;bWatchReciveReadData = dTrue;}break;case 5:{RS232ReadCmd(0xff,0x21,8,0,1);LenTXD = 8;bWatchReciveReadData = dTrue;}break;default: SendId = 0;break;}if(++SendId > 5){SendId = 0;}}//----------------------------------------------------------------------------。

详细的Modbus串口编程

详细的Modbus串口编程

详细的Modbus串口编程(1)建立一个基于对话框的MFC工程,名字为Modbus(2)添加MSComm控件打开“Project->Add To Project->Components and Controls->Registered Activex Controls”,然后选择控件:Microsoft Communications Control,version 6.0插入到当前的工程中。

这样就将类CMSComm 的相关文件mscomm.cpp 和mscomm.h 一并加入到了工程中。

再将控件对话中的MSComm 控件拖至你的应用对话框中,用MFC类向导给其添加变量m_MSComm。

(3)串口初始化:在CModbusDlg::OnInitDialog()函数中// TODO: Add extra initialization hereif(m_MSComm.GetPortOpen()) //如果串口是打开的,则先关闭串口{m_MSComm.SetPortOpen(FALSE);}m_MSComm.SetCommPort(4); //选择COM4m_MSComm.SetInBufferSize(1024); //接收缓冲区m_MSComm.SetOutBufferSize(1024); //发送缓冲区m_MSComm.SetInputLen(0);//设置当前接收区长度为0,表示全部读取m_MSComm.SetInputMode(1);//以二进制方式读写数据m_MSComm.SetRThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件m_MSComm.SetSettings("9600,n,8,1");//波特率9600,无校验位,8个数据位,1个停止位if(!m_MSComm.GetPortOpen())//如果串口没有打开则打开m_MSComm.SetPortOpen(TRUE);//打开串口else{m_MSComm.SetOutBufferCount(0);AfxMessageBox("Open The Serial Port 1 Failurre!");}(4)发送数据:首先,在Modbus协议中,要求以十六进制发送数据,因此需要在ClassView 中为CModbusDlg类添加以下两个PUBLIC成员函数,并编辑代码如下:int CModbusDlg::String2Hex(CString str, CByteArray &senddata){int hexdata,lowhexdata;int hexdatalen=0;int len=str.GetLength();senddata.SetSize(len/2);for(int i=0;i<len;)< p="">{char lstr,hstr=str[i];if(hstr==' '){i++;continue;}i++;if(i>=len)break;lstr=str[i];hexdata=ConvertHexChar(hstr);lowhexdata=ConvertHexChar(lstr);if((hexdata==16)||(lowhexdata==16))break;elsehexdata=hexdata*16+lowhexdata;i++;senddata[hexdatalen]=(char)hexdata;hexdatalen++;}senddata.SetSize(hexdatalen);return hexdatalen;}char CModbusDlg::ConvertHexChar(char ch){if((ch>='0')&&(ch<='9'))return ch-0x30;else if((ch>='A')&&(ch<='F'))return ch-'A'+10;else if((ch>='a')&&(ch<='f'))return ch-'a'+10;else return (-1);}然后接在(3)的后面写——//发送数据CString str="12 FA";CByteArray hexdata;int len=String2Hex(str,hexdata); //len用于计算发送了多少个十六进制数m_MSComm.SetOutput((COleVariant)hexdata); //发送十六进制数据Sleep(1000);(5)接收数据:在MFC的类向导中,为MSComm控件添加一个成员函数OnOnCommMscomm1(),然后编辑代码:void CModbusDlg::OnOnCommMscomm1(){// TODO: Add your control notification handler code here //接收数据V ARIANT variant_inp;COleSafeArray safearray_inp;LONG len,k;BYTE rxdata[2048]; //设置BYTE数组CString strtemp,str;BYTE bt;int resEvent;resEvent=m_MSComm.GetCommEvent();if(resEvent==2){variant_inp=m_MSComm.GetInput(); //读缓冲区safearray_inp=variant_inp; //V ARIANT型转为ColeSafeArray 型len=safearray_inp.GetOneDimSize(); //得到有效数据长度for(k=0;k<len;k++)< p="">for(k=0;k<="">{bt=*(char*)(rxdata+k); //字节型//strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放strtemp.Format("%02X ",bt); //十六进制显示str+=strtemp;}MessageBox(str);}}Modbus协议下的接收程序:void CModbusDlg::OnOnCommMscomm1(){// TODO: Add your control notification handler code here V ARIANT variant_inp;COleSafeArray safearray_inp;LONG len,k;BYTE rxdata[2048]; //设置BYTE数组CString strtemp,str;BYTE bt;char tempBuf[200];if(m_MSComm.GetCommEvent()==2)//监听到串口有数据传来{variant_inp=m_MSComm.GetInput(); //读缓冲区safearray_inp=variant_inp; //V ARIANT型转为ColeSafeArray 型len=safearray_inp.GetOneDimSize(); //得到有效数据长度for(k=0;k<len;k++)< p="">for(k=0;k<="">{bt=*(char*)(rxdata+k); //字节型strtemp.Format("%02X ",bt); //十六进制显示switch(recvNum){case 0: //接收第1个字节recvStr=strtemp;recvNum++;break;case 1:recvStr+=strtemp;recvNum++;break;case 2:sscanf(strtemp,"%d",&recvDataLen);recvStr+=strtemp;recvNum++;break;default:recvStr+=strtemp;if(recvNum==recvDataLen+4)//已经接收完一帧数据{MessageBox(recvStr);recvNum=0;recvStr="";}elserecvNum++;break;} // switch END} // for循环END} //if END}函数中有几个全局变量:在.cpp文件开头定义://串口通信全局变量short recvNum; //接收到1帧数据中的字节下标(从0开始) CString recvStr; //接收到的字节转成的字符串short recvDataLen; //数据长度信息在OnInitDialog()中://用于串口数据接收的全局变量初始化recvNum=0;recvStr="";</len;k++)<></len;k++)<></len;)<>。

VB控件Mscomm控件与PLC进行RS485(Modbus)通讯源码

VB控件Mscomm控件与PLC进行RS485(Modbus)通讯源码

V B控件M s c o m m控件与P L C进行R S485(M o d b u s)通讯源码本人用的是ModbusRTU通讯模式,通过计算机串口转RS485与外围设备通行通讯,读写外围设备指定地址里的数据,从而达到自动化控制远端设备。

DimHiByteAsByteDimLoByteAsByteDimCRC16LoAsByteDimCRC16HiAsByteDimReturnData(1)AsByteDimKAsIntegerDimCmdLenthAsIntegerPrivateSubCommand1_Click()K=Text9.Text'写6个字节Text13.Text=""'===========数组赋值输入代码=============================================================================== ========'<<算法一>>DimWriteStr()AsByteDimuAsIntegerReDimWriteStr(K+2)Foru=0ToKWriteStr(u)=Val("&H"&Text1(u).Text)Next'<<算法二>>DimCRC_2()AsByteDimvAsIntegerReDimCRC_2(K)Forv=0ToKCRC_2(v)=Val("&H"&Text1(v).Text)Next'============================================================================== ====================CallCRC161(CRC_2())CallCRC16(WriteStr(),K)MSComm1.InBufferCount=0'==========显示发送代码=============================================================================== =========DimmAsIntegerForm=0To23Ifm<=KThenText8(m).Text=Hex(WriteStr(m))ElseText8(m).Text=""EndIfNext'============================================================================== ====================WriteStr(K+1)=LoByteWriteStr(K+2)=HiByte'发送代码Text4.Text=""DimgAsIntegerForg=0ToK+2Text4.Text=Text4.Text+""+Hex(WriteStr(g))Next'写命令发送后,当接收到8个字节时中断CmdLenth=8MSComm1.RThreshold=CmdLenthMSComm1.Output=WriteStrEndSubPrivateSubCommand2_Click()EndEndSubPrivateSubCommand3_Click()Label34.Caption="="Text13.Text=""K=Text9.Text'写6个字节'===========数组赋值输入代码=============================================================================== ========'<<算法>>DimCRC_2()AsByteDimvAsIntegerReDimCRC_2(K)Forv=0ToKCRC_2(v)=Val("&H"&Text1(v).Text)Next'============================================================================== ====================CallCRC161(CRC_2())CallCRC16(WriteStr(),K)MSComm1.InBufferCount=0'==========显示发送代码=============================================================================== =========DimmAsIntegerForm=0To23Ifm<=KThenText8(m).Text=Hex(WriteStr(m))ElseText8(m).Text=""EndIfNext'============================================================================== ====================WriteStr(K+1)=LoByteWriteStr(K+2)=HiByte'发送代码Text4.Text=""DimgAsIntegerForg=0ToK+2Text4.Text=Text4.Text+""+Hex(WriteStr(g))Next'读命令发送后,当接收5+SendStr(5)*2个字节时产生中断CmdLenth=5+WriteStr(5)*2MSComm1.RThreshold=CmdLenthMSComm1.Output=WriteStr'发送命令'****************************************************************************** **********************************************************'****************************************************************************** *************************************'****************************************************************************** **********************************************************'DimsAddrAsString''DimCheckStringAsString'DimCheckCodeAsString'DimCmdCodeAsString'DimSumAsInteger'DimaAsInteger'DimtmpAsString'a=0'tmp=0''''DoWhileLen(tmp)<8''tmp=tmp+MSComm1.Input'testNO.Caption=testNO.Caption+""+Str(Hex(Asc(tmp)))'a=a+1'Ifa>=3000Then'MSComm1.PortOpen=False'ExitFunction'ExitDo'EndIf'Loop'Label33.Caption=tmp'Text16.Text=Len(tmp)'DimnsAsInteger'Forns=1ToLen(tmp)'Label34.Caption=Label34.Caption+"+"+Str(Asc(Mid(tmp,ns,1))) ''Next'Label35.Caption=Str(Val(Asc(Mid(tmp,6,1)))/10)'''tmp=Mid$(tmp,6,4)'''DimstrHexAsString'DimHex2DecAsLong'DimstrTmpAsString'DimlongTmpAsLong'DimlongDecAsLong'DimintLenAsInteger'Dimn1AsInteger''strHex=Right$(tmp,2)+Left$(tmp,2)''intLen=Len(strHex)'Forn1=1TointLen'strTmp=Mid(strHex,n1,1)'SelectCaseAsc(strTmp)'Case48To57'longTmp=Val(strTmp)'Case65To70'longTmp=Asc(strTmp)-55'CaseElse'Hex2Dec=0''ExitFunction'EndSelect'Text13.Text=Text13.Text+"+"+Str(Asc(strTmp))'longDec=longDec+longTmp*16^(intLen-n1)'Nextn1''Hex2Dec=longDec'Text13.Text=Hex2Dec'****************************************************************************** **********************************************************'****************************************************************************** *************************************'****************************************************************************** **********************************************************EndSubPrivateSubMSComm1_OnComm()DimNeAsIntegermEventCasecomEvReceiveDimBufferAsVariantMSComm1.InputMode=comInputModeBinaryMSComm1.InputLen=0Buffer=MSComm1.InputForNe=LBound(Buffer)ToUBound(Buffer)Text13.Text=Text13.Text&"+"&Buffer(Ne)Label34.Caption=Buffer(3)&""&Buffer(4)NextNeCaseElseEndSelectBeepEndSubPrivateSubCommand4_Click()EndSubPrivateSubCommand5_Click()Label34.Caption="="EndSubPrivateSubForm_Load()MSComm1.Settings="9600,N,8,1"mPort=1MSComm1.SThreshold=0IfNotMSComm1.PortOpenThenMSComm1.PortOpen=TrueEndSubPrivateSubTimer1_Timer()'显示<<算法一>>结果Text2.Text=Hex(HiByte)Text3.Text=Hex(LoByte)'显示<<算法二>>结果Text6.Text=Hex(CRC16Hi)Text7.Text=Hex(CRC16Lo)IfText5.Text<>""Then'十进制转十六进制Text10.Text=Hex(Text5.Text)EndIfIfText11.Text<>""Then'十六进制转十进制Text12.Text=Val("&H"&Text11.Text)EndIfText14.Text=MSComm1.OutBufferCountEndSub'==========CRC校验<<算法二>>=========================================================================== =============FunctionCRC161(data()AsByte)AsString'CRC计算函数'DimCRC16LoAsByte,CRC16HiAsByte'CRC寄存器DimCLAsByte,CHAsByte'多项式码&HA001DimSaveHiAsByte,SaveLoAsByteDimIAsIntegerDimFlagAsIntegerCRC16Lo=&HFFCRC16Hi=&HFFCL=&H1CH=&HA0ForI=0ToUBound(data)CRC16Lo=CRC16LoXordata(I)'每一个数据与CRC寄存器进行异或ForFlag=0To7CRC16Hi=CRC16Hi\2'高位右移一位CRC16Lo=CRC16Lo\2'低位右移一位If((SaveHiAnd&H1)=&H1)Then'如果高位字节最后一位为1CRC16Lo=CRC16LoOr&H80'则低位字节右移后前面补1EndIf'否则自动补0If((SaveLoAnd&H1)=&H1)Then'如果LSB为1,则与多项式码进行异或CRC16Hi=CRC16HiXorCHCRC16Lo=CRC16LoXorCLEndIfNextFlagNextIDimReturnData(1)AsByteReturnData(0)=CRC16Hi'CRC高位ReturnData(1)=CRC16Lo'CRC低位asd=Right("00"+Hex(CRC16Lo),2)+Right("00"+Hex(CRC16Hi),2)EndFunctionPrivateSubmscomm_OnComm()EndSub。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
自己写的modbus协议的控件(delphi 6) 2009-4-2编程资料 2009-04-02 14:22:50 阅读576 评论1 字号:大中小 订阅 .
unit ModBusBase;
interface
uses
Windows, Messages, SysUtils, Classes, ExtCtrls, Forms,MMSystem;
procedure SendOneDataPack;// 从链表中发送一个数据包
// 加入一个包到发送链表中
procedure AddOneDataPack(Address,FuncId:Byte;DataStr:PByte;DataSize:integer);
end;
// TModBusBase 控件代码 /////////////////////////////////////////////////////
{
01-funci髇 ilegal
02-direcci髇 ilegal
04-error de trabajo del esclavo
m_csWriteBuff:TRTLCriticalSection;
procedure ClearSendBuffList;
procedure ClearReceiveBuff;
public
m_hEndThreadEvent:THandle;
TOnTimeSendData=procedure(Sender : TObject;Buff:PByte;BuffSize:integer) of Object;
TOnReceiveDataEnd=procedure(Sender:TObject;Address,FuncId:Byte;DataStr:PByte;DataSize:integer)of object;
begin
test2:=GetTickCount()-test1;
test2:=test2;
test1:=GetTickCount();
ResetEvent(m_ModBusBase.m_hEventArray[Event]);
if (self.m_ModBusBase.GetReceiveDataFlag()=true)then// 收到数据
self.m_ModBusBase.SetReceiveDataFlag(false)// 定时间隔结束
else // 说明接收数据模块没有刷新接收数据标志
type
// arreglo de bytes que conforman el mensaje modbus y un puntero al mismo
PDataByte=^TDataByte;
TDataByte = array of byte;
TOnErrorEvent = procedure(Sender : TObject; const ErrorMsg : String) of Object;
Synchronize(self.m_ModBusBase.ReceiveDataEnd);
end;
end;
end;
timeKillEvent(TimerId1);
timeKillEvent(TimerId2);
SetEvent(self.m_ModBusBase.m_hThreadHasEnd);
property OnReceiveDataEnd:TOnReceiveDataEnd read FOnReceiveDataEnd write FOnReceiveDataEnd;
endபைடு நூலகம்
procedure Register;
implementation
procedure Register;
property OnError: TOnErrorEvent read FOnError write FOnError;
property OnTimeSendData:TOnTimeSendData read FOnTimeSendData write FOnTimeSendData;
// modbus基类,(1)完成延时发送(定时20毫秒发送一个读数据包,在20毫秒后再发送下一个数据包)
// (2)数据是否结束检测(接收到字符后,延时10毫秒,还没有收到字符,说明数据包接收完成)
// (3)完成数据封装和解析(从设备地址和功能码+具体从设备数据+crc校验)
// 生成检测数据包是否结束的定时器
TimerId2:=timeSetEvent(self.m_ModBusBase.ReceiveDataTime,0,TFNTimeCallBack(self.m_ModBusBase.m_hRecevieDataEndTimerEvent),
0,TIME_PERIODIC or TIME_CALLBACK_EVENT_SET);
// 具体设备数据的包应该由具体的设备开发单元来封装和解析
TModBusBase=class;
// modbus基类线程类
TModBusBaseThread=Class(TThread)
private
test1,test2:DWORD;
protected
procedure EncodeData(DeviceAddress,FunctionId:Byte;DataStr:PByte;DataSize:integer;
PackStr:PByte;var PackSize:integer); // 封包
// 生成定时发读数据的定时器
TimerId1:=timeSetEvent(self.m_ModBusBase.SendDataTime,0,TFNTimeCallBack(self.m_ModBusBase.m_hTimerSendDataEvent),
0,TIME_PERIODIC or TIME_CALLBACK_EVENT_SET);
m_Thread:TModBusBaseThread;
m_ReceiveBuff:TDataByte;
m_ReceiveDataFlag:boolean;
m_csReceiveData:TRTLCriticalSection;
m_WriteBuff:TList;
function DecodeData(var DeviceAddress,FunctionId:Byte;DataStr:PByte;var DataSize:integer;
PackStr:PByte;PackSize:integer):boolean; // 解包
begin
RegisterComponents('DMSComponent', [TModBusBase]);
end;
// TModBusBaseThread 控件代码 //////////////////////////////////////////////////
// 线程执行函数
begin
ResetEvent(m_ModBusBase.m_hEventArray[Event]);
Synchronize(self.m_ModBusBase.SendOneDataPack);
end;
2: // 收到字符延时事件
// (1)定义定时器发送数据包(2)定义定时器用于检测数据包是否结束
procedure TModBusBaseThread.Execute; //线程执行过程
var Event:DWORD;
loop:boolean;
TimerId1,TimerId2:integer;
Begin
case Event of
0: // 结束线程
begin
ResetEvent(m_ModBusBase.m_hEventArray[Event]);
loop:=false;
end;
1: // 定时发包事件
m_hTimerSendDataEvent:THandle;
m_hRecevieDataEndTimerEvent:THandle;
m_hEventArray:array[0..2]of THandle;
m_hThreadHasEnd:THandle;
published
property SendDataTime:integer read FSendDataTime write FSendDataTime;
property ReceiveDataTime:integer read FReceiveDataTime write FReceiveDataTime;
Event:=0;
loop:=true;
test1:=0;
test2:=0;
While (loop) do
Begin
Event := WaitForMultipleObjects(3, @m_ModBusBase.m_hEventArray, FALSE, INFINITE);
05-el esclavo requiere m醩 tiempo
06-el esclavo est?ocupado y no atiende al query
07-time out
08-error de acceso a memoria del esclavo
procedure Execute;override;
public
m_ModBusBase:TModBusBase;
相关文档
最新文档