Commit 27b90029 LN

增加松下伺服类库

1 个父辈 7f084438
......@@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeLibrary", "CodeLibraryP
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeToolClinet", "CodeToolClinet\CodeToolClinet.csproj", "{87075EC9-91E4-4EF1-9B35-E220DA7C937C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceLib", "DeviceLibrary\DeviceLib.csproj", "{A26E4DBE-908A-40F4-88A5-DAB0D27CBE4B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -33,6 +35,10 @@ Global
{87075EC9-91E4-4EF1-9B35-E220DA7C937C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87075EC9-91E4-4EF1-9B35-E220DA7C937C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87075EC9-91E4-4EF1-9B35-E220DA7C937C}.Release|Any CPU.Build.0 = Release|Any CPU
{A26E4DBE-908A-40F4-88A5-DAB0D27CBE4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A26E4DBE-908A-40F4-88A5-DAB0D27CBE4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A26E4DBE-908A-40F4-88A5-DAB0D27CBE4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A26E4DBE-908A-40F4-88A5-DAB0D27CBE4B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A26E4DBE-908A-40F4-88A5-DAB0D27CBE4B}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DeviceLib</RootNamespace>
<AssemblyName>DeviceLib</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PanasonicServo\ACCMDManager.cs" />
<Compile Include="PanasonicServo\AcSerialBean.cs" />
<Compile Include="PanasonicServo\ACServerManager.cs" />
<Compile Include="PanasonicServo\ACServerManager_Partial.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
\ No newline at end of file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DeviceLib
{
public class ACCMDManager
{
/// <summary>
/// 0132h 原点接近传感器输入 (HOME) 状态 ReadOnly 0: 输入 OFF 1: 输入 ON
/// </summary>
internal static string Home_Single = "0132";
/// <summary>
/// 0022h 负方向驱动禁止输入(NOT) ReadOnly 0: 输入 OFF、 1: 输入 ON
/// </summary>
internal static string Limit_Negative_Single = "0022";
/// <summary>
/// 0023h 正方向驱动禁止输入(POT) ReadOnly 0: 输入 OFF、 1: 输入 ON
/// </summary>
internal static string Limit_Positive_Single = "0023";
/// <summary>
///速度 4601
/// </summary>
internal static string Speed_Addr = "4601";
/// <summary>
/// 0060h 伺服 On 输入 (SRV-ON) 操作 R/W 0000h:输入 OFF、FF00h:输入 ON
/// </summary>
internal static string ServerOn_Addr = "0060";
/// <summary>
/// 0120h 选通输入 (STB) 操作 R/W 0000h:输入 OFF、FF00h:输入 ON
/// </summary>
internal static string STB_Addr = "0120";
/// <summary>
/// 0124h 减速停止输入 (S-STOP) 操作 R/W 0000h:输入 OFF、FF00h:输入 ON
/// </summary>
internal static string Stop_Addr = "0124";
/// <summary>
/// 0123h 紧急停止输入 (H-STOP) 操作 R/W 0000h:输入 OFF、FF00h:输入 ON
/// </summary>
internal static string SDStop_Addr = "0123";
/// <summary>
/// 0061h 报警清除输入 (A-CLR) 操作 R/W 0000h:输入 OFF、FF00h:输入 ON
/// </summary>
internal static string Clear_Alarm_Addr = "0061";
/// <summary>
/// 1020h Save all parameters - 0 - 4294967295 2 R/W 参数写入 EEPROM 写入“6173h”后,实行 EEPROM 写入
/// </summary>
internal static string EEPROM_Param_Addr = "1020";
/// <summary>
/// 目标位置=600B
/// </summary>
internal static string TargetPostion = "600B";
/// <summary>
/// 实际位置=600F
/// </summary>
internal static string ActualPosition = "600F";
/// <summary>
/// BUSY状态=0140,0140h 动作执行状态 (BUSY) ReadOnly 0:未执行 1:执行中
internal static string BUSYStatus = "0140";
/// <summary>
/// HOME-CMP=0141,0141h 回原点完成状态 (HOME-CMP) ReadOnly 0:未完成 1:完成
/// </summary>
internal static string HOME_CMP_Status = "0141";
/// <summary>
/// 私服Ready状态,00A0h 伺服 Ready 状态 (S-RDY) ReadOnly 0:Ready OFF 1:Ready ON
/// </summary>
internal static string ServerOn_Status = "00A0";
/// <summary>
/// 报警状态=00A1,00A1h 报警状态 (ALM) ReadOnly 0:报警未发生 1:报警发生
/// </summary>
internal static string Alarm_Status = "00A1";
/// <summary>
/// 指定BlockNo=4414
/// </summary>
internal static string BlockNo = "4414";
/// <summary>
/// 读线圈01
/// </summary>
internal static byte CMD_ReadCoil= 0x01;
/// <summary>
/// 写线圈 05
/// </summary>
internal static byte CMD_WriteCoil = 0x05;
/// <summary>
/// 读寄存器03
/// </summary>
internal static byte CMD_ReadRegisters = 0x03;
/// <summary>
/// 写寄存器06
/// </summary>
internal static byte CMD_WriteRegisters = 0x06;
/// <summary>
/// 写多个线圈 0f
/// </summary>
internal static byte CMD_WriteMCoil = 0x0F;
/// <summary>
/// 写多个寄存器10
/// </summary>
internal static byte CMD_WriteMRegisters = 0x10;
/// <summary>
/// block0=原点返回,正方向
/// </summary>
internal static string Block_HomeMove0 = "0";
/// <summary>
/// block1=原点返回,反方向
/// </summary>
internal static string Block_HomeMove1 = "1";
/// <summary>
/// block2=绝对位置运动
/// </summary>
internal static string Block_AbsMove = "2";
/// <summary>
/// block3=相对位置运动
/// </summary>
internal static string Block_RelMove = "3";
/// <summary>
/// block4=正方向匀速运动
/// </summary>
internal static string Block_VolMove0 = "4";
/// <summary>
/// block5=反方向匀速运动
/// </summary>
internal static string Block_VolMove1 = "5";
/// <summary>
/// block6=减速停止
/// </summary>
internal static string Block_DelSpeedStop = "6";
/// <summary>
/// block7=紧急停止
/// </summary>
internal static string Block_SuddenStop = "7";
internal static byte[] buildCheckData(byte[] sendData, int length)
{
ushort pChecksum = 0;
AcSerialBean.CalculateCRC(sendData, length, out pChecksum);
string checkStr = Convert.ToString(pChecksum, 16);
byte[] checkByte = AcSerialBean.StringToByte(checkStr);
if (checkByte.Length == 1)
{
sendData[length] = checkByte[0];
sendData[length + 1] = 0x00;
}
else
{
sendData[length + 1] = checkByte[0];
sendData[length] = checkByte[1];
}
return sendData;
}
internal static byte[] GetWriteData(int slvAddr, byte cmd, string addr, string dataValue, int length)
{
// ( 2) 读取寄存器( 03h)
if (cmd.Equals(CMD_ReadRegisters))
{
return Get03WriteData(slvAddr, addr,length);
}
else if (cmd.Equals(CMD_WriteRegisters))
{
// ( 4) 写入寄存器( 06h)
return Get06WriteData(slvAddr, addr, dataValue);
}
else if (cmd.Equals(CMD_WriteCoil))
{
return Get05WriteData(slvAddr, addr, dataValue);
}
else if (cmd.Equals(CMD_ReadCoil))
{
return Get01WriteData(slvAddr, addr, length);
}
return null;
}
private static byte[] Get05WriteData(int slvAddr, string addr, string dataValue)
{
byte[] sendData = new byte[8];
sendData[0] = (byte)slvAddr;
sendData[1] = CMD_WriteCoil;
byte[] addrByte = AcSerialBean.StringToByte(addr.ToString());
if (addrByte.Length == 1)
{
sendData[2] = 0x00;
sendData[3] = addrByte[0];
}
else if (addrByte.Length == 2)
{
sendData[3] = addrByte[1];
sendData[2] = addrByte[0];
}
byte[] dataByte = AcSerialBean.StringToByte(dataValue);
if (dataByte.Length == 1)
{
sendData[4] = 0x00;
sendData[5] = dataByte[0];
}
else if (dataByte.Length == 2)
{
sendData[5] = dataByte[1];
sendData[4] = dataByte[0];
}
sendData = buildCheckData(sendData, sendData.Length - 2);
return sendData;
}
private static byte[] Get01WriteData(int slvAddr, string addr, int length)
{
byte[] sendData = new byte[8];
sendData[0] = (byte)slvAddr;
sendData[1] = CMD_ReadCoil;
byte[] addrByte = AcSerialBean.StringToByte(addr.ToString());
if (addrByte.Length == 1)
{
sendData[2] = 0x00;
sendData[3] = addrByte[0];
}
else if (addrByte.Length == 2)
{
sendData[3] = addrByte[1];
sendData[2] = addrByte[0];
}
byte[] dataByte = AcSerialBean.StringToByte(length.ToString());
if (dataByte.Length == 1)
{
sendData[4] = 0x00;
sendData[5] = dataByte[0];
}
else if (dataByte.Length == 2)
{
sendData[4] = dataByte[1];
sendData[5] = dataByte[0];
}
sendData = buildCheckData(sendData, sendData.Length - 2);
return sendData;
}
private static byte[] Get03WriteData(int slvAddr, string addr, int length)
{
// ( 2) 读取寄存器( 03h)
//发送
//从站地址
//03h
//寄存器起始地址 高位
//低位
//寄存器数(N) 高位
//低位
//CRC 低位
//高位
byte[] sendData = new byte[8 ];
sendData[0] = (byte)slvAddr;
sendData[1] = CMD_ReadRegisters;
byte[] addrByte = AcSerialBean.StringToByte(addr.ToString());
if (addrByte.Length == 1)
{
sendData[2] = 0x00;
sendData[3] = addrByte[0];
}
else if (addrByte.Length == 2)
{
sendData[3] = addrByte[1];
sendData[2] = addrByte[0];
}
byte[] dataByte = AcSerialBean.StringToByte(length.ToString());
if (dataByte.Length == 1)
{
sendData[4] = 0x00;
sendData[5] = dataByte[0];
}
else if (dataByte.Length == 2)
{
sendData[4] = dataByte[1];
sendData[5] = dataByte[0];
}
sendData = buildCheckData(sendData, sendData.Length-2);
return sendData;
}
private static byte[] Get06WriteData(int slvAddr, string addr, string dataValue)
{
// ( 4) 写入寄存器( 06h)
//从站地址
//06h
//地址 高位
//低位
//変更数据 高位
//低位
//CRC 低位
//高位
byte[] sendData = new byte[8];
sendData[0] = (byte)slvAddr;
sendData[1] = CMD_WriteRegisters;
byte[] addrByte = AcSerialBean.StringToByte(addr.ToString());
if (addrByte.Length == 1)
{
sendData[2] = 0x00;
sendData[3] = addrByte[0];
}
else if (addrByte.Length == 2)
{
sendData[3] = addrByte[1];
sendData[2] = addrByte[0];
}
byte[] dataByte = AcSerialBean.StringToByte(dataValue);
if (dataByte.Length == 1)
{
sendData[4] = 0x00;
sendData[5] = dataByte[0];
}
else if (dataByte.Length == 2)
{
sendData[4] = dataByte[0];
sendData[5] = dataByte[1];
//sendData[4] = dataByte[1];
//sendData[5] = dataByte[0];
}
sendData = buildCheckData(sendData, sendData.Length - 2);
return sendData;
}
}
public enum InfoType
{
Debug=1,
Info=2,
Error=3
}
}

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
namespace DeviceLib
{
/// <summary>
/// 外部调用的接口放在此文件中
/// </summary>
public partial class ACServerManager
{
public static bool IsShowMsg = false ;
private static int SleepMSendons = 20;
private static int ReviceOutTimeMS = 100;
private static Dictionary<string, Dictionary<string, int>> ComAddrValue = new Dictionary<string, Dictionary<string, int>>();
private static string mapObj = "";
public delegate void LogDelegate(InfoType type, string msg);
public static event LogDelegate LogEvent;
public static void Log(InfoType type, string msg)
{
LogEvent?.Invoke(type, msg);
}
/// <summary>
/// 打开端口
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="ACBaudRate">波特率</param>
/// <returns></returns>
public static bool OpenPort(string portName,int ACBaudRate)
{
if (serialBeanMap.ContainsKey(portName))
{
return true;
}
//int ACBaudRate = ConfigAppSettings.GetIntValue(Setting_Init.ACBaudRate);
if (ACBaudRate <= 0)
{
ACBaudRate = 9600;
}
AcSerialBean bean = new AcSerialBean(portName, ACBaudRate, Parity.Even, 8, StopBits.One);
bool result = bean.openPort();
if (!result)
{
Log(InfoType.Info,"打开串口【" + portName + "】【" + ACBaudRate + "】失败");
return false;
}
Log(InfoType.Info,"打开串口【" + portName + "】【" + ACBaudRate + "】成功");
//bean.DataReceived += DataReceived;
if (serialBeanMap.ContainsKey(portName))
{
serialBeanMap.Remove(portName);
}
serialBeanMap.Add(portName, bean);
return true;
}
/// <summary>
/// 关闭端口
/// </summary>
/// <param name="portName">端口号</param>
public static void ColsePort(string portName)
{
AcSerialBean bean = GetSerialBean(portName);
if (bean == null)
{
Log(InfoType.Info,"串口【" + portName + "】未打开,不需要关闭");
return;
}
//清理缓存
bean.clearInBuffer();
bean.clearOutBuffer();
bean.closePort();
if (serialBeanMap.ContainsKey(portName))
{
serialBeanMap.Remove(portName);
}
Log(InfoType.Info,"ACServerManager 关闭串口【" + portName + "】 ");
}
/// <summary>
/// 关闭所有端口
/// </summary>
public static void CloseAllPort()
{
List<string> kes = new List<string>(serialBeanMap.Keys);
foreach (string key in kes)
{
ColsePort(key);
}
}
/// <summary>
/// 是否成功打开伺服
/// </summary>
public static bool ServerOnStatus(string portName, int slvAddr)
{
if (!serialBeanMap.ContainsKey(portName))
{
return false ;
}
PreReadCoilAddr = ACCMDManager.ServerOn_Addr;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadCoil, PreReadCoilAddr, "0000", 1);
//SendData(portName,dataArray);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 6);
int result= GetCoilData(portName, reviceData, PreReadCoilAddr);
//TODO
return result>=1;
}
/// <summary>
/// 是否原点返回完成
/// </summary>
public static bool IsHomeMoveEnd(string portName, int slvAddr)
{
int status = GetHomeEndStatus(portName, slvAddr);
bool isOk = ACServerManager.GetBusyStatus(portName, slvAddr).Equals(0);
if (status >= 1&&isOk)
{
return true;
} return false;
}
public static void InitSlvAddr(string portName, int slvAddr)
{
InitSlvAddr(portName, slvAddr, 100, 30, 30 );
//InitSlvAddr(portName, slvAddr, 100, 30, 30, 100, 50, 30);
}
//把数字转换为四位的字符串
public static string SpeedToStr(int speed,int length)
{
string str = String.Format("{0:X}", speed);
return str.PadLeft(length, '0');
}
/// <summary>
/// 伺服初始化
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
/// <param name="targetSpeed">目标速度</param>
/// <param name="addSpeed">加速度</param>
/// <param name="delSpeed">减速带</param>
public static void InitSlvAddr(string portName, int slvAddr,int targetSpeed,int addSpeed,int delSpeed )
//public static void InitSlvAddr(string portName, int slvAddr,int targetSpeed,int addSpeed,int delSpeed,int homeHighSpeed,int homeLowSpeed,int homeAddSpeed)
{
Log(InfoType.Info,"开始初始化伺服【" + portName + "】【" + slvAddr + "】");
//写入block
int sleep = 50;
string slvAddrStr = string.Format(strFromat, slvAddr);
////block0=原点返回,正方向
//string str0 = slvAddrStr + "104800 000408 00000420 00000000 ffff";
//SendStrAndSleep(portName, str0, sleep);
////block1=原点返回,反方向
//string str1 = slvAddrStr + "104804 000408 04000420 00000000 ffff";
//SendStrAndSleep(portName, str1, sleep);
////block2=绝对位置运动
//string str2 = slvAddrStr + "104808 000408 10000211EC78FFFF ffff";
//SendStrAndSleep(portName, str2, sleep);
////block3=相对位置运动
//string str3 = slvAddrStr + "10480C 000408 10000111EC78FFFF ffff";
//SendStrAndSleep(portName, str3, sleep);
////block4=正方向匀速运动
//string str4 = slvAddrStr + "104810 000408 10000311 00000000 ffff";
//SendStrAndSleep(portName, str4, sleep);
////block5=反方向匀速运动
//string str5 = slvAddrStr + "104814 000408 14000311 00000000 ffff";
//SendStrAndSleep(portName, str5, sleep);
////block6=减速停止
//string str6 = slvAddrStr + "104818 000408 00000500 00000000 ffff";
//SendStrAndSleep(portName, str6, sleep);
////block7=紧急停止
//string str7 = slvAddrStr + "10481c 000408 00000510 00000000 ffff";
//SendStrAndSleep(portName, str7, sleep);
//0106460001009D12
//速度 V1 =100
string v1 = slvAddrStr + "064601 " + SpeedToStr(targetSpeed, 4) + " ffff";
SendStrAndSleep(portName, v1, sleep);
//加速度 A1 =30
string a1 = slvAddrStr + "064611 " + SpeedToStr(addSpeed, 4) + " ffff";
SendStrAndSleep(portName, a1, sleep);
//减速度 D1=30
string d1 = slvAddrStr + "064621 " + SpeedToStr(delSpeed, 4) + " ffff";
SendStrAndSleep(portName, d1, sleep);
////原点返回高速 homeHighSpeed=100
//SendStrAndSleep(portName, slvAddrStr + "06 4637 " + SpeedToStr(homeHighSpeed, 4) + " ffff", sleep);
////原点返回抵速 homeLowSpeed=50
//SendStrAndSleep(portName, slvAddrStr + "06 4638 " + SpeedToStr(homeLowSpeed, 4) + " ffff", sleep);
////原点返回加速度=30
//SendStrAndSleep(portName, slvAddrStr + "06 4639 " + SpeedToStr(homeAddSpeed, 4) + " ffff", sleep);
//UpdateEEPROM(portName, slvAddr);
}
private static void UpdateEEPROM(string portName, int slvAddr)
{
string addr = ACCMDManager.EEPROM_Param_Addr;
string data = "6173";
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteRegisters, addr, data, length);
SendData(portName, dataArray, 5);
}
/// <summary>
/// 伺服ON
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
public static void ServoOn(string portName, int slvAddr)
{
string addr = ACCMDManager.ServerOn_Addr;
string data = "FF00";
//byte cmd = 0x05;
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
/// <summary>
/// 伺服Off
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
public static void ServoOff(string portName, int slvAddr)
{
string addr = ACCMDManager.ServerOn_Addr;
string data = "0000";
//byte cmd = 0x05;
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
/// <summary>
/// 相对运动
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
/// <param name="position">相对位置</param>
/// <param name="targetSpeed">目标速度</param>
public static void RelMove(string portName, int slvAddr, int position,int targetSpeed)
{
//先更新速度
string slvAddrStr = string.Format(strFromat, slvAddr);
string v1 = slvAddrStr + "064601 " + SpeedToStr(targetSpeed, 4) + " ffff";
SendStrAndSleep(portName, v1,SleepMSendons);
RelMove(portName, slvAddr, position);
}
private static void RelMove(string portName, int slvAddr, int position)
{
//int position = Convert.ToInt32(txtPosition.Text);
byte[] positionData = AcSerialBean.StringToByte(position.ToString("X8"));
byte[] data = AcSerialBean.StringToByte("0110480C 000408 10000111EC78FFFF ffff");
data[0] = (byte)slvAddr;
data[data.Length - 1] = 0x00;
data[data.Length - 2] = 0x00;
if (positionData.Length == 4)
{
data[11] = positionData[2];
data[12] = positionData[3];
data[13] = positionData[0];
data[14] = positionData[1];
}
else if (positionData.Length == 3)
{
data[11] = positionData[1];
data[12] = positionData[2];
data[13] = 0x00;
data[14] = positionData[0];
}
else if (positionData.Length == 2)
{
data[11] = positionData[0];
data[12] = positionData[1];
data[13] = 0x00;
data[14] = 0x00;
}
else if (positionData.Length == 1)
{
data[11] = 0x00;
data[12] = positionData[0];
data[13] = 0x00;
data[14] = 0x00;
}
data = ACCMDManager.buildCheckData(data, data.Length - 2);
SendData(portName, data);
System.Threading.Thread.Sleep(SleepMSendons);
UpdateBlock(portName, slvAddr, ACCMDManager.Block_RelMove);
OpenAndCloseSTB(portName, slvAddr);
}
/// <summary>
/// 原点返回
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
/// <param name="speed">速度</param>
/// <param name="mustMove">原点返回前是否必须要相对走2000</param>
public static void HomeMove(string portName, int slvAddr, int speed,bool mustMove=false)
{
try
{
//先判断是否在原点,如果已经在原点,先向正方向走2000
int homeSingle = GetHomeSingle(portName, slvAddr);
if (homeSingle.Equals(1)||mustMove)
{
int isHomeEnd = GetHomeEndStatus(portName, slvAddr);
if (isHomeEnd.Equals(1))
{
int value = 2000;
Log(InfoType.Info,"轴【" + portName +"_"+slvAddr +"】"+ mustMove + " HomeMove,需要先相对走" + value);
RelMove(portName, slvAddr, value);
bool isStop = false;
for (int i = 0; i <= 10; i++)
{
Thread.Sleep(200);
if (GetBusyStatus(portName, slvAddr).Equals(0))
{
isStop = true;
Log(InfoType.Info,"轴【" + portName + "_" + slvAddr + "】 相对走" + value + "已结束");
break;
}
}
if (!isStop)
{
Log(InfoType.Info,"轴【" + portName + "_" + slvAddr + "】 相对走" + value + "已等待2分钟,直接停止");
SuddenStop(portName, slvAddr);
}
}
else
{
int volSpeed =Math.Abs( speed / 5);
int time = 1500;
Log(InfoType.Info,"轴【" + portName + "_" + slvAddr + "】" + mustMove + " HomeMove,先匀速向上走" + time+",速度["+ volSpeed + "]" );
//需要匀速向上走
ACServerManager.SpeedMove(portName, slvAddr, volSpeed);
Thread.Sleep(time);
Log(InfoType.Info,"轴【" + portName + "_" + slvAddr + "】匀速 已等待" + time + ",直接停止");
SuddenStop(portName, slvAddr);
Thread.Sleep(SleepMSendons);
}
}
}catch(Exception ex)
{
Log(InfoType.Error,"轴【" + portName + "_" + slvAddr + "】原点返回前验证是否在原点出错:" +ex.ToString());
}
//默认负方向原点返回
UpdateBlock(portName, slvAddr, ACCMDManager.Block_HomeMove1);
Thread.Sleep(SleepMSendons);
OpenAndCloseSTB(portName, slvAddr);
}
private static void SetSpeed(string portName, int slvAddr, int speed)
{
speed = Math.Abs(speed);
int preSpeed = GetAddrValue(portName, slvAddr, ACCMDManager.Speed_Addr);
if ((preSpeed.Equals(-1)) || (!preSpeed.Equals(speed)))
{
string v1 = slvAddr + "064601 " + ACServerManager.SpeedToStr(speed, 4) + " ffff";
Log(InfoType.Debug,"轴【" + portName + "_" + slvAddr + "】更新速度为【" + speed + "】,发送数据【" + v1 + "】");
Thread.Sleep(SleepMSendons);
for (int i = 1; i <= 3; i++)
{
bool result = SendStrAndSleep(portName, v1, SleepMSendons);
if (result)
{
break;
}
else
{
Log(InfoType.Error,"轴【" + portName + "_" + slvAddr + "】更新速度为【" + speed + "】,发送数据【" + v1 + "】,第【" + i + "】次失败");
Thread.Sleep(SleepMSendons);
}
}
UpdateAddrValue(portName, slvAddr, ACCMDManager.Speed_Addr, speed);
Thread.Sleep(SleepMSendons);
}
}
/// <summary>
/// 匀速运动
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
/// <param name="speed">速度</param>
public static void SpeedMove(string portName, int slvAddr, int speed)
{
SetSpeed(portName, slvAddr, speed);
if (speed > 0)
{
UpdateBlock(portName, slvAddr, ACCMDManager.Block_VolMove0);
}
else
{
UpdateBlock(portName, slvAddr, ACCMDManager.Block_VolMove1);
}
//Thread.Sleep(SleepMSendons);
OpenAndCloseSTB(portName, slvAddr);
}
/// <summary>
/// 当前是否在指定的位置
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
/// <param name="PPosition">位置</param>
/// <param name="canError">误差值</param>
/// <returns></returns>
public static bool isInPosition(string portName, int slvAddr, int PPosition,int canError)
{
int outCount = ACServerManager.GetActualtPosition(portName, slvAddr);
int errorCount = Math.Abs(outCount - PPosition);
if (errorCount <= canError)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 绝对运动
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="slvAddr">伺服地址</param>
/// <param name="targetPosition">目标位置</param>
/// <param name="targetSpeed">目标速度</param>
public static void AbsMove(string portName, int slvAddr, int targetPosition, int targetSpeed)
{
//先更新速度
string slvAddrStr = string.Format(strFromat, slvAddr);
int preSpeed = GetAddrValue(portName,slvAddr, ACCMDManager.Speed_Addr);
if ((preSpeed.Equals(-1)) || (!preSpeed.Equals(targetSpeed)))
{
//速度 V1 =100
string v1 = slvAddrStr + "064601 " + SpeedToStr(targetSpeed, 4) + " ffff";
SendStrAndSleep(portName, v1, SleepMSendons);
UpdateAddrValue(portName,slvAddr, ACCMDManager.Speed_Addr, targetSpeed);
}
//绝对运动
AbsMove(portName, slvAddr, targetPosition);
}
private static void AbsMove(string portName, int slvAddr, int position)
{
//int position = Convert.ToInt32(txtPosition.Text, 10);
byte[] positionData = AcSerialBean.StringToByte(position.ToString("X8"));
byte[] data = AcSerialBean.StringToByte("01104808 000408 10000211 EC78FFFF ffff");
data[0] = (byte)slvAddr;
data[data.Length - 1] = 0x00;
data[data.Length - 2] = 0x00;
if (positionData.Length == 4)
{
data[11] = positionData[2];
data[12] = positionData[3];
data[13] = positionData[0];
data[14] = positionData[1];
}
else if (positionData.Length == 3)
{
data[11] = positionData[1];
data[12] = positionData[2];
data[13] = 0x00;
data[14] = positionData[0];
}
else if (positionData.Length == 2)
{
data[11] = positionData[0];
data[12] = positionData[1];
data[13] = 0x00;
data[14] = 0x00;
}
else if (positionData.Length == 1)
{
data[11] = 0x00;
data[12] = positionData[0];
data[13] = 0x00;
data[14] = 0x00;
}
data = ACCMDManager.buildCheckData(data, data.Length - 2);
SendData(portName, data);
Thread.Sleep(SleepMSendons);
UpdateBlock(portName, slvAddr, ACCMDManager.Block_AbsMove);
//data = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteRegisters, ACCMDManager.BlockNo, ACCMDManager.Block_AbsMove, 2);
//SendData(portName, data);
//Thread.Sleep(SleepMSendons);
OpenAndCloseSTB(portName, slvAddr);
}
}
}

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
namespace DeviceLib
{
partial class ACServerManager
{
private static Dictionary<int, Dictionary<string, RegisterInfo>> LastDataMap = new Dictionary<int, Dictionary<string, RegisterInfo>>();
//private static SerialBean bean = null;
private static string strFromat = "{0:X2}";
private static Dictionary<string, AcSerialBean> serialBeanMap = new Dictionary<string, AcSerialBean>();
private static AcSerialBean GetSerialBean(string portName)
{
if (serialBeanMap.ContainsKey(portName))
{
return serialBeanMap[portName];
}
return null;
}
private static bool SendStrAndSleep(string portName, string str, int sleepS)
{
byte[] data = AcSerialBean.StringToByte(str);
data[data.Length - 1] = 0x00;
data[data.Length - 2] = 0x00;
data = ACCMDManager.buildCheckData(data, data.Length - 2);
bool result = SendData(portName, data);
System.Threading.Thread.Sleep(sleepS);
return result;
}
private static void SaveData(string portName, byte slvAddr, string regAddr, int value)
{
if (LastDataMap.ContainsKey(slvAddr))
{
if (LastDataMap[slvAddr].ContainsKey(regAddr))
{
LastDataMap[slvAddr][regAddr] = new RegisterInfo(slvAddr, regAddr, value);
}
else
{
LastDataMap[slvAddr].Add(regAddr, new RegisterInfo(slvAddr, regAddr, value));
}
}
else
{
Dictionary<string, RegisterInfo> map = new Dictionary<string, RegisterInfo>();
map.Add(regAddr, new RegisterInfo(slvAddr, regAddr, value));
LastDataMap.Add(slvAddr, map);
}
}
private static RegisterInfo GetData(string portName, byte slvAddr, string regAddr)
{
if (LastDataMap.ContainsKey(slvAddr))
{
if (LastDataMap[slvAddr].ContainsKey(regAddr))
{
return LastDataMap[slvAddr][regAddr];
}
}
return null;
}
private static void SendData(string portName, byte[] data, int reviceLength)
{
if (data == null)
{
return;
}
byte[] returnData = SendCommand(portName, data, ReviceOutTimeMS, reviceLength);
string strSend = "";
for (int i = 0; i < returnData.Length; i++)
{
strSend += string.Format("{0:X2} ", returnData[i]);
}
if (IsShowMsg)
{
Log(InfoType.Info, "串口" + portName + " 收到数据:" + strSend + "");
}
}
private static bool SendData(string portName, byte[] data)
{
if (data == null)
{
return false;
}
int timeOut = ReviceOutTimeMS;
//if (data[1].Equals((byte)10))
//{
// timeOut = 1000;
//}
bool result = false;
byte[] returnData = SendCommand(portName, data, timeOut, 8, out result);
if (returnData != null)
{
string strSend = "";
for (int i = 0; i < returnData.Length; i++)
{
strSend += string.Format("{0:X2} ", returnData[i]);
}
if (IsShowMsg)
{
Log(InfoType.Info,"串口" + portName + " 收到数据:" + strSend + "");
}
}
return result;
}
/// <summary>
/// 发送数据并获取返回值
/// </summary>
/// <param name="data">发送的数据</param>
/// <param name="outTime">超时时间</param>
/// <returns>返回值的长度</returns>
private static byte[] SendCommand(string portName, byte[] data, int outTime, int reviceLength)
{
if (outTime <100)
{
outTime = 100;
}
byte[] returnData = null;
try
{
if (data == null)
{
return returnData;
}
string strSend = "";
for (int i = 0; i < data.Length; i++)
{
strSend += string.Format("{0:X2} ", data[i]);
}
if (strSend.Equals(""))
{
return returnData;
}
if (IsShowMsg)
{
Log(InfoType.Info, "串口" + portName + " 写入数据:" + strSend + "");
}
AcSerialBean bean = GetSerialBean(portName);
if (bean == null)
{
Log(InfoType.Debug,"ACServerManager SendCommand 试图向未打开串口【" + portName + "】写入数据:" + strSend + "。");
}
else
{
int ret= bean.SendCommand(data, ref returnData, outTime, reviceLength);
string rDataStr = AcSerialBean.ByteToString(returnData);
if (!ret.Equals(reviceLength))
{
Log(InfoType.Error,"串口" + portName + " 写入数据:" + strSend + ",预计返回字节数【"+reviceLength+"】实际返回【"+ret+"】【"+rDataStr+"】");
}
System.Threading.Thread.Sleep(2);
}
}
catch (Exception ex)
{
Log(InfoType.Info,ex.ToString());
}
return returnData;
}
/// <summary>
/// 发送数据并获取返回值
/// </summary>
/// <param name="data">发送的数据</param>
/// <param name="outTime">超时时间</param>
/// <param name="result">返回结果,是否发送成功</param>
/// <returns>返回值的长度</returns>
private static byte[] SendCommand(string portName, byte[] data, int outTime, int reviceLength, out bool result)
{
if (outTime < 100)
{
outTime = 100;
}
byte[] returnData = null;
result = false;
try
{
if (data == null)
{
return returnData;
}
string strSend = "";
for (int i = 0; i < data.Length; i++)
{
strSend += string.Format("{0:X2} ", data[i]);
}
if (strSend.Equals(""))
{
return returnData;
}
if (IsShowMsg)
{
Log(InfoType.Info,"串口" + portName + " 写入数据:" + strSend + "");
}
AcSerialBean bean = GetSerialBean(portName);
if (bean == null)
{
Log(InfoType.Debug,"ACServerManager SendCommand 试图向未打开串口【" + portName + "】写入数据:" + strSend + "。");
}
else
{
int ret = bean.SendCommand(data, ref returnData, outTime, reviceLength);
if (!ret.Equals(reviceLength))
{
string datastr = AcSerialBean.ByteToString(returnData);
Log(InfoType.Error,"串口" + portName + " 写入数据:" + strSend + ",预计返回字节数【" + reviceLength + "】实际返回【" + ret + "】:"+ datastr);
}
else
{
result = true;
}
System.Threading.Thread.Sleep(2);
}
}
catch (Exception ex)
{
Log(InfoType.Info,ex.ToString());
}
return returnData;
}
private static void WriteData(string portName, int slvAddr, string addr, string data, byte cmd, int length)
{
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, cmd, addr, data, length);
SendData(portName, dataArray);
}
private static void SendStr(string portName, int slvAddr, string str)
{
//string str = txtSendStr.Text;
byte[] data = AcSerialBean.StringToByte(str);
data[data.Length - 1] = 0x00;
data[data.Length - 2] = 0x00;
data = ACCMDManager.buildCheckData(data, data.Length - 2);
SendData(portName, data);
}
private static void Stop(string portName, int slvAddr)
{
//RunBlock(6);
string addr = ACCMDManager.Stop_Addr;
string data = "FF00";
//byte cmd = 0x05;
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
System.Threading.Thread.Sleep(1000);
data = "0000";
dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
private static void OpenAndCloseSTB(string portName, int slvAddr)
{
OnlyOpenSTB(portName, slvAddr);
System.Threading.Thread.Sleep(200);
CloseSTB(portName, slvAddr);
System.Threading.Thread.Sleep(SleepMSendons);
}
private static void OnlyOpenSTB(string portName, int slvAddr)
{
string addr = ACCMDManager.STB_Addr;
string data = "FF00";
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
private static void CloseSTB(string portName, int slvAddr)
{
string addr = ACCMDManager.STB_Addr;
string data = "0000";
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
private static void UpdateBlock(string portName, int slvAddr, string blockNum)
{
int preNum = GetAddrValue(portName,slvAddr, ACCMDManager.BlockNo);
if (preNum.Equals(-1) || (!preNum.ToString().Equals(blockNum)))
{
byte[] data = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteRegisters, ACCMDManager.BlockNo, blockNum , 2);
SendData(portName, data);
int value = Convert.ToInt16(blockNum);
UpdateAddrValue(portName,slvAddr, ACCMDManager.BlockNo, value);
Thread.Sleep(SleepMSendons);
}
}
private static void CloseAlarmClear(string portName, int slvAddr)
{
string addr = ACCMDManager.Clear_Alarm_Addr;
string data = "0000";
//byte cmd = 0x05;
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
private static string PreReadAddr = "";
private static string PreReadCoilAddr = "";
private static int GetRegisterData(string portName, byte[] reviceData, string Address)
{
if (reviceData != null && reviceData.Length > 0)
{
string strSend = "";
for (int i = 0; i < reviceData.Length; i++)
{
strSend += string.Format("{0:X2} ", reviceData[i]);
}
if (IsShowMsg)
{
Log(InfoType.Info, "串口" + portName + " 收到数据:" + strSend + "");
}
string strFromat = "{0:X2}";
byte slvAddrR = reviceData[0];
int lenth = reviceData[2];
byte cmd = reviceData[1];
if (cmd.Equals(ACCMDManager.CMD_ReadRegisters) && reviceData.Length > 6 && lenth == 4)
{
string str = string.Format(strFromat, reviceData[5]) + string.Format(strFromat, reviceData[6]) + string.Format(strFromat, reviceData[3]) + string.Format(strFromat, reviceData[4]);
int value = Convert.ToInt32(str.Trim().Replace(" ", ""), 16);
SaveData(portName, slvAddrR, Address, value);
return value;
}
}
return -1;
}
private static int GetCoilData(string portName, byte[] reviceData, string Address)
{
if (reviceData != null && reviceData.Length > 0)
{
string strSend = "";
for (int i = 0; i < reviceData.Length; i++)
{
strSend += string.Format("{0:X2} ", reviceData[i]);
}
if (IsShowMsg)
{
Log(InfoType.Info, "串口" + portName + " 收到数据:" + strSend + "");
}
string strFromat = "{0:X2}";
byte slvAddrR = reviceData[0];
int lenth = reviceData[2];
byte cmd = reviceData[1];
if (cmd.Equals(ACCMDManager.CMD_ReadCoil) && reviceData.Length >= 6 && lenth == 1)
{
string str = string.Format(strFromat, reviceData[3]);
int value = Convert.ToInt32(str.Trim().Replace(" ", ""), 16);
SaveData(portName, slvAddrR, Address, value);
return value;
}
}
return -1;
}
/// <summary>
/// 紧急停止运动
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
public static void SuddenStop(string portName, int slvAddr)
{
// RunBlock(7);
string addr = ACCMDManager.SDStop_Addr;
string data = "FF00";
//byte cmd = 0x05;
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
System.Threading.Thread.Sleep(500);
data = "0000";
dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
/// <summary>
/// 获取伺服当前实际位置
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <param name="rGetCount"></param>
/// <returns></returns>
public static int GetActualtPosition(string portName, int slvAddr, int rGetCount = 3)
{
PreReadAddr = ACCMDManager.ActualPosition;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadRegisters, ACCMDManager.ActualPosition, "0000", 2);
// SendData(portName,dataArray);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 9);
int result = -1;
for (int i = 1; i <= rGetCount; i++)
{
result = GetRegisterData(portName, reviceData, ACCMDManager.ActualPosition);
if (!result.Equals(-1))
{
break;
}
else
{
Log(InfoType.Error, "第" + i + "次获取" + portName + "_" + slvAddr + "的实时位置" + result);
}
Thread.Sleep(180);
}
return result;
}
/// <summary>
/// 清理报警
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
public static void AlarmClear(string portName, int slvAddr)
{
string addr = ACCMDManager.Clear_Alarm_Addr;
string data = "FF00";
//byte cmd = 0x05;
int length = 2;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
System.Threading.Thread.Sleep(200);
data = "0000";
dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_WriteCoil, addr, data, length);
SendData(portName, dataArray);
}
/// <summary>
/// 获取伺服目标位置
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <returns></returns>
public static int GetTargetPosition(string portName, int slvAddr)
{
PreReadAddr = ACCMDManager.TargetPostion;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadRegisters, ACCMDManager.TargetPostion, "0000", 2);
// SendData(portName,dataArray);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 9);
return GetRegisterData(portName, reviceData, ACCMDManager.TargetPostion);
}
/// <summary>
/// 获取伺服报警状态,1=报警中
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <returns></returns>
public static int GetAlarmStatus(string portName, int slvAddr)
{
PreReadCoilAddr = ACCMDManager.Alarm_Status;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadCoil, PreReadCoilAddr, "0000", 1);
//SendData(portName,dataArray);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 6);
return GetCoilData(portName, reviceData, PreReadCoilAddr);
}
/// <summary>
/// 获取伺服忙碌状态,1=忙碌中
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <returns></returns>
public static int GetBusyStatus(string portName, int slvAddr)
{
PreReadCoilAddr = ACCMDManager.BUSYStatus;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadCoil, ACCMDManager.BUSYStatus, "0000", 1);
//SendData(portName,dataArray);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 6);
return GetCoilData(portName, reviceData, ACCMDManager.BUSYStatus);
}
/// <summary>
/// 获取原点返回是否完成的值,1=完成
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <returns></returns>
public static int GetHomeEndStatus(string portName, int slvAddr)
{
PreReadCoilAddr = ACCMDManager.HOME_CMP_Status;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadCoil, ACCMDManager.HOME_CMP_Status, "0000", 1);
//SendData(portName,dataArray);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 6);
return GetCoilData(portName, reviceData, ACCMDManager.HOME_CMP_Status);
}
/// <summary>
/// 获取原点信号值,1=原点亮
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <returns></returns>
public static int GetHomeSingle(string portName, int slvAddr)
{
PreReadCoilAddr = ACCMDManager.Home_Single;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadCoil, ACCMDManager.Home_Single, "0000", 1);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 6);
return GetCoilData(portName, reviceData, ACCMDManager.Home_Single);
}
/// <summary>
/// 获取负极限值,1=负极限亮
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <returns></returns>
public static int GetLimitNegativeSingle(string portName, int slvAddr)
{
PreReadCoilAddr = ACCMDManager.Home_Single;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadCoil, ACCMDManager.Limit_Negative_Single, "0000", 1);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 6);
return GetCoilData(portName, reviceData, ACCMDManager.Home_Single);
}
/// <summary>
/// 获取正极限值,2=正极限亮
/// </summary>
/// <param name="portName"></param>
/// <param name="slvAddr"></param>
/// <returns></returns>
public static int GetLimitPositiveSingle(string portName, int slvAddr)
{
PreReadCoilAddr = ACCMDManager.Home_Single;
byte[] dataArray = ACCMDManager.GetWriteData(slvAddr, ACCMDManager.CMD_ReadCoil, ACCMDManager.Limit_Positive_Single, "0000", 1);
byte[] reviceData = SendCommand(portName, dataArray, ReviceOutTimeMS, 6);
return GetCoilData(portName, reviceData, ACCMDManager.Home_Single);
}
private static int GetAddrValue(string portName, int slvAddr, string addr)
{
int value = -1;
try
{
string name = portName + "_" + slvAddr;
Dictionary<string, int> map = null;
ComAddrValue.TryGetValue(name, out map);
if (map == null)
{
return -1;
}
if (map.ContainsKey(addr))
{
return map[addr];
}
}
catch (Exception ex)
{
Log(InfoType.Error, "UpdateAddrValue出错:" + ex.ToString());
}
return value;
}
private static void UpdateAddrValue(string portName, int slvAddr, string addr, int value)
{
try
{
lock (mapObj)
{
string name = portName + "_" + slvAddr;
Dictionary<string, int> map = null;
ComAddrValue.TryGetValue(name, out map);
if (map == null)
{
map = new Dictionary<string, int>();
ComAddrValue.Add(name, map);
}
if (map.ContainsKey(addr))
{
ComAddrValue[name][addr] = value;
}
else
{
ComAddrValue[name].Add(addr, value);
}
}
}
catch (Exception ex)
{
Log(InfoType.Error, "UpdateAddrValue出错:" + ex.ToString());
}
}
}
/// <summary>
/// 记录最后一次获得的寄存器的值
/// </summary>
public class RegisterInfo
{
public RegisterInfo(int slv, string addr, int data)
{
this.SlvAddr = slv;
this.RegisterAddr = addr;
this.LastData = data;
this.LastTime = new DateTime();
}
public int SlvAddr { get; set; }
public string RegisterAddr { get; set; }
public int LastData { get; set; }
public DateTime LastTime { get; set; }
}
}

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
namespace DeviceLib
{
internal class AcSerialBean
{
#region 全部变量
// internal static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private SerialPort _serialPort = null;
private object lockObj = new object();
//定义委托
//internal delegate void SerialPortDataReceiveEventArgs(string portName, object sender, SerialDataReceivedEventArgs e, byte[] bits);
//定义接收数据事件
//internal event SerialPortDataReceiveEventArgs DataReceived;
//定义接收错误事件
//internal event SerialErrorReceivedEventHandler Error;
//接收事件是否有效 false表示有效
//internal bool ReceiveEventFlag = false;
#endregion
#region 获取串口名
private string protName;
internal string PortName
{
get { return _serialPort.PortName; }
set
{
_serialPort.PortName = value;
protName = value;
}
}
#endregion
#region 获取比特率
private int baudRate;
internal int BaudRate
{
get { return _serialPort.BaudRate; }
set
{
_serialPort.BaudRate = value;
baudRate = value;
}
}
#endregion
#region 默认构造函数
///// <summary>
///// 默认构造函数,操作COM1,速度为9600,没有奇偶校验,8位字节,停止位为1 "COM1", 9600, Parity.None, 8, StopBits.One
///// </summary>
//internal SerialBean()
//{
// _serialPort = new SerialPort();
//}
#endregion
#region 构造函数
///// <summary>
///// 构造函数,
///// </summary>
///// <param name="comPortName"></param>
//internal SerialBean(string comPortName)
//{
// _serialPort = new SerialPort(comPortName);
// _serialPort.BaudRate = 9600;
// _serialPort.Parity = Parity.Even;
// _serialPort.DataBits = 8;
// _serialPort.StopBits = StopBits.One;
// _serialPort.Handshake = Handshake.None;
// _serialPort.RtsEnable = true;
// _serialPort.ReadTimeout = 2000;
// setSerialPort();
//}
#endregion
#region 构造函数,可以自定义串口的初始化参数
/// <summary>
/// 构造函数,可以自定义串口的初始化参数
/// </summary>
/// <param name="comPortName">需要操作的COM口名称</param>
/// <param name="baudRate">COM的速度</param>
/// <param name="parity">奇偶校验位</param>
/// <param name="dataBits">数据长度</param>
/// <param name="stopBits">停止位</param>
internal AcSerialBean(string comPortName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
_serialPort = new SerialPort(comPortName, baudRate, parity, dataBits, stopBits);
_serialPort.RtsEnable = true; //自动请求
_serialPort.ReadTimeout = 3000;//超时
setSerialPort();
}
#endregion
#region 析构函数
/// <summary>
/// 析构函数,关闭串口
/// </summary>
~AcSerialBean()
{
if (_serialPort.IsOpen)
_serialPort.Close();
}
#endregion
#region 设置串口参数
/// <summary>
/// 设置串口参数
/// </summary>
/// <param name="comPortName">需要操作的COM口名称</param>
/// <param name="baudRate">COM的速度</param>
/// <param name="dataBits">数据长度</param>
/// <param name="stopBits">停止位</param>
internal void setSerialPort(string comPortName, int baudRate, int dataBits, int stopBits)
{
if (_serialPort.IsOpen)
_serialPort.Close();
_serialPort.PortName = comPortName;
_serialPort.BaudRate = baudRate;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = dataBits;
_serialPort.StopBits = (StopBits)stopBits;
_serialPort.Handshake = Handshake.None;
_serialPort.RtsEnable = false;
_serialPort.ReadTimeout = 3000;
_serialPort.NewLine = "/r/n";
setSerialPort();
}
#endregion
#region 设置接收函数
/// <summary>
/// 设置串口资源,还需重载多个设置串口的函数
/// </summary>
void setSerialPort()
{
if (_serialPort != null)
{
//设置触发DataReceived事件的字节数为1
_serialPort.ReceivedBytesThreshold = 1;
//接收到一个字节时,也会触发DataReceived事件
// _serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);
//接收数据出错,触发事件
_serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(_serialPort_ErrorReceived);
//打开串口
//openPort();
}
}
#endregion
#region 打开串口资源
/// <summary>
/// 打开串口资源
/// <returns>返回bool类型</returns>
/// </summary>
internal bool openPort()
{
bool ok = false;
//如果串口是打开的,先关闭
if (_serialPort.IsOpen)
_serialPort.Close();
try
{
//打开串口
_serialPort.Open();
ok = true;
}
catch (Exception Ex)
{
ACServerManager.Log(InfoType.Error , Ex.ToString());
//throw Ex;
}
return ok;
}
#endregion
#region 关闭串口
/// <summary>
/// 关闭串口资源,操作完成后,一定要关闭串口
/// </summary>
internal void closePort()
{
//如果串口处于打开状态,则关闭
if (_serialPort.IsOpen)
_serialPort.Close();
}
internal void clearInBuffer()
{
if (_serialPort.IsOpen)
{
_serialPort.DiscardInBuffer();
}
}
internal void clearOutBuffer()
{
if (_serialPort.IsOpen)
{
_serialPort.DiscardOutBuffer();
}
}
#endregion
#region 接收数据出错事件
/// <summary>
/// 接收数据出错事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void _serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
}
#endregion
#region 发送数据string类型
//internal void SendData(string data)
//{ //发送数据
// if (_serialPort.IsOpen)
// {
// lock (lockObj)
// {
// _serialPort.Write(data);
// System.Threading.Thread.Sleep(10);
// }
// }
//}
#endregion
#region 发送数据byte类型
///// <summary>
///// 数据发送
///// </summary>
///// <param name="data">要发送的数据字节</param>
//internal void SendData(byte[] data, int offset, int count)
//{
// string strSend = "";
// for (int i = 0; i < data.Length; i++)
// {
// strSend += string.Format("{0:X2} ", data[i]);
// }
// LOGGER.Debug("【" + _serialPort.PortName + "】发送数据【" + strSend + "】");
// lock (lockObj)
// {
// try
// {
// if (_serialPort.IsOpen)
// {
// _serialPort.DiscardInBuffer();//清空接收缓冲区
// _serialPort.Write(data, offset, count);
// System.Threading.Thread.Sleep(10);
// }
// }
// catch (Exception ex)
// {
// _serialPort.DiscardOutBuffer();
// ACServerManager.Log(InfoType.Error ,LOGGER, "SendData ERROR:" + ex.ToString(), 21);
// }
// }
//}
#endregion
#region 发送命令
/// <summary>
/// 发送命令
/// </summary>
/// <param name="SendData">发送数据</param>
/// <param name="ReceiveData">接收数据</param>
/// <param name="Overtime">超时时间</param>
/// <returns></returns>
internal int SendCommand(byte[] SendData, ref byte[] ReceiveData, int Overtime,out bool isOk)
{
isOk = false;
if (_serialPort.IsOpen)
{
//lock (lockObj)
if(Monitor.TryEnter(lockObj,Overtime+50))
{
//Monitor.Enter(lockObj);
try
{
_serialPort.DiscardInBuffer(); //清空接收缓冲区
_serialPort.Write(SendData, 0, SendData.Length);
int num = 0, ret = 0;
System.Threading.Thread.Sleep(10);
while (num++ < Overtime)
{
if (_serialPort.BytesToRead >= ReceiveData.Length)
break;
System.Threading.Thread.Sleep(1);
}
if (num >= Overtime)
{
ACServerManager.Log(InfoType.Error ,PortName + " 发送数据" + ByteToString(SendData) + "等待接受数据超时");
}
if (_serialPort.BytesToRead >= ReceiveData.Length)
{
ret = _serialPort.Read(ReceiveData, 0, ReceiveData.Length);
}
else
{
ret = _serialPort.Read(ReceiveData, 0, _serialPort.BytesToRead);
}
isOk = true;
return ret;
}
catch (Exception ex)
{
isOk = false;
ACServerManager.Log(InfoType.Error , "SendCommand ERROR:" + ex.ToString());
}
finally
{
Monitor.Exit(lockObj);
}
}
else
{
ACServerManager.Log(InfoType.Error ,PortName + " 发送数据" + ByteToString(SendData) + "失败,未得到锁");
}
}
return -1;
}
private byte PreSlvAddr = 0;
/// <summary>
/// 发送命令
/// </summary>
/// <param name="SendData">发送数据</param>
/// <param name="ReceiveData">接收数据</param>
/// <param name="Overtime">超时时间</param>
/// <param name="ReceiveLength">接收数据长度</param>
/// <returns></returns>
internal int SendCommand(byte[] SendData, ref byte[] ReceiveData, int Overtime, int ReceiveLength)
{
if (_serialPort == null)
{
ACServerManager.Log(InfoType.Error ,PortName+" 发送数据"+ByteToString(SendData)+ "失败,_serialPort=null");
return -1;
}
if (_serialPort.IsOpen)
{
if (Monitor.TryEnter(lockObj, Overtime + 80))
{
//Monitor.Enter(lockObj);
try
{
//判断是否需要休眠
if (SendData != null && SendData.Length > 0)
{
if (!SendData[0].Equals(PreSlvAddr))
{
Thread.Sleep(50);
PreSlvAddr = SendData[0];
}
}
_serialPort.DiscardInBuffer(); //清空接收缓冲区
_serialPort.Write(SendData, 0, SendData.Length);
int num = 0, ret = 0;
//System.Threading.Thread.Sleep(10);
if (ReceiveData == null)
{
ReceiveData = new byte[ReceiveLength];
}
while (num++ < Overtime)
{
if (_serialPort.BytesToRead >= ReceiveData.Length)
break;
System.Threading.Thread.Sleep(1);
}
if (num >= Overtime)
{
ACServerManager.Log(InfoType.Error ,PortName + " 发送数据" + ByteToString(SendData) + "等待接受数据超时");
}
if (_serialPort.BytesToRead >= ReceiveData.Length)
{
ret = _serialPort.Read(ReceiveData, 0, ReceiveData.Length);
}
else
{
ret = _serialPort.Read(ReceiveData, 0, _serialPort.BytesToRead);
}
return ret;
}
catch (Exception ex)
{
ACServerManager.Log(InfoType.Error ,PortName + " 发送数据" + ByteToString(SendData) + " 出错:"+ex.ToString());
}
finally
{
Monitor.Exit(lockObj);
}
}
else
{
ACServerManager.Log(InfoType.Error ,PortName + " 发送数据" + ByteToString(SendData) + "失败,未得到锁");
}
}
return -1;
}
#endregion
#region 获取串口
/// <summary>
/// 获取所有已连接短信猫设备的串口
/// </summary>
/// <returns></returns>
internal string[] serialsIsConnected()
{
List<string> lists = new List<string>();
string[] seriallist = getSerials();
foreach (string s in seriallist)
{
}
return lists.ToArray();
}
#endregion
#region 获取当前全部串口资源
/// <summary>
/// 获得当前电脑上的所有串口资源
/// </summary>
/// <returns></returns>
internal string[] getSerials()
{
return SerialPort.GetPortNames();
}
#endregion
#region 字节型转换16
/// <summary>
/// 把字节型转换成十六进制字符串
/// </summary>
/// <param name="InBytes"></param>
/// <returns></returns>
internal static string ByteToString(byte[] InBytes)
{
string StringOut = "";
foreach (byte InByte in InBytes)
{
StringOut = StringOut + String.Format("{0:X2} ", InByte);
}
return StringOut;
}
#endregion
#region 十六进制字符串转字节型
/// <summary>
/// 打包方法,可以将十六制字符串转成byte[] ,字符串没有空格
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
internal static byte[] StringToByte(string s)
{
string temps = ReplaceSpace(s);
if (temps.Length % 2 != 0)
{
temps = "0" + temps;
}
byte[] tempb = new byte[50];
int j = 0;
for (int i = 0; i < temps.Length; i = i + 2, j++)
{
tempb[j] = Convert.ToByte(temps.Substring(i, 2), 16);
}
byte[] send = new byte[j];
Array.Copy(tempb, send, j);
return send;
}
//除去空格
internal static string ReplaceSpace(string str)
{
string putout = "";
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{ putout += str[i]; }
}
return putout;
}
#endregion
#region 计算校验码
internal static void CalculateBCC(byte[] pByte, int nNumberOfBytes, out ushort pChecksum)
{
byte check = 0;
check = (byte)(pByte[0] ^ (pByte[1]));
for (int i = 2; i < pByte.Length; i++)
{
check = (byte)(check ^ (pByte[i]));
}
pChecksum = check;
}
internal static void CalculateCRC(byte[] pByte, int nNumberOfBytes, out ushort pChecksum)
{
int nBit;
ushort nShiftedBit;
pChecksum = 0xFFFF;
for (int nByte = 0; nByte < nNumberOfBytes; nByte++)
{
pChecksum ^= pByte[nByte];
for (nBit = 0; nBit < 8; nBit++)
{
if ((pChecksum & 0x1) == 1)
{
nShiftedBit = 1;
}
else
{
nShiftedBit = 0;
}
pChecksum >>= 1;
if (nShiftedBit != 0)
{
pChecksum ^= 0xA001;
}
}
}
}
#endregion
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("DeviceLibrary")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DeviceLibrary")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("a26e4dbe-908a-40f4-88a5-dab0d27cbe4b")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!