Страницы

Поиск по вопросам

Показаны сообщения с ярлыком com-порт. Показать все сообщения
Показаны сообщения с ярлыком com-порт. Показать все сообщения

четверг, 13 февраля 2020 г.

Как ловить данные из com-порта и использовать в своих программах?

#arduino #com_порт


Возникла необходимость получать данные с Arduino, к ней подключен RC522 и в мониторе
порта выводится 1 строка чисел, мне хочется чтобы при считывании эта строка 
1)выводилась на экран
2)записывалась в текстовик 
3)Отправлялась на сервер
Такое возможно?
    


Ответы

Ответ 1



Есть два варианта либо искать в интернете программу, которая слушает СОМ-порт и как-то пересылать на сервер, либо писать программу самому. Во втором случае нужно определится с языком программирования. Например, если вы решите использовать C#, то здесь есть фрагмент кода, который можно незначительно изменить и получить желаемый вами результат. Обновление чтение моментальное. Данные пришли данные отобразились. Можете изменять таймауты получения и отправки вручную (это миллисекунды). Программа видит все что пришло в ком порт, неважно какой источник данных. Единственное что замечу в вашем случае возможно придется использовать не ReadExisting, a ReadByte. Зависит от формата передаваемых данных, нужно смотреть. Если будут вопросы создавайте новый вопрос, поможем.

Ответ 2



Возможно, вам окажется не бесполезной моя статья об этом. Host-клиент Arduino на C (Linux)

суббота, 8 февраля 2020 г.

Как на Си передать информацию от микроконтроллера на COM-порт?

#cpp #c #микроконтроллеры #com_порт


Занимаюсь изучением программирования микроконтроллеров АВР, и столкнулся с вопросом
передачи данных от микроконтроллера на ПК через ком порт. Пишу на Си, МК Atmel AtMega32. 
    


Ответы

Ответ 1



Для передачи информации от МК на COM-порт ПК используется интерфейс RS-232. На микроконтроллерах AVR он называется USART(универсальный синхронно-асинхронный приемо передатчик). Вы написали, что программа на Си, но не указали какой компилятор Вы используете, поэтому ниже приведу программу написанную в CodeVision AVR, но перенести ее на любой другой C компилятор микроконтроллеров AVR не должно составить особых сложностей. Есть два пути создания такого рода ПО. 1) Воспользоваться стандартным генератором начального кода, который имеется в CodeVisionAVR. Для этого нужно выполнить следующие шаги. а) при создании нового проекта, выбрать "использовать CodeWizard" б) перейти на вкладку USART и там поставить галочки перед приемником и передатчиком, то есть активизировать их. в) задать скорость приема передачи информации и другие параметры, синхронность асинхронность, кол-во стоп битов и т.д. г) нажать генерировать ПО д) далее используя стандартную библиотеку ввода-вывода отправлять и принимать информацию. 2) Написать ручками ниже приведенный код: #include #include #include void main(void) { // Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00; // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00; DDRB=0x0C; // Port C initialization // Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out // State7=0 State6=0 State5=T State4=T State3=T State2=T State1=0 State0=0 PORTC=0x00; DDRC=0xC3; // Port D initialization // Func7=Out Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=0 State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x88; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC0 output: Non-Inverted PWM TCCR0=0x6B; TCNT0=0x00; OCR0=0x5F; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC2 output: Non-Inverted PWM ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x5F; // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00; MCUCSR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00; /// USART initialization // Параметры соединения: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 38400 UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x19; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; while (1) { int a; a = 5; unsigned char get; // Отправить что нибудь: printf("%d\n\r", a); // Принять get = getchar(); //Отправить принятое: printf("%d\n\r", get); } } Но не забывайте, прежде чем организовать прием-передачу информации посредством RS232 необходимо согласовать логические уровни. И соединять надо приемник с передатчиком!) Как то так.

Как послать данные на ком-порт?

#c_sharp #com_порт


