pigpio 利用普通GPIO为树莓派增加软串口实现ttl通讯

树莓派串口

    根据官方文档,树莓派0、1、2、3均有2个UARTS:UART、mini UART,其中 mini UART的不足:

  • No break detection
  • No framing errors detection
  • No parity bit
  • No receive timeout interrupt
  • No DCD, DSR, DTR or RI signals

    这时如果有多台外设需要通过串口采集数据该怎么办?

  1. 买usb转uart硬件,增加硬件串口数量;
  2. 用pigpio库模拟软串口

    软串口的不足是波特率高时,误包率偏高,不过根据测试,19200及以下波特率是可靠的,不需要做错误检测和恢复。

    软串口可以利用26个BCM GPIO中的任意两个,除了14、15这一对自带uart,一个树莓派最多可以增加12个软串口!

PIGPIO

    是一个利用CPU中断模拟脉冲的库,中文和安装方法可参考这篇博文

//安装
sudo apt-get update
sudo apt-get install pigpio python-pigpio python3-pigpio

//设置pigpiod自启动
sudo systemctl enable pigpiod

软串口python代码

    参考pyserial的调用方式,对pigpio的python方法进行了封装,增加了timeout,命名为softuart

import os
import time
import pigpio

class softuart(object):
	"""soft uart(ttl) based on pigpio wiht Rx & Tx GPIO need to be set"""
	def __init__(self, rxPin, txPin, baud=9600, timeout=5):
		self._rxPin = rxPin
		self._txPin = txPin
		self._baud = baud#according to https://www.raspberrypi.org/forums/viewtopic.php?p=694626, bard>19200 is not reliable
		self._timeout = timeout
		# PIGPIO
		self._pi = pigpio.pi()
		if not self._pi.connected:
			os.system('sudo pigpiod')
			self._pi = pigpio.pi()
		self._pi.set_mode(self._rxPin, pigpio.INPUT)
		self._pi.set_mode(self._txPin, pigpio.OUTPUT)

	def flushInput(self):
		pigpio.exceptions = False#fatal exceptions off (so that closing an unopened gpio doesn't error)
		self._pi.bb_serial_read_close(self._rxPin)
		pigpio.exceptions = True
		self._pi.bb_serial_read_open(self._rxPin, self._baud, 8)#open a gpio to bit bang read, 1 byte each time.

	def write(self, msg):
		self._pi.wave_clear()
		self._pi.wave_add_serial(self._txPin, self._baud, msg)#create a waveform representing msg
		wid = self._pi.wave_create()
		start = time.time()
		self._pi.wave_send_once(wid)
		succeed=True
		while self._pi.wave_tx_busy():# wait until all data sent or timeout
			pass
			if (time.time()-start)>self._timeout:
				succeed=False
				break
		self._pi.wave_delete(wid)

		return succeed
	
	def read(self, size):
		count=1
		text=""
		lt=0
		start = time.time()
		while count:
			(count,data)=self._pi.bb_serial_read(self._rxPin)
			if count:
				text = text+data
				lt = lt+count
			if (time.time()-start)>self._timeout:
				break
			if len(text)==size:
				break
			time.sleep(0.1)# enough time to ensure more data

		return text

软串口测试

    利用BCM 6(GPIO.22) 13(GPIO.23)分别作为Rx和Tx,替换噪声一文中的GPIO.15、GPIO.14,测试代码修改为:

import time
#import serial
import softuart
import sys
import RPi.GPIO as GPIO
#port="/dev/ttyAMA0"
#usart=serial.Serial(port,9600,timeout=None)
usart=softuart.softuart(6,13,9600)
usart.flushInput()
sendbuf = bytearray.fromhex("01 03 00 00 00 01 84 0A")
while True:
	usart.write(sendbuf)
	recvbuf = bytearray(usart.read(7))
	b1 = int(recvbuf[3])
	b0 = int(recvbuf[4])
	result = (b1<<8) | b0
	print(result/10.0)
	#time.sleep(.05)
	time.sleep(1)

    头2次调用之后可以正常读到数据。

    sudo top可以看到,pigpiod进程占用cpu 9%左右。

猜你喜欢

转载自blog.csdn.net/xhydongda/article/details/109737006