Как использовать событие dataReceived объекта порта SerialPort в C #? - PullRequest
19 голосов
/ 21 января 2009

Я пытаюсь создать небольшое приложение для сбора данных, полученных от внешнего датчика, подключенного к COM10. Я успешно создал небольшой консольный объект и приложение C #, который открывает порт и передает данные в файл в течение фиксированного периода времени, используя цикл for.

Я хотел бы преобразовать это приложение, чтобы вместо него использовать событие dataReceived для потоковой передачи. После прочтения Top 5 SerialPort Tips я все еще не могу понять, как это работает, и не знаю, чего мне не хватает. Я переписал консольное приложение так, чтобы весь код был в Main и вставлен ниже. Может ли кто-нибудь помочь мне объяснить, почему не вызывается обработчик событий port_OnReceiveDatazz, хотя я знаю, что аппаратные данные отправляют в порт данные?

Спасибо

Азим

PS: Спасибо @ Gabe , @ Jason Down и @ abatishchev за все предложения. Я в тупике и не могу заставить обработчик событий работать. Возможно, это как-то связано с устройством. Я могу жить только чтением порта в потоке и передачей данных прямо в файл.


Код


namespace serialPortCollection
{   class Program
    {
        static void Main(string[] args)
        {

            const int bufSize = 2048;
            Byte[] buf = new Byte[bufSize]; //To store the received data.

            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            // Wait for data or user input to continue.
            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            const int bufSize = 12;
            Byte[] buf = new Byte[bufSize];
            Console.WriteLine("DATA RECEIVED!");
            Console.WriteLine(spL.Read(buf, 0, bufSize));
        }
    }
}

Ответы [ 7 ]

12 голосов
/ 21 января 2009

Я думаю, что ваша проблема - строка: **

sp.DataReceived + = port_OnReceiveDatazz;

Разве это не должно быть:

sp.DataReceived + = новый SerialDataReceivedEventHandler (port_OnReceiveDatazz);

** Не берите в голову, синтаксис в порядке (не понимал ярлык в то время, когда я первоначально ответил на этот вопрос).

Я также видел предложения, чтобы вы включили следующие опции для вашего последовательного порта:

sp.DtrEnable = true;    // Data-terminal-ready
sp.RtsEnable = true;    // Request-to-send

Вам также может потребоваться установить для рукопожатия значение RequestToSend (посредством перечисления рукопожатия).


UPDATE:

Нашел предложение, в котором говорится, что сначала нужно открыть свой порт, а затем назначить обработчик событий. Может быть, это ошибка?

Итак, вместо этого:

sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);
sp.Open();

Сделайте это:

sp.Open();
sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);

Дайте мне знать, как это происходит.

9 голосов
/ 21 января 2009

Прежде всего, я рекомендую использовать следующий конструктор вместо того, который вы используете в данный момент:

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

Далее вы действительно должны удалить этот код:

// Wait 10 Seconds for data...
for (int i = 0; i < 1000; i++)
{
    Thread.Sleep(10);
    Console.WriteLine(sp.Read(buf,0,bufSize)); //prints data directly to the Console
}

И вместо этого просто зацикливайтесь, пока пользователь не нажмет клавишу или что-то вроде этого:

namespace serialPortCollection
{   class Program
    {
        static void Main(string[] args)
        {
            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
            {
                Console.Write(b.ToString());
            }
            Console.WriteLine();
        }
    }
}

Кроме того, обратите внимание на изменения в обработчике событий полученных данных, теперь он должен фактически напечатать буфер.

ОБНОВЛЕНИЕ 1