надо послать 0x55 на 3 ком-порт с одним стоп битом.

    using System;
    using System.IO.Ports;

    namespace Com
    {
        class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    SerialPort _serialPort = new SerialPort("COM3",
                                              2400,
                                              Parity.None,
                                              8,
                                              StopBits.One);
                    _serialPort.Handshake = Handshake.None;

                    _serialPort.Open();
                    _serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

                    byte sent = 0x55;
                    Console.WriteLine("sent: {0}", sent);
                    _serialPort.Write(new byte[1] { sent }, 0, 1);

                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception:, {0}", e);
                }
            }
            private static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                SerialPort sp = (SerialPort)sender;
                string indata = sp.ReadExisting();
                Console.WriteLine("Data Received:, {0}", indata);          
                Console.ReadLine(); //Pause
            }
        }
    }


Вроде все верно. Но программа ничего не показывает. Где может закрасться ошибка?  
    


Ответы

Ответ 1



Причин может быть много: возможно у вас в системе несколько СОМ-портов и вы отправляете не на тот; устройство которому вы отправляете посылку ничего не отвечает; скорость не подходит, попробуйте поставить, например, 1200; попробуйте поменять таймауты. _serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500; Или же ваша программа закрывается еще до получения ответа. Попробуйте так: static void Main(string[] args) { try { SerialPort _serialPort = new SerialPort("COM3", 2400, Parity.None, 8, StopBits.One); _serialPort.Handshake = Handshake.None; _serialPort.Open(); _serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived); byte sent = 0x55; Console.WriteLine("sent: {0}", sent); _serialPort.Write(new byte[1] { sent }, 0, 1); } catch (Exception e) { Console.WriteLine("Exception:, {0}", e); } Console.ReadKey(); }

Ответ 2



Ваша программа ничего не показывает потому что завершается. Поставьте в конец Main вызов Console.ReadLine()

пятница, 24 января 2020 г.

Управление прибором с компьютера через COM порт на Windows

#cpp #visual_studio #visual_cpp #com_порт #rs232


Добрый день,

Мне нужно реализовать программу управления прибором E7-25. Подключается этот прибор
к компьютеру через usb кабель, и при подключении создается виртуальный com-порт. Подключиться
к этому порту у меня получается, передачу данных и прием данных проверял при помощи
Virtual Serial Port Driver, и данные отправляются и передаются, но при отправке данных
на прибор в виде:
char data[] = "(0xAA, 14)";
прибор не отвечает вообще ничего.

Вот код моей программы     

#include "stdafx.h"
#include 
#include 
using namespace std;

HANDLE hSerial;

void ReadCOM()
{
      DWORD iSize;
      char sReceivedChar[20];
      while (true)
      {
            ReadFile(hSerial, &sReceivedChar, 20, &iSize, 0);
            if (iSize > 0)
                cout << sReceivedChar;
      }
}

int _tmain(int argc, _TCHAR* argv[])
{
    LPCTSTR sPortName = L"COM4";  

    hSerial = ::CreateFile(sPortName,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if(hSerial==INVALID_HANDLE_VALUE)
    {
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
        {
            cout << "serial port does not exist.\n";
        }
        cout << "some other error occurred.\n";
    }


    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams))
    {
        cout << "getting state error\n";
    }
    dcbSerialParams.BaudRate=CBR_9600;
    dcbSerialParams.ByteSize=8;
    dcbSerialParams.StopBits=ONESTOPBIT;
    dcbSerialParams.Parity=NOPARITY;
    if(!SetCommState(hSerial, &dcbSerialParams))
    {
        cout << "error setting serial port state\n";
    }
    char data[] = "(0xAA, 64)";
    DWORD dwSize = sizeof(data);
    DWORD dwBytesWritten;
    LPOVERLAPPED ov;

    BOOL iRet = WriteFile (hSerial,data,dwSize,&dwBytesWritten ,NULL);

    cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. "
<< endl;

    while(1)
    {
        ReadCOM();
    }
    return 0;
}


