Я пытаюсь установить связь с устройством через RS-485 через последовательный порт.Все работает нормально, пока мы не попытаемся увеличить скорость связи, чтобы проверить ограничение скорости карты, и тогда возникает странная проблема.В основном мы отправляем первую команду с изображением в качестве аргументов, а затем еще одну команду для отображения этого изображения.После каждой команды карта отвечает, что команда была принята хорошо.Но мы достигаем пределов слишком рано, и карта должна обрабатывать намного больше.
Поэтому мне интересно, так как передача и прием проходят по одному и тому же проводу, если происходит какое-то столкновение данных?И я должен ждать, чтобы получить все данные?Является ли SerialDataReceivedEventHandler слишком медленным в этой ситуации, и я должен продолжать читать байты в цикле true в отдельном потоке и сигнализировать другому потоку, как только получено полное сообщение?
Другая информация:
- У нас уже есть протокол для связи: startdelimiter, data, CRC16, enddelimiter
- Отправка двумя командами - это способ, которым мы это делаем, и его нельзя изменить.
- BaudRate определено в 115200
- Инженер все еще работает над программой на карте, поэтому проблема также может быть на его конце.
- Английский не мой родной язык, поэтому не стесняйтесь спрашивать, если я не ясно ...:)
Я понимаю, что программирование на SerialPort не моя сила, и я пытался найти какую-то оболочку, но я не нашел ни одной, которая бы соответствовала моим потребностям.Если у кого-то есть один, чтобы предложить мне, что было бы замечательно, или, возможно, у кого-то есть представление о том, что может быть не так.В любом случае здесь немного кода:
Поток, отправляющий фреймы:
public void SendOne()
{
timerLast = Stopwatch.GetTimestamp();
while (!Paused && conn.ClientConnState == Connexion.ConnectionState.Connected)
{
timerNow = Stopwatch.GetTimestamp();
if ((timerNow - timerLast) / (double)Stopwatch.Frequency >= 1 / (double)fps)
{
averageFPS.Add((int)((double)Stopwatch.Frequency / (timerNow - timerLast)) + 1);
if (averageFPS.Count > 10) averageFPS.RemoveAt(0);
timerLast = Stopwatch.GetTimestamp();
if (atFrame >= toSend.Count - 1)
{
atFrame = 0;
if (!isLoop)
Paused = true;
}
SendColorImage();
}
}
public void SendColorImage()
{
conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Request.SendImage, toSend[++atFrame]));
WaitForResponse();
conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Request.DisplayImage, VIP16.DisplayOnArg));
WaitForResponse();
}
private void WaitForResponse()
{
Thread.Sleep(25);
}
Так что WaitForResponse () имеет решающее значение, потому что, если я отправлю другую команду до того, как карта ответит, она сойдет с ума.Хотя я ненавижу использовать Thread.Sleep (), потому что он не очень точный, плюс он ограничивает мою скорость до 20 кадров в секунду, и если я использую что-то ниже 25 мс, риск сбоя гораздо выше.Поэтому я собирался изменить Thread.Sleep на «Чтение байтов, пока не будет получено все сообщение» и игнорировать DataReceivedEvent ... просто интересно, если я полностью не в курсе?
Tx много!
ОБНОВЛЕНИЕ 1
Первое спасибо Брэду и 500 - Внутренняя ошибка сервера!Но я решил пока придерживаться последовательного порта .NET и улучшить точность Thread.Sleep (с timebeginperiod).Я решил дождаться получения полного ответа и синхронизировал свои потоки примерно так, используя ManualResetEventSlim (для скорости):
public static ManualResetEventSlim _waitHandle = new ManualResetEventSlim(false);
Затем я изменил SendColorIMage на:
public void SendColorImage()
{
conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Requetes.SendImage, toSend[++atFrame]));
WaitForResponse();
conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Requetes.DisplayImage, VIP16.DisplayOnArg));
WaitForResponse2();
}
private void WaitForResponse()
{
Connexion._waitHandle.Wait(100);
Thread.Sleep(20);
}
private void WaitForResponse2()
{
Connexion._waitHandle.Wait(100);
//Thread.Sleep(5);
}
При вызове SerialDataReceivedEventHandler:
public void Recevoir(object sender, SerialDataReceivedEventArgs e)
{
if (!msg.IsIncomplete)
msg = new Vip16Message();
lock (locker)
{
if (sp.BytesToRead > 0)
{
byte[] byteMsg = new byte[sp.BytesToRead];
sp.Read(byteMsg, 0, byteMsg.Length);
msg.Insert(byteMsg);
}
}
if (!msg.IsIncomplete)
{
_waitHandle.Set();
if (MessageRecu != null)
MessageRecu(msg.toByte());
}
}
Итак, я обнаружил, что после второй команды мне вообще не нужно вызывать Thread.Sleep ... а после первой мне нужно было поспать хотя бы20 мс для карты, чтобы не врезаться.Так что я думаю, что это время, когда карта должна получить / обработать все изображение до его пикселя.И столкновение данных на самом деле не должно происходить, так как я жду, пока не прибудет целое сообщение, что означает, что проблема не на моем конце!ДА!: p