Я только что успешно выполнил следующий код на моей машине (используя нуль-модемный кабель между COM33 и COM34)

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread writeThread = new Thread(new ThreadStart(WriteThread));
            SerialPort sp = new SerialPort("COM33", 115200, Parity.None, 8, StopBits.One);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            writeThread.Start();

            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
            {
                Console.Write(b.ToString() + " ");
            }
            Console.WriteLine();
        }

        private static void WriteThread()
        {
            SerialPort sp2 = new SerialPort("COM34", 115200, Parity.None, 8, StopBits.One);
            sp2.Open();
            byte[] buf = new byte[100];
            for (byte i = 0; i < 100; i++)
            {
                buf[i] = i;
            }
            sp2.Write(buf, 0, buf.Length);
            sp2.Close();
        }
    }
}

ОБНОВЛЕНИЕ 2


Учитывая весь трафик по этому вопросу в последнее время. Я начинаю подозревать, что либо ваш последовательный порт не настроен должным образом, либо устройство не отвечает.

Я настоятельно рекомендую вам попытаться установить связь с устройством другими способами (я часто использую гипертерминал). Затем вы можете поиграть со всеми этими настройками (битрейт, четность, биты данных, стоп-биты, управление потоком), пока не найдете набор, который работает. В документации на устройство также должны быть указаны эти настройки. Как только я это выяснил, я убедился, что мой .NET SerialPort правильно настроен для использования этих настроек.

Некоторые советы по настройке последовательного порта:

Обратите внимание, что когда я сказал, что вы должны использовать следующий конструктор, я имел в виду, что используйте эту функцию, а не обязательно эти параметры! Вам необходимо ввести параметры для вашего устройства, приведенные ниже настройки являются общими, но могут отличаться для вашего устройства.

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

Также важно, чтобы вы настроили .NET SerialPort на использование того же управления потоком, что и на вашем устройстве (как уже говорили другие люди). Вы можете найти больше информации здесь:

http://www.lammertbies.nl/comm/info/RS-232_flow_control.html

4 голосов
/ 08 июня 2009

У меня была та же проблема с модемом, который ранее работал, а затем однажды просто перестал вызывать событие DataReceived.

В моем случае решение было очень случайным: включить RTS, например:

sp.RtsEnable = true;

Понятия не имею, почему это сработало с этим конкретным комплектом (вообще-то, не со связным), и почему это сработало, а затем остановилось, но может помочь кому-то еще однажды, поэтому просто разместите его на всякий случай ...

3 голосов
/ 21 января 2009

Кстати, вы можете использовать следующий код в вашем обработчике событий:

switch(e.EventType)
{
  case SerialData.Chars:
  {
    // means you receives something
    break;
  }
  case SerialData.Eof:
  {
    // means receiving ended
    break;
  }
}
1 голос
/ 12 марта 2014

Может быть очень хорошо, если Console.ReadLine блокирует ваш обратный вызов Console.Writeline, на самом деле. Пример на MSDN выглядит ПОЧТИ идентичны, за исключением того, что они используют ReadKey (который не блокирует консоль).

1 голос
/ 14 марта 2011

Я полагаю, что это не сработает, потому что вы используете консольное приложение и не работает цикл событий. Цикл событий / насос сообщений, используемый для обработки событий, устанавливается автоматически при создании приложения Winforms, но не для консольного приложения.

0 голосов
/ 02 октября 2016

Имейте в виду, что существуют проблемы с использованием .NET / C # и любого COM-порта выше COM9.

См .: HOWTO: указать последовательные порты больше, чем COM9

Существует обходной путь в формате: "\\. \ COM10", который поддерживается в базовом методе CreateFile, но .NET не позволяет использовать этот формат обходного пути; ни конструктор SerialPort, ни свойство PortName не разрешат имя порта, начинающееся с "\"

Я изо всех сил пытался получить надежную связь с COM10 в C # /. NET. Например, если у меня есть устройство на COM9 и COM10, трафик, предназначенный для COM10, направляется на устройство на COM9! Если я удаляю устройство на COM9, трафик COM10 идет на устройство на COM10.

Я до сих пор не понял, как использовать дескриптор, возвращенный CreateFile, для создания объекта SerialPort в стиле C # / .NET, если бы я знал, как это сделать, то я думаю, что мог бы отлично использовать COM10 + из C #.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...