В документации к прибору написано, что команды ему нужно посылать в следующем формате
Формат обмена:

ПК — E7-25: 0xAA, №команды, [параметры].
Е7-25 — ПК: 0xAA, №команды, [параметры].


То есть вот что должна возвращать та команда, которую я по умолчанию отправляю

    64 – Получить имя прибора
    ПК — (0xAA, 64); E7-25 — (0xAA, 64, “Е725”)


Поэтому  у меня есть вопросы. 
Правильно ли я отправляю данные в порт? И правильно ли я их принимаю из порта?
Заранее спасибо.
    


Ответы

Ответ 1



Протокол связи с прибором у Вас - очевидно бинарный, Вы сами его привели. Затем Вы зачем-то посчитали двоичные данные - строкой, а потом добавили по бокам ещё два байта скобок плюс нулевой байт на конце: char data[] = "(0xAA, 64)"; // эквивалентно: char data[11] = {'(', '0', 'x', 'A', 'A', ',', ' ', '6', '4', ')', 0x00} Зачем это было сделано? Возможно, стоит подучить синтаксис. Нужно сформировать массив этих двух байтов, чтобы не было ничего лишнего char data[2] = {0xAA, 64}; DWORD dwSize = 2; // ... После чего просто отправить эти два байта в устройство.

четверг, 23 января 2020 г.

COM Порт в python: как ждать данные, не нагружая CPU

#python #serial #com_порт


Есть программа, которая принимает данные из COM порта. Возникла проблема, как заставить
программу ждать данные и не выполняться дальше? 

При использовании бесконечного цикла while, программа нагружает ЦП до 50%.

forchar = 0
idcom = []

ser = serial.Serial(
    port = 'COM2',\
    baudrate=2400,\
    parity=serial.PARITY_NONE,\
    stopbits=serial.STOPBITS_ONE,\
    bytesize=serial.EIGHTBITS,\
    timeout=0)

print("connected to: " + ser.portstr)
count=1

while True:
    for line in ser.readline():
        forchar = forchar + 1
        idcom.append(line)
    if forchar >= 13:
        break

    


Ответы

Ответ 1



У вас порт настроен на неблокирующее чтение, так как установлен timeout=0, Либо уберите эту опцию, либо напишите timeout=None, тогда порт у вас будет ждать данные, до тех пор пока они не появятся. Если же вам все таки нужно неблокирующее соединение, то в цикл while надо добавить небольшую задержку time.sleep, тогда нагрузка процессора уйдет.

Ответ 2



Еще есть такая конструкция: while True: while ser.inWaiting() == 0: pass #необходимая работа с данными... Тут выполняется проверка на наличие данных в очереди порта. Такой способ ожидания, ЦП не нагружает совсем.

Ответ 3



Так понятнее while ser.inWaiting(): data = ser.read() пока в порте нет данных чтение не выполняетса

Ответ 4



допустим def recCode(data):# и поехали проверять по условиям - например if data == (b'\x05sRR\r\n') print(u'я получил сообщение ') while True: while ser.inWaiting() > 0:# даже если мы поставим без условия data = ser.readline() recCode(data) при таком построении алгоритма while True будет выполнятся постоянно и recCode(data) будет вызываться при приёме каждого символа (байта) в порт, а если 1 количество байтов в пакете не известно(работа по стартовому и конечному символу) или 2 надо ещё обслуживать графический интерфейс и в добавок 3 отправлять данные (сообщения ) в порт , то некоторые символы (принимаемые ) могут потеряться , да и программа (не зависимо сколько ядер у процессора ) будет занята только этим , а если надо 2 порта обслуживать ? в ассемблере (avr контроллеры), в VB6(x86 и 64), есть возможность применения аппаратных прерываний , т е событие (приём символа портом ) может (при правильной настройке аппаратного узла контроллера или машины), остановить выполнение (или перенаправить поток команд) основного тела программы , выполнить подпрограмму (прерывание) приёма одного символа с возможностью формирования строки по стартовым и конечным символам (\х05 и \r\n) и после приёма конечного символа непосредственно в подпрограмме (если условий мало ) обработать - изменив переменные или, выставить флаг готовности принятого сообщения для основной программы , или изменив глобальную переменную для других процессов. тогда while True может заниматься (допустим ) проверкой флагов готовности сообщения одного , второго , н-ого порта , обновлением процессов графической оболочки типа root=Tk() ..(графические элементы ) , и в место root.vfinloop() использовать root.update(), тк как графические интерфейсы управления достаточно медленные процессы

