Ví dụ về Thư viện PiGPIO cho Bit-Banging một UART


11

Thư viện PiGPIO http://abyz.me.uk/rpi/pigpio/index.html đề cập rằng một trong những tính năng của nó là "liên kết nối tiếp phần mềm sử dụng bất kỳ gpio người dùng nào".

Tôi hiểu điều này có nghĩa là bạn có thể sử dụng nó để tạo UART phần mềm trên bất kỳ 2 chân GPIO miễn phí nào.

Trong trang ví dụ của dự án, không có ví dụ nào cho tính năng này và tôi không tìm thấy cái nào trên Google.

Có ai đã làm điều này? Nếu vậy xin vui lòng chỉ cho tôi ví dụ.

Nếu không, có bất kỳ thư viện thay thế nào cho bit-banging UART không?

Cảm ơn,


Xem thêm: raspberrypi.stackexchange.com/questions/3485/ và và mâm xôi.stackexchange.com/questions/24019/ Sau
Ghanima

Tôi đã dành vài ngày để kiểm tra nối tiếp phần mềm pigpio bằng cách gửi từ Pi đến máy tính xách tay và tiếng vang của máy tính xách tay trở lại Pi. Tôi định viết nó lên nhưng các sự kiện đã vượt qua bài tập đó. Tôi sẽ xem những gì tôi có thể tìm thấy.
joan

Câu trả lời:


13

Đây là một số Python tôi đã sử dụng để kiểm tra độ tin cậy của phần mềm nối tiếp. Phía đầu vào là khá nhỏ. Bạn chỉ cần thực hiện các cuộc gọi mở nối tiếp bit bang thích hợp trong Python hoặc C. Phía đầu ra có liên quan nhiều hơn khi bạn phải sử dụng dạng sóng để xây dựng luồng bit.

Mã ở đây đang sử dụng dữ liệu 7 bit thay vì 8 bit. Thử nghiệm được viết cùng lúc với khi tôi thêm hỗ trợ cho các bit khác nhau trên mỗi byte.

Mã này ghi các khối dữ liệu nhị phân vào một gpio được kết nối với máy tính xách tay (thông qua dongle nối tiếp). Máy tính xách tay lặp lại dữ liệu nối tiếp đến dòng nối tiếp đầu ra của nó. Pi đọc dữ liệu nối tiếp trên một gpio khác.

Mã kiểm tra sự khác biệt giữa dữ liệu gửi và nhận. Máy tính xách tay được coi là không có lỗi, do đó, bất kỳ lỗi nào được giả sử là trong tiếng đập bit.

Nhìn vào nhật ký bất cứ điều gì dưới 19,2kb / giây là vững chắc. Bất cứ điều gì lên đến 115,2kbps là hợp lý (nhưng sẽ yêu cầu kiểm tra lại) và 230,4kbps cho tỷ lệ lỗi 13% byte.

#!/usr/bin/env python

# bb_serial.py
# 2014-12-23
# Public Domain

# bit bang transmit and receive of serial data
#
# tested by connecting the arbitrary RX/TX gpios to a USB
# serial dongle plugged in to a Linux box.
#
# on the Linux box set the baud and data bits (cs5-cs8)
#
# stty -F /dev/ttyUSB0 19200 cs8
# cat </dev/ttyUSB0 >/dev/ttyUSB0
#
# so the Linux box echoes back data received from the Pi.
#
# laptop timings deviations
#
# baud  exp us   act us
#   50   20000    13310 * 75
#   75   13333    13310
#  110    9091    13310 * 75
#  134    7462     6792 * 150
#  150    6667     6792
#  200    5000     6792 * 150
#  300    3333     3362
#

import sys
import time
import difflib

import pigpio

RX=19
TX=26

MSGLEN=256

if len(sys.argv) > 1:
   baud = int(sys.argv[1])
else:
   baud = 115200

if len(sys.argv) > 2:
   bits = int(sys.argv[2])
else:
   bits = 8

if len(sys.argv) > 3:
   runtime = int(sys.argv[3])
else:
   runtime = 300

ten_char_time = 100.0 / float(baud)

if ten_char_time < 0.1:
   ten_char_time = 0.1

MASK=(1<<bits)-1

# initialise test data

msg = [0] * (MSGLEN+256)

for i in range(len(msg)):
   msg[i] = i & MASK

first = 0

pi = pigpio.pi()

pi.set_mode(TX, pigpio.OUTPUT)

# fatal exceptions off (so that closing an unopened gpio doesn't error)

pigpio.exceptions = False

pi.bb_serial_read_close(RX)

# fatal exceptions on

pigpio.exceptions = True

# create a waveform representing the serial data

pi.wave_clear()

TEXT=msg[first:first+MSGLEN]
pi.wave_add_serial(TX, baud, TEXT)
wid=pi.wave_create()

# open a gpio to bit bang read the echoed data

