PiGPIO Library ตัวอย่างสำหรับ Bit-Banging a UART


11

ไลบรารี PiGPIO http://abyz.me.uk/rpi/pigpio/index.htmlระบุว่าฟีเจอร์อย่างหนึ่งของมันคือ "ลิงก์อนุกรมซอฟต์แวร์โดยใช้ผู้ใช้ gpio"

ฉันใช้สิ่งนี้เพื่อหมายความว่าคุณสามารถใช้มันเพื่อสร้างซอฟต์แวร์ UART บนพิน GPIO ฟรี 2 ตัว

ในหน้าตัวอย่างของโครงการไม่มีตัวอย่างสำหรับคุณลักษณะนี้และฉันไม่พบสิ่งใดบน Google

มีใครทำเช่นนี้? ถ้าเป็นเช่นนั้นโปรดชี้ให้ฉันเป็นตัวอย่าง

ถ้าไม่มีจะมีห้องสมุดทางเลือกอื่นใดสำหรับการต่อเชื่อม UART หรือไม่?

ขอบคุณ


ดูเพิ่มเติมที่: raspberrypi.stackexchange.com/questions/3475/…และraspberrypi.stackexchange.com/questions/24019//คนหลังตอบโดย @joan ชี้ไปที่ pigpio ดังนั้นบางทีเขาอาจเสนอความเข้าใจเพิ่มเติม
Ghanima

ฉันใช้เวลาสองสามวันทดสอบซอฟต์แวร์ pigpio โดยส่งจาก Pi ไปยังแล็ปท็อปและให้แล็ปท็อปดังก้องกลับไปที่ Pi ฉันตั้งใจจะเขียนมันขึ้นมา แต่เหตุการณ์ต่าง ๆ ก็มาถึงแบบฝึกหัดนั้น ฉันจะดูสิ่งที่ฉันสามารถหาได้
joan

คำตอบ:


13

นี่คือ Python บางตัวที่ฉันใช้ทดสอบความน่าเชื่อถือของซีเรียลซอฟต์แวร์ ด้านอินพุตค่อนข้างเล็กน้อย คุณเพียงแค่ทำการโทรเปิดบิตแบตช์ที่เหมาะสมใน Python หรือ C ด้านเอาต์พุตมีส่วนร่วมมากขึ้นเนื่องจากคุณต้องใช้รูปแบบของคลื่นเพื่อสร้างบิตสตรีม

รหัสที่นี่ใช้ 7 บิตแทนที่จะเป็นข้อมูล 8 บิต การทดสอบนั้นเขียนขึ้นในเวลาเดียวกับที่ฉันเพิ่มการรองรับบิตที่แตกต่างกันต่อไบต์

รหัสจะเขียนบล็อกของข้อมูลไบนารีไปยัง gpio ที่เชื่อมต่อกับแล็ปท็อป (ผ่านดองเกิลอนุกรม) แล็ปท็อปจะสะท้อนข้อมูลอนุกรมขาเข้ากับสายอนุกรมเอาต์พุต Pi อ่านข้อมูลอนุกรมใน gpio อื่น

รหัสตรวจสอบความคลาดเคลื่อนระหว่างข้อมูลที่ส่งและรับ แล็ปท็อปจะถือว่าปราศจากข้อผิดพลาดดังนั้นข้อผิดพลาดใด ๆ จะถือว่าเป็นการต่อสู้เล็กน้อย

ดูบันทึกอะไรที่น้อยกว่า 19.2kbps เป็นของแข็ง อะไรที่มากถึง 115.2kbps นั้นสมเหตุสมผล (แต่จะต้องมีการตรวจสอบ) และ 230.4kbps ให้อัตราความผิดพลาด 13% ไบต์

#!/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()

ท่อน

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

คุณใช้ดองเกิลอนุกรมอะไร บางครั้งคนที่แก่กว่าอาจไม่น่าเชื่อถือเลย
ทีเดียว

ฉันใช้ PL2303HX USB เป็นโมดูลเอาท์พุท RS232 TTL 5V 3.3V 3.3V สำหรับการทดสอบ 1.53 ปอนด์จาก eBay
joan

คุณสามารถทดสอบความน่าเชื่อถือของดองเกิลได้อย่างง่ายดาย เชื่อมต่อเป็น Tx ของตัวเองเพื่อ Rx และรันการทดสอบอีกครั้ง
earcam

0

เมื่อคุณวางสาย Tx โดยตรงกับ Rx เพื่อทดสอบโดยไม่มีสิ่งใดที่จะเพิ่มข้อผิดพลาดเช่นดองเกิลมันจะบอกคุณว่าห้องสมุดมีประสิทธิภาพดีเพียงใด

ใช้ GPIO 23 เป็น Tx และ GPIO 24 เป็น Rx หรือ GPIO ฟรีอื่น ๆ บน Raspberry Pi 3b + สิ่งนี้ดูดีในลำดับเดียวกับ UART บนบอร์ดและอยู่ติดกับมันเพียง 3 พินทางด้านขวาโดยมี GND ที่ด้านขวาของ Rx

ผล:

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

หากคุณสามารถอยู่กับ 19200 หรือน้อยกว่าโดยไม่จำเป็นต้องใช้เช็คซัมหรือ SPI / I2C เพื่อแปลง UART - มันควรจะดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.