суббота, 4 января 2020 г.

Как правильно открыть COM порт

#c_sharp #com_порт


На столе лежит Gsm модуль RX 101 от "Телеофис", хочу пообщаться с ним из кода, но
не получается.

Так же есть две программы для диагностики модуля, которые успешно связываются с модулем
и успешно общаются по AT протоколу. То есть модуль рабочий.

А теперь что происходит когда я пытаюсь обратиться к модулю из кода - ничего!
То есть лампочка RX мигает, но ответа нет. При чем после закрытия программы которая
успешно общалась с модулем, я могу из кода обращаться и модуль отвечает. Вот такая
магия. Я полагаю что программы открывают порт с какими-то параметрами которые я не
указываю в коде, но понятия не имею какие.

Вот код который пытается связаться с модулем:

using System;
using System.IO.Ports;
using System.Threading;

namespace ConsoleApplication
{
    internal class Program
    {
        private static void Main( string[] args )
        {
            var comPort = new SerialPort( "COM4", 115200, Parity.None, 8, StopBits.One );

            comPort.Open();

            if ( !comPort.IsOpen ) throw new Exception();

            comPort.DataReceived += ComPortOnDataReceived; //событие, кстати, тоже
не генерируется

            comPort.WriteLine( "AT \r\n" );

            Thread.Sleep( 3000 );

            var response = comPort.ReadExisting();

            Console.WriteLine( string.IsNullOrWhiteSpace( response ) ? "null" : response );

            comPort.DataReceived -= ComPortOnDataReceived;
            comPort.Close();
        }

        private static void ComPortOnDataReceived( object sender,
            SerialDataReceivedEventArgs serialDataReceivedEventArgs )
        {
            Console.WriteLine( "received" );
        }
    }
}

    


Ответы

Ответ 1



В данном случае необходимо установить кроме основных параметров инициализации СОМ порта еще и дополнительные comPort.Handshake = Handshake.XOnXOff; так как по умолчанию этот параметр установлен в None. Более детально про этот параметр можно посмотреть здесь. Так же иногда могут возникать ситуации когда устройство долго отвечает на запрос(дольше стандартных значений). В таких случаях нужно изменять время ответа (искать в документации или экспериментировать с увеличением значений) comPort.ReadTimeout = 500; Я встречал устройства у которых время ответа по умолчанию равнялось 10с. А вообще, в подобных ситуациях, когда не получается опросить устройство по СОМ порту и у вас есть родная программа опроса, запускать снифер СОМ-порта и смотреть какие основные и дополнительные параметры порта устанавливает эта программа.

суббота, 21 декабря 2019 г.

Изменить COM-порт устройства программно

#cpp #c #windows #cmd #com_порт


У меня подключено устройство (arduino), оно определяется и подключается к какому-нибудь
COM-порту. Номер порта можно изменить через Устройства и принтеры > свойства > изменить.
А возможно ли это сделать с помощью C/C++, или, на крайний случай, через консоль?
    


Ответы

Ответ 1