pi.bb_serial_read_open(RX, baud, bits)

# zero error counts

bad_char = 0
total_char = 0

# run for fixed time

start=time.time()

while (time.time()-start) < runtime:

   pi.wave_send_once(wid)   # transmit serial data
   pi.wave_delete(wid)

   TXTEXT = TEXT

   first += 1
   if first >= MSGLEN:
      first = 0

   TEXT=msg[first:first+MSGLEN]
   pi.wave_add_serial(TX, baud, TEXT,bb_bits=7)

   while pi.wave_tx_busy(): # wait until all data sent
      pass

   wid=pi.wave_create()

   count = 1
   text=""
   lt = 0
   total_char += MSGLEN

   while count: # read echoed serial data
      (count, data) = pi.bb_serial_read(RX)
      if count:
         text += data
         lt += count
      time.sleep(ten_char_time) # enough time to ensure more data

   if text != TXTEXT: # Do sent and received match?
      if lt == MSGLEN: # No, is message correct length?
         for i in range(MSGLEN): # If so compare byte by byte.
            if text[i] != TXTEXT[i]:
               # print("{:2X} {:2X}".format(text[i], TXTEXT[i]))
               bad_char += 1
      else: # Wrong message length, find matching blocks.
         ok = 0
         s=difflib.SequenceMatcher(None, TXTEXT, text)
         for frag in  s.get_matching_blocks():
            ok += frag[2] # More matching bytes found.
            # print(frag)
         # print(text, MSGLEN, ok)
         if ok < MSGLEN: # Sanity check.
            bad_char += (MSGLEN - ok)
         else:
            print("*** ERRONEOUS good={} LEN={} ***".format(ok, MSGLEN))

print("secs={} baud={} bits={} bad={:.3f}%".
   format(runtime, baud, bits, float(bad_char)*100.0/float(total_char)))

print("total={} badchar={}".format(total_char, bad_char))

# free resources

pi.wave_delete(wid)

pi.bb_serial_read_close(RX)

pi.stop()

Nhật ký

harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 230400; done
secs=300 baud=230400 bad=12.610%
total=249344 badchar=31443
secs=300 baud=230400 bad=12.580%
total=247296 badchar=31111
secs=300 baud=230400 bad=12.669%
total=246528 badchar=31232
secs=300 baud=230400 bad=12.274%
total=249600 badchar=30635
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 115200; done
secs=300 baud=115200 bad=0.378%
total=246784 badchar=934
secs=300 baud=115200 bad=0.152%
total=241408 badchar=368
secs=300 baud=115200 bad=0.189%
total=249088 badchar=472
secs=300 baud=115200 bad=0.347%
total=242688 badchar=843
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 57600; done
secs=300 baud=57600 bad=0.080%
total=220416 badchar=177
secs=300 baud=57600 bad=0.066%
total=219392 badchar=145
secs=300 baud=57600 bad=0.099%
total=219904 badchar=218
secs=300 baud=57600 bad=0.084%
total=219136 badchar=184
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 38400; done
secs=300 baud=38400 bad=0.019%
total=206336 badchar=39
secs=300 baud=38400 bad=0.021%
total=206848 badchar=43
secs=300 baud=38400 bad=0.015%
total=206592 badchar=30
secs=300 baud=38400 bad=0.030%
total=206592 badchar=61
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
secs=300 baud=19200 bad=0.000%
total=174336 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 75; done
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0

Bạn đã sử dụng dongle nối tiếp nào? Những người lớn tuổi đôi khi có thể thay không đáng tin cậy ...
not2qubit

Tôi đã sử dụng một mô-đun đầu ra USB PL2303HX sang USB TTL 5V 5V cho các thử nghiệm. 1,53 bảng từ eBay.
gia

Bạn có thể dễ dàng kiểm tra độ tin cậy của dongle; kết nối Tx của riêng nó với Rx và chạy lại bài kiểm tra
Earcam

0

Khi bạn kết nối Tx trực tiếp với Rx để kiểm tra bất kỳ thứ gì có thể gây ra lỗi như dongle, nó sẽ cho bạn biết thư viện thực sự hoạt động tốt như thế nào.

Sử dụng GPIO 23 dưới dạng Tx và GPIO 24 dưới dạng Rx hoặc GPIO miễn phí khác trên Raspberry Pi 3b +. Điều này có vẻ tốt theo thứ tự như UART trên tàu và nó thực tế nằm bên cạnh nó, chỉ cần 3 chân ở bên phải, với một pin GND ở bên phải của Rx.

Các kết quả:

Until 19200bps no errors.
- 38400 and 57600 bps less 1% error sometimes
- 115200bps was 10-20% error or so
- 230400bps over 80% error or so

Nếu bạn có thể sống với 19200 hoặc ít hơn mà không cần sử dụng băm tổng kiểm tra cũng như các bộ chuyển đổi SPI / I2C sang UART - nó sẽ ổn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.