PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » serial port принять данные


serial port принять данные

Сообщений 1 страница 11 из 11

1

Здравствуйте, прошу помощи. Программированием для ПК только пытаюсь изучить, помогите пожалуйста разобраться с приём по Com порту. Устройство отдаёт данные пакетами, в начале пакета h02 + 10 байт данных в ascii и завершение приёма h03. С открытием и настройкой порта понятно.  Таким способом я ловлю всё что идёт в порт, а мне нужно собрать строку от начала пакета h02 и до конца h03 и выводить значение в текст гаджет. Спасибо.

Код:
#Com_Port=3
If IsSerialPort (#Com_port)
  CloseSerialPort (#Com_port)
EndIf
If OpenSerialPort(#Com_port, "COM3", 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
  Debug "Порт открыт успешно"
Else
  Debug "Порт не обнаружен"
EndIf

Procedure InData() ; Прием данных. 
  Protected InBytes 
  
  If IsSerialPort(#COM_Port)   ; С таким ИД порт открыт. 
    InBytes = AvailableSerialPortInput(#COM_Port) 
    
    Protected Dim InBuffer.a(InBytes), RealInBytes   
    RealInBytes = ReadSerialPortData(#COM_Port, @InBuffer(), InBytes) 
    AddGadgetItem(3, -1, PeekS(@InBuffer(), RealInBytes, #PB_Ascii)) 
  EndIf 
  
EndProcedure 

Procedure ComOut (Sent_data.s)
  If IsSerialPort(#Com_port)
    
    WriteSerialPortData(#Com_Port,@Sent_data,1)  
  Else
    
    Debug "Куда данные посылать?"
  EndIf
EndProcedure

OpenWindow(0,0,0,700,500,"Тестовая программа",#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered); открываем окно

EditorGadget(3, 50, 160, 330, 150); 

Repeat
  Event=WaitWindowEvent() ; Получаем идентификатор события. 
  Gadget=EventGadget()    ; Узнаём идентификатор активного гаджета. 
  InData()
Until Event = #PB_Event_CloseWindow ; Прерываем цикл при закрытии окна 

End

0

2

Этот код все читает как строку, а нужно только то что между 02 и 03.
Алгоритм следующий. Ищем 02. Если нашли, ищем 03. Если нашли, читаем строку между этими байтами а из массива ее убираем (включая 02 и 03). Если не нашли, значит пакет целиком еще не пришел и нужно дальше принимать данные до появления 03 в них.

0

3

Пётр, спасибо что ответили, подобный алгоритм у меня реализован на bascom avr. Но там я по байту принимаю в прерывании и проверяю на получение 02, далее в массив складываю принятые байты до получения байта равного 03. После собираю строку из массива байт. А как на Purebasic это реализовать не соображу...   Как-то мало примеров по работе с серийным портом в сети. Если Вас не затруднит, помогите каким-то примером.

Отредактировано catalex (13.03.2022 19:29:47)

0

4

catalex
На офсайте ввожу по очереди поиск IsSerialPort, InData, COM3, там по несколько страниц найдено.

Отредактировано AZJIO (14.03.2022 01:00:12)

0

5

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

Код:
Procedure InData() ; Прием данных.
  Static Dim InBuffer.a(0), Pos=0
  Protected InBytes, RealInBytes
  Protected Start=#False, x, i
  
  If IsSerialPort(#COM_Port)   ; С таким ИД порт открыт. 
    InBytes = AvailableSerialPortInput(#COM_Port) 
    If InBytes>0
      If Pos+InBytes > ArraySize(InBuffer()) ; В массиве мало места, нужно увеличить.
        ReDim InBuffer(Pos+InBytes)
      EndIf
      RealInBytes = ReadSerialPortData(#COM_Port, @InBuffer(Pos), InBytes)
      If RealInBytes>0
        ; Ищем последовательности начала и завершения.
        x = 0
        Pos + RealInBytes
        For i=0 To Pos - 1
          If Start=#False ; Стартовый байт не найден.
            If InBuffer(i)=2 ; Нашли стартовый байт.
              x=i+1
              Start=#True
            EndIf
          Else            ; Стартовый байт найден.
            If InBuffer(i)=3 ; Нашли завершающий байт.
              AddGadgetItem(3, -1, PeekS(@InBuffer(x), i-x-1, #PB_Ascii))
              Pos = 0
              Break
            EndIf
          EndIf
        Next
      EndIf
    EndIf
  EndIf 
  
EndProcedure 

0

6

Пётр, AZJIO, большое спасибо за помощь, буду разбираться с программой. Приём идёт как-то рывками...  3-4 пакета примет, потом пауза...   Но надеюсь разберусь.

0

7

Принимать лучшее по таймеру, т. е. вместо

Код:
Repeat
  Event=WaitWindowEvent() ; Получаем идентификатор события. 
  Gadget=EventGadget()    ; Узнаём идентификатор активного гаджета. 
  InData()
Until Event = #PB_Event_CloseWindow ; Прерываем цикл при закрытии окна 

Должно быть.

Код:
AddWindowTimer(0, 0, 16)
BindEvent(#PB_Event_Timer, @InData(), 0, 0)

Repeat
  Event=WaitWindowEvent() ; Получаем идентификатор события. 
  ;Gadget=EventGadget()    ; Узнаём идентификатор активного гаджета. 
Until Event = #PB_Event_CloseWindow ; Прерываем цикл при закрытии окна 

0

8

Добрый вечер.
Не буду открывать новую тему т.к. эта тема совпадает с моим вопросом.
Объясните, мне тупому, как правильно принимать данные.
Все делал как тут предлагалось и в других темах где рассматривался вопрос работы с сериальным портом.
В принципе данные уже принимаются нормально но вот остался вопрос о наполнении/заполнении входного буфера.
Приведу пример.
Я пытаюсь общаться с девайсом который выдает его статус при приеме команды ״s"
Я ему отправляю запрос:

Код:
#ComPort = 1
#Command = "s"   
WriteSerialPortString(#ComPort, #Command, #PB_Ascii)

Если я пытаюсь сразу или после

Код:
Repeat : Until AvailableSerialPortInput(#ComPort) > 0

Прочитать данные

Код:
    If AvailableSerialPortInput(#ComPort) > 0
        DataLenth = AvailableSerialPortInput(#ComPort)
        If DataLenth > 0
            For i=1 To DataLenth
                If ReadSerialPortData(#ComPort, @Buffer, 1) = 1
                    SerialData$+Chr(Buffer)
                EndIf
            Next i
            Debug "SerialData = " + SerialData$
            
        EndIf
        
    EndIf

То пронимаю только часть данных :(
Потом я решил после отсылки команды "s" подождать 900мС Delay(900), только после этого стал принимать всю дату.
Так значит получается что надо ждать пока SerialPortInput буфер наполнится?
Или проверять

Код:
 Repeat : Until AvailableSerialPortInput(#ComPort) > 800 

Т.к. принимаю 806 байт то при побайтном приеме 5 байт еще в SerialPortInput буфере пополнится.

Спасибо.

Отредактировано dibor (10.11.2023 21:00:51)

0

9

Кто либо принимал данные в отдельном потоке?
У меня не получается :(

0

10

Вероятно в коде что-то не так.
Поддержка многопоточности была включена?

0

11

Да, в установках компилятора она включена.
Дебагер кричал что то про память буфера, уже не помню.

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » serial port принять данные