Как я вижу проблему (могу видеть её не полностью, так как лет двадцать уже не работал с железом на низком уровне): есть два варианта, через которые можно её решать: через Driver SDK или по принципу "нормальные герои всегда идут в обход". Driver SDK никогда не любил, хотя и приходилось, плюс это не интересно и не спортивно :) А вот запросить WMI, поковыряться в реестре и обновить ручками ComDB - гораздо интереснее: Лезем в реестр по адресу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\COM Name Arbiter. Видим: Я даже не ожидал, что у меня в системе есть хотя бы один COM-порт. А он есть, и именно один. Каждый байт в параметре ComDB отвечает сразу за 8 портов (бит на каждый): "0101 1011" |||| ||||____ Com1 используется |||| |||_____ Com2 используется |||| ||______ Com3 не используется |||| |_______ Com4 используется ||||_________ Com5 используется |||__________ Com6 не используется ||___________ Com7 используется |____________ Com8 не используется Т.е. нам понадобится поменять нужные биты. Это раз. Ну, и второе: залезть в реестр по адресу HKLM:\SYSTEM\CurrentControlSet\Enum\, найти там наш девайс и перепривязать новый порт, меняя при это имя. Где-то в недрах моих архивов лежит почти готовое решение на Delphi. Если надо, постараюсь найти или написать заново, уж перевести на C++ труда не составит :) Ну, либо вот решение для консоли, а именно для powershell. В нём вроде бы всё понятно, можно сразу переводить на C++, я ещё не знаю, как в нём работать с битами. Проверить у себя не могу, т.к. нет ни одного устройства, которое бы работало с COM-портом, а злобная Windows 10 удаляет эмуляторы. $DeviceName = "My Arduino" $ComPort = "COM1" function Change-ComPort { Param ($Name,$NewPort) #Запрашиваем через WMI наш девайс $Query = 'Select * from Win32_PnPEntity where Description = "' + $Name + '"' $Device = Get-WmiObject -Query $Query #Выполняем только, если девайс присутствует в системе if ($Device) { #Берем информацию о нём $DeviceKey = "HKLM:\SYSTEM\CurrentControlSet\Enum\" + $Device.DeviceID $PortKey = "HKLM:\SYSTEM\CurrentControlSet\Enum\" + $Device.DeviceID + "\Device Parameters" $Port = get-itemproperty -path $PortKey -Name PortName $OldPort = [convert]::ToInt32(($Port.PortName).Replace("COM","")) #Выставляем новое значение порта и обновляем имя $FriendlyName = $Name + " (" + $NewPort + ")" New-ItemProperty -Path $PortKey -Name "PortName" -PropertyType String -Value $NewPort -Force New-ItemProperty -Path $DeviceKey -Name "FriendlyName" -PropertyType String -Value $FriendlyName -Force #освобождаем старый порт из ComDB $Byte = ($OldPort - ($OldPort % 8))/8 $Bit = 8 - ($OldPort % 8) if ($Bit -eq 8) { $Bit = 0 $Byte = $Byte - 1 } $ComDB = get-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\COM Name Arbiter" -Name ComDB $ComBinaryArray = ([convert]::ToString($ComDB.ComDB[$Byte],2)).ToCharArray() while ($ComBinaryArray.Length -ne 8) { $ComBinaryArray = ,"0" + $ComBinaryArray } $ComBinaryArray[$Bit] = "0" $ComBinary = [string]::Join("",$ComBinaryArray) $ComDB.ComDB[$Byte] = [convert]::ToInt32($ComBinary,2) Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\COM Name Arbiter" -Name ComDB -Value ([byte[]]$ComDB.ComDB) } } Change-ComPort $DeviceName $ComPort Да, разумеется, права на исполнение понадобятся, в зависимости от того, как выставлены разрешения на указанные в скрипте ветки реестра.

Ответ 2



Благодарю Виктора Томилова за ответ, но у меня получилось сделать таким образом: Win32_PnPEntity WHERE ClassGuid="{4d36e978-e325-11ce-bfc1-08002be10318}" Такой запрос возвращает имена всех COM устройств, у которых в названии система прописывает номер COM-порта, остаётся только найти нужное устройство по имени и достать от туда номер порта. Вот регулярка для взятия порта из текста, если кому надо: COM\d{1,}

понедельник, 15 июля 2019 г.

COM порт, время жизни подключения

Не первый раз сталкиваюсь с проблемой. Стороннее COM устройство делает дисконнект через день/неделю/месяц постоянного опроса. Есть ли какие-нибудь ограничения на количества данных за сеанс или длительность сеанса в подключении WinXP к COM устройству, или это фича самого устройства?
ЗЫ: проверено на 2-х устройствах разного производителя.
ЗЫ2: программирую на c#, SerialPort. Но подозреваю проблема не в этом.


Ответ

В ОС ограничений нет, судя по тому что были проверены разные устройства разных производителей, скорее всего где-то вы ошиблись. Посмотрите тут Протокол обмена данными (Контроль четности, Стоп бит) http://www.denvo.ru/pub/hardware/rs-232.html

пятница, 12 июля 2019 г.

Чтение данных с com порта к которому подключена Arduino

Как считывать строки с Arduino так чтобы последние символов строки не обрезались ? Может дайте ссылки на литературу как это сделать !! Использую javafx+jssc.
Код :
@FXML private void handleButtonAction(ActionEvent event) { System.out.println("You clicked me!"); label.setText("Hello World!"); SerialPort serialPort = new SerialPort("COM5"); try { serialPort.openPort();//Open serial port serialPort.setParams(9600, 8, 1, 0);//Set params. byte[] buffer = serialPort.readBytes(10);//Read 10 bytes from serial port serialPort.closePort();//Close serial port String str = new String(buffer, StandardCharsets.UTF_8); System.out.println(str); } catch (SerialPortException ex) { System.out.println(ex); }
}
Должно быть :
1.791 1.791 1.425
1.325 Есть :
1.791 1.7 1.4 2 5 1. 3 2 5
Пробывал делать так :
SerialPort serialPort = new SerialPort("COM12"); try { serialPort.openPort();//Open serial port serialPort.setParams(9600, 8, 1, 0);//Set params. byte[] but = serialPort.readBytes(3);//Read 10 bytes from serial port serialPort.closePort();//Close serial port
ByteBuffer buffer = ByteBuffer.wrap(but); buffer.get(); while(buffer.getLong()==3) { System.out.println(buffer); buffer.clear(); } } catch (SerialPortException ex) { System.out.println(ex); }
}

Получил :
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774) at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Node.fireEvent(Node.java:8413) at javafx.scene.control.Button.fire(Button.java:185) at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Scene$MouseHandler.process(Scene.java:3757) at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431) at com.sun.glass.ui.View.handleMouseEvent(View.java:555) at com.sun.glass.ui.View.notifyMouse(View.java:937) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71) at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275) at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769) ... 48 more Caused by: java.nio.BufferUnderflowException at java.nio.Buffer.nextGetIndex(Buffer.java:506) at java.nio.HeapByteBuffer.getLong(HeapByteBuffer.java:412) at jssctest.FXMLDocumentController.handleButtonAction(FXMLDocumentController.java:41) ... 58 more


