我正在与DPS5020电源通信,以获得电压和电流。SMPS数据输出在数据包的末尾不包含任何分隔符,所以我认为它引起了问题。当我使用串行终端程序查询SMPS时,每次都得到正确的数据包,但是当我使用C#程序查询时,没有70%的数据。in数据包大小为9字节。我使用了serial_port.Read(buffer, 0, 9),但即使如此,也存在错误。这里有人能帮我吗?我的密码在下面。
主要功能
private void ovcRead_Click(object sender, EventArgs e)
{
byte[] sendbyte = power2.PowerSupply_GetOVC(); // get over current value
try
{ serial_pow2.Write(sendbyte, 0, sendbyte.Length);
SMPS2_timer.Enabled = true;
textBox2.Text = "";
}
catch
{ MessageBox.Show(serial_pow2.PortName + " port error"); }
}
private void ser_AVDD_DataRx(object sender, SerialDataReceivedEventArgs e)
{
//if (SMPS2_Tick == false)
// return;
//SMPS2_Tick = true;
byte[] readb = new byte[9];
int s = serial_pow2.Read(readb, 0, 9);
Action Receive = () =>
{
if (power2.getOutCur == true)
{
decimal volt, cur;
power2.processOCP(readb, out volt, out cur); // process over current raw data
power2.getOutCur = false;
if (volt != 99.99m && cur != 99.99m)
textBox2.Text = volt + " V, " + cur + " A." + "; " + readb[0].ToString("X2") + " " + readb[1].ToString("X2") + " " + readb[2].ToString("X2") + " " + readb[3].ToString("X2") + " " + readb[4].ToString("X2") + " " + readb[5].ToString("X2") + " " + readb[6].ToString("X2") + " " + readb[7].ToString("X2") + " " + readb[8].ToString("X2");
}
};
this.Invoke(new Action(Receive));
serial_pow2.DiscardInBuffer();
}
private void SMPS2_timer_Tick(object sender, EventArgs e)
{
SMPS2_timer.Enabled = false;
SMPS2_Tick = true;
}类Power2函数。
public byte[] PowerSupply_GetOVC()
{
UInt16 CRC_high = 0;
UInt16 CRC_low = 0;
int i = 0;
getOutCur = true;
int[] supplySet = { 0x01, 0x03, 0x00, 0x02, 0x00, 0x02 }; // get output volt, current
byte[] sendbyte = new byte[supplySet.Length + 2];
Modbus_CRC_Check(supplySet, out CRC_high, out CRC_low);
for (i = 0; i < supplySet.Length; i++)
sendbyte[i] = Convert.ToByte(supplySet[i]);
sendbyte[i++] = Convert.ToByte(CRC_low);
sendbyte[i++] = Convert.ToByte(CRC_high);
return sendbyte;
}
public void processOCP(byte[] readb, out decimal volt, out decimal cur)
{
try
{
int t = readb[3];
t <<= 8;
int y = readb[4];
int vol = (t + y);
volt = (decimal)vol / 100;
t = readb[5];
t <<= 8;
y = readb[6];
int curr = (t + y);
cur = (decimal)curr / 100;
}
catch
{
volt = 99.99m;
cur = 99.99m;
}
}
void Modbus_CRC_Check(int[] data_array, out UInt16 CRC_high, out UInt16 CRC_low)
{
UInt16 crc = 65535;
for (int i = 0; i < data_array.Length; i++)
{
crc ^= (ushort)data_array[i];
for (int j = 0; j < 8; j++)
{
if ((crc & 1) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
CRC_low = (ushort)(crc & 0x00FF);
CRC_high = (ushort)(crc >> 8);
}当使用终端时,输入和输出数据如下:
input command: 01 03 00 02 00 02 65 CB
output data : 01 03 04 00 62 00 00 5B ED当值不正确时使用C#:
input command: 01 03 00 02 00 02 65 CB
output data1: 01 03 04 00 62 00 00 5B ED
output data2: 01 03 04 00 00 00 00 00 00
output data3: 01 00 00 00 00 00 00 00 00我尝试设置ReadTimeout值,并在串行接收事件的开头使用计时器检查,但是结果是一样的。
发布于 2020-05-15 03:30:04
我想我解决了。我一直怀疑程序正在接收碎片的数据。如果数据长度不是9,我将数据存储在临时缓冲区中。在下一次读取中,将最新的数据连接到串行口事件处理中的临时缓冲区。现在我得到了正确的数据。
我就是这样做的。
private void ovcRead_Click(object sender, EventArgs e)
{
byte[] sendbyte = power1.PowerSupply_GetOVC();
try
{ serial_pow1.Write(sendbyte, 0, sendbyte.Length); }
catch
{ MessageBox.Show(serial_pow1.PortName + " port error"); }
sendbyte = power2.PowerSupply_GetOVC();
try
{ serial_pow2.Write(sendbyte, 0, sendbyte.Length);
query = true;
textBox2.Text = "";
}
catch
{ MessageBox.Show(serial_pow2.PortName + " port error"); }
}
byte[] readb = new byte[100];
int cnt = 0;
int prevlen = 0;
int newlen = 0;
private void ser_AVDD_DataRx(object sender, SerialDataReceivedEventArgs e)
{
int bytes = serial_pow2.BytesToRead;
byte[] readc = new byte[bytes];
serial_pow2.Read(readc, 0, bytes);
if (bytes < 9)
{
if (query == true)
{
readc.CopyTo(readb, 0);
prevlen = readc.Length;
query = false;
}
else
{
try
{
readc.CopyTo(readb, prevlen);
newlen = prevlen + readc.Length;
}
catch (Exception ex)
{
MessageBox.Show(readc.Length + "/n" + ex.Message);
}
}
}
else
{
readc.CopyTo(readb, 0);
}
Action Receive = () =>
{
if (readc.Length == 9)
{
prevlen = 0;
cnt = 0;
decimal volt, cur;
power2.processOCP(readc, out volt, out cur);
power2.getOutCur = false;
textBox2.Text = volt + " V, " + cur + " A." + "; " + readb[0].ToString("X2") + " " + readb[1].ToString("X2") + " " + readb[2].ToString("X2") + " " + readb[3].ToString("X2") + " " + readb[4].ToString("X2") + " " + readb[5].ToString("X2") + " " + readb[6].ToString("X2") + " " + readb[7].ToString("X2") + " " + readb[8].ToString("X2");
//if (volt != 99.99m && cur != 99.99m)
}
else
{
textBox2.Text = "";
byte[] temp = new byte[newlen];
for (int b = 0; b < newlen; b++)
{
textBox2.Text += readb[b].ToString("X2") + " ";
}
}
};
this.Invoke(new Action(Receive));
}发布于 2020-05-14 08:55:04
这个问题可能是由serial_pow2.DiscardInBuffer()引起的。
除非您知道缓冲区中不需要数据,否则不要丢弃它。
如果您发出两个请求而只读取一个响应,serial_pow2.DiscardInBuffer()将在缓冲区中丢弃第二个响应。
由于您的代码片段是由按钮初始化的,我无法保证您如何提出请求并获得响应。
我的建议是不使用DiscardInBuffer,除非您正在初始化或关闭应用程序,否则可能会丢失数据。
https://stackoverflow.com/questions/61733323
复制相似问题