Ответ

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

воскресенье, 14 апреля 2019 г.

Как на Си передать информацию от микроконтроллера на COM-порт?

Занимаюсь изучением программирования микроконтроллеров АВР, и столкнулся с вопросом передачи данных от микроконтроллера на ПК через ком порт. Пишу на Си, МК Atmel AtMega32.


Ответ

Для передачи информации от МК на COM-порт ПК используется интерфейс RS-232. На микроконтроллерах AVR он называется USART(универсальный синхронно-асинхронный приемо передатчик). Вы написали, что программа на Си, но не указали какой компилятор Вы используете, поэтому ниже приведу программу написанную в CodeVision AVR, но перенести ее на любой другой C компилятор микроконтроллеров AVR не должно составить особых сложностей. Есть два пути создания такого рода ПО. 1) Воспользоваться стандартным генератором начального кода, который имеется в CodeVisionAVR. Для этого нужно выполнить следующие шаги. а) при создании нового проекта, выбрать "использовать CodeWizard" б) перейти на вкладку USART и там поставить галочки перед приемником и передатчиком, то есть активизировать их. в) задать скорость приема передачи информации и другие параметры, синхронность асинхронность, кол-во стоп битов и т.д. г) нажать генерировать ПО д) далее используя стандартную библиотеку ввода-вывода отправлять и принимать информацию. 2) Написать ручками ниже приведенный код: #include #include #include
void main(void) {
// Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00;
// Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00; DDRB=0x0C;
// Port C initialization // Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out // State7=0 State6=0 State5=T State4=T State3=T State2=T State1=0 State0=0 PORTC=0x00; DDRC=0xC3;
// Port D initialization // Func7=Out Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=0 State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x88;
// Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC0 output: Non-Inverted PWM TCCR0=0x6B; TCNT0=0x00; OCR0=0x5F;
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC2 output: Non-Inverted PWM ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x5F;
// External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00; MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;
/// USART initialization // Параметры соединения: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 38400 UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x19;
// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00;
while (1) { int a; a = 5; unsigned char get; // Отправить что нибудь: printf("%d

", a); // Принять get = getchar(); //Отправить принятое: printf("%d

", get); } } Но не забывайте, прежде чем организовать прием-передачу информации посредством RS232 необходимо согласовать логические уровни. И соединять надо приемник с передатчиком!) Как то так.

пятница, 12 апреля 2019 г.

Как послать данные на ком-порт?

надо послать 0x55 на 3 ком-порт с одним стоп битом.
using System; using System.IO.Ports;
namespace Com { class Program { static void Main(string[] args) { try { SerialPort _serialPort = new SerialPort("COM3", 2400, Parity.None, 8, StopBits.One); _serialPort.Handshake = Handshake.None;
_serialPort.Open(); _serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
byte sent = 0x55; Console.WriteLine("sent: {0}", sent); _serialPort.Write(new byte[1] { sent }, 0, 1);
} catch (Exception e) { Console.WriteLine("Exception:, {0}", e); } } private static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; string indata = sp.ReadExisting(); Console.WriteLine("Data Received:, {0}", indata); Console.ReadLine(); //Pause } } }
Вроде все верно. Но программа ничего не показывает. Где может закрасться ошибка?


Ответ

Причин может быть много:
возможно у вас в системе несколько СОМ-портов и вы отправляете не на тот; устройство которому вы отправляете посылку ничего не отвечает; скорость не подходит, попробуйте поставить, например, 1200; попробуйте поменять таймауты.
_serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500;
Или же ваша программа закрывается еще до получения ответа. Попробуйте так:
static void Main(string[] args) { try { SerialPort _serialPort = new SerialPort("COM3", 2400, Parity.None, 8, StopBits.One); _serialPort.Handshake = Handshake.None;
_serialPort.Open(); _serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
byte sent = 0x55; Console.WriteLine("sent: {0}", sent); _serialPort.Write(new byte[1] { sent }, 0, 1);
} catch (Exception e) { Console.WriteLine("Exception:, {0}", e); } Console.ReadKey(); }

среда, 13 марта 2019 г.

COM Порт в python: как ждать данные, не нагружая CPU

Есть программа, которая принимает данные из COM порта. Возникла проблема, как заставить программу ждать данные и не выполняться дальше?
При использовании бесконечного цикла while, программа нагружает ЦП до 50%.
forchar = 0 idcom = []
ser = serial.Serial( port = 'COM2',\ baudrate=2400,\ parity=serial.PARITY_NONE,\ stopbits=serial.STOPBITS_ONE,\ bytesize=serial.EIGHTBITS,\ timeout=0)
print("connected to: " + ser.portstr) count=1
while True: for line in ser.readline(): forchar = forchar + 1 idcom.append(line) if forchar >= 13: break


Ответ

У вас порт настроен на неблокирующее чтение, так как установлен timeout=0, Либо уберите эту опцию, либо напишите timeout=None, тогда порт у вас будет ждать данные, до тех пор пока они не появятся.
Если же вам все таки нужно неблокирующее соединение, то в цикл while надо добавить небольшую задержку time.sleep, тогда нагрузка процессора уйдет.