如何用python写个串口通信的程序

Python019

如何用python写个串口通信的程序,第1张

就是打开串口后,启动一个线程来监听串口数据的进入,有数据时,就做数据的处理(也可以发送一个事件,并携带接收到的数据)。

我没有用到串口处理太深的东西。

客户的原程序不能给你,不过我给你改一下吧。

里面的一些东西,已经经过了处理,要运行,可能你要自己改一下,把没有用的东西去掉。

我这里已经没有串口设备了,不能调了,你自己处理一下吧,不过基本的东西已经有了。

=================================================================

#coding=gb18030

import sys,threading,time

import serial

import binascii,encodings

import re

import socket

class ReadThread:

def __init__(self, Output=None, Port=0, Log=None, i_FirstMethod=True):

self.l_serial = None

self.alive = False

self.waitEnd = None

self.bFirstMethod = i_FirstMethod

self.sendport = ''

self.log = Log

self.output = Output

self.port = Port

self.re_num = None

def waiting(self):

if not self.waitEnd is None:

self.waitEnd.wait()

def SetStopEvent(self):

if not self.waitEnd is None:

self.waitEnd.set()

self.alive = False

self.stop()

def start(self):

self.l_serial = serial.Serial()

self.l_serial.port = self.port

self.l_serial.baudrate = 9600

self.l_serial.timeout = 2

self.re_num = re.compile('\d')

try:

if not self.output is None:

self.output.WriteText(u'打开通讯端口\r\n')

if not self.log is None:

self.log.info(u'打开通讯端口')

self.l_serial.open()

except Exception, ex:

if self.l_serial.isOpen():

self.l_serial.close()

self.l_serial = None

if not self.output is None:

self.output.WriteText(u'出错:\r\n%s\r\n' % ex)

if not self.log is None:

self.log.error(u'%s' % ex)

return False

if self.l_serial.isOpen():

if not self.output is None:

self.output.WriteText(u'创建接收任务\r\n')

if not self.log is None:

self.log.info(u'创建接收任务')

self.waitEnd = threading.Event()

self.alive = True

self.thread_read = None

self.thread_read = threading.Thread(target=self.FirstReader)

self.thread_read.setDaemon(1)

self.thread_read.start()

return True

else:

if not self.output is None:

self.output.WriteText(u'通讯端口未打开\r\n')

if not self.log is None:

self.log.info(u'通讯端口未打开')

return False

def InitHead(self):

#串口的其它的一些处理

try:

time.sleep(3)

if not self.output is None:

self.output.WriteText(u'数据接收任务开始连接网络\r\n')

if not self.log is None:

self.log.info(u'数据接收任务开始连接网络')

self.l_serial.flushInput()

self.l_serial.write('\x11')

data1 = self.l_serial.read(1024)

except ValueError,ex:

if not self.output is None:

self.output.WriteText(u'出错:\r\n%s\r\n' % ex)

if not self.log is None:

self.log.error(u'%s' % ex)

self.SetStopEvent()

return

if not self.output is None:

self.output.WriteText(u'开始接收数据\r\n')

if not self.log is None:

self.log.info(u'开始接收数据')

self.output.WriteText(u'===================================\r\n')

def SendData(self, i_msg):

lmsg = ''

isOK = False

if isinstance(i_msg, unicode):

lmsg = i_msg.encode('gb18030')

else:

lmsg = i_msg

try:

#发送数据到相应的处理组件

pass

except Exception, ex:

pass

return isOK

def FirstReader(self):

data1 = ''

isQuanJiao = True

isFirstMethod = True

isEnd = True

readCount = 0

saveCount = 0

RepPos = 0

#read Head Infor content

self.InitHead()

while self.alive:

try:

data = ''

n = self.l_serial.inWaiting()

if n:

data = data + self.l_serial.read(n)

#print binascii.b2a_hex(data),

for l in xrange(len(data)):

if ord(data[l])==0x8E:

isQuanJiao = True

continue

if ord(data[l])==0x8F:

isQuanJiao = False

continue

if ord(data[l]) == 0x80 or ord(data[l]) == 0x00:

if len(data1)>10:

if not self.re_num.search(data1,1) is None:

saveCount = saveCount + 1

if RepPos==0:

RepPos = self.output.GetInsertionPoint()

self.output.Remove(RepPos,self.output.GetLastPosition())

self.SendData(data1)

data1 = ''

continue

except Exception, ex:

if not self.log is None:

self.log.error(u'%s' % ex)

self.waitEnd.set()

self.alive = False

def stop(self):

self.alive = False

self.thread_read.join()

if self.l_serial.isOpen():

self.l_serial.close()

if not self.output is None:

self.output.WriteText(u'关闭通迅端口:[%d] \r\n' % self.port)

if not self.log is None:

self.log.info(u'关闭通迅端口:[%d]' % self.port)

def printHex(self, s):

s1 = binascii.b2a_hex(s)

print s1

#测试用部分

if __name__ == '__main__':

rt = ReadThread()

f = open("sendport.cfg", "r")

rt.sendport = f.read()

f.close()

try:

if rt.start():

rt.waiting()

rt.stop()

else:

pass

except Exception,se:

print str(se)

if rt.alive:

rt.stop()

print 'End OK .'

del rt

可能是与串口软件冲突,解决方法如下:

1、添加控件,通过菜单Project→AddtoProject→ComponentsandControl插入即可,再将该控件从工具箱中拉到对话框中。

2、在窗口上添加一个串口控件,随便放一个位置,此控件是不可见的。

3、为控件添加变量m_com为后面操作做准备,如果不添加变量也可以用GetDlgItem函数获取句柄进行操作。

4、打开串口即可。

rshell是专门针对MicroPython的远程shell,基于串口和网络。支持多种模式:

目前必须使用Linux中的Python3。由于硬件映射问题,所以Windows10的Ubuntu子系统无法使用/dev/tty*,必须使用VBox中的Ubuntu虚拟机,或者Cygwin。

不知道是否是Flash原因,使用rshell经常会无法写入文件。重刷固件也不解决问题。看来MRAM/PSRAM/FeRAM在IoT时代还是很有意义的。

所以,现在我要访问MicroPython,如同盗梦空间一样:

Remote MicroPytyhon shell.

This is a simple shell which runs on the host and uses MicroPython's

raw-REPL to send python snippets to the pyboard in order to get

filesystem information, and to copy files to and from MicroPython's

filesystem.

It also has the ability to invoke the regular REPL, so rshell can be

used as a terminal emulator as well.

Note: With rshell you can disable USB Mass Storage and still copy files

into and out of your pyboard.

When using the commands, the /flash directory, and the /sdcard directory

(if an sdcard is inserted) are considered to be on the pyboard, and all

other directories are considered to be on the host. For an ESP based board you

can only reference its directory by using the board name e.g. /pyboard etc..

NOTE: rshell requires a fairly recent version of the MicroPython

firmware, specifically one which contains the ubinascii.unhexlify

command which was added May 19, 2015 (v1.4.3-28-ga3a14b9 or newer).

If your verion of the firmware isn't new enough, then you'll see an

error message something like this:

::

You can install rshell using the command:

::

If you use a virtualenv, then you don't need the sudo. rshell needs Python3.

All of my testing was done using version 3.4.0.

Debian/Ubuntu users can get pip3 using:

::

This shows a pyboard in its default state, copying a hello.py and then

entering the repl and importing it.

::

Displays a lit of the valid options. You should get something like the

following displayed:

::

Sets the baud rate to use when talking to the pyboard over a serial port. If

no baud is specified, then the baudrate from the RSHELL_BAUD enviroinment

variable is used. If the RSHELL_BAUD environment variable is not defined then

the default baudrate of 115200 is used.

Sets the buffer size used when transferring files betweem the host and the

pyboard. If no buffer size is specified, then the value from the

RSHELL_BUFFER_SIZE environment variable is used. If the RSHELL_BUFFER_SIZE

environment variable is not defined, then the default of 512 is used.

Turns on debugging. This allows you to see the script which is sent over

the raw REPL and the response received.

Specifies the editor to use with the edit command. If no editor is specified,

then the following environment variables will be searched: RSHELL_EDITOR,

VISUAL, and EDITOR. If none of those environment variables is set then vi will

be used.

Specifies a file of rshell commands to process. This allows you to

create a script which executes any valid rshell commands.

By default, rshell uses ANSI color escape codes when displaying the

prompt and ls output. This option allows colorized output to be

disabled.

On certain platforms the raw REPL mode is unreliable with particular sequences

of binary characters. Specifying --ascii enables the transfer of binary files

to such platforms. It does this by encoding the data as ASCII hex.

If a port is specified defines how long rshell will wait for the port to exist

and for a connection to be established. The default is 0 seconds specifying an

immediate return.

Specifies the serial port which should be used to talk to the

MicroPython board. You can set the RSHELL_PORT environment variable to

specify the default port to be used, if --port is not specified on the

command line.

This option causes the Connecting messages printed when rshell starts to be

suppressed. This is mostly useful for the test scripts.

If the timing option is specified then rshell will print the amount of time

that each command takes to execute.

Specifies the username to use when logging into a WiPy over telent. If no

username is specified, then the username from the RSHELL_USER environment

variable is used. If the RSHELL_USER environment variable doesn't exist

then the default username 'micro' is used.

Specified the password to use when logging into a WiPy over telnet. If no

password is specified, then the password from the RSHELL_PASSWORD environment

variable is used. If the RSHELL_PASSWORD environment variable doesn't exist

then the default password 'python' is used.

If a command is specified, then that command will be executed and rshell will

exit. Examples:

::

rshell can be connected to multiple pyboards simultaneously. If the

board module exists on the pyboard (i.e. a file named board.py somewhere

in the module search path) and it contains an attribute called name

(e.g. :code: name = "myboard" ) then the pyboard will use that name. If the board

module can't be imported then the board will be named, pyboard or wipy.

Names will have -1 (or some other number) to make the board name unique.

You can access the internal flash on the first board connected using

/flash and the sd card on the first board connected can be accessed

using /sd.

For all other connected pyboards, you can use /board-name/flash or

/board-name/sd (you can see the board names using the boards command).

The boards command will show all of the connected pyboards, along with all of

the directories which map onto that pyboard.

::

Debug function for verifying argument parsing. This function just prints

out each argument that it receives.

::

Lists all of the boards that rshell is currently connected to, their

names, and the connection.

You can give a custom name to a board with either copying over a :code: board.py

file or using the :code: echo command, e.g.

::

(Remember to exit rshell and re-enter to see the change).

::

Concatenates files and sends to stdout.

::

Changes the current directory. ~ expansion is supported, and cd - goes

to the previous directory.

::

Connects a pyboard to rshell. rshell can be connected to multiple

pyboards simultaneously.

::

Copies the SOURCE file to DEST. DEST may be a filename or a directory

name. If more than one source file is specified, then the destination

should be a directory.

Directories will only be copied if -r is specified.

A single pattern may be specified, in which case the destination

should be a directory. Pattern matching is performed according to a subset

of the Unix rules (see below).

Recursive copying uses rsync (see below): where a file exists on source

and destination, it will only be copied if the source is newer than the

destination.

::

Display a line of text.

::

If the file is on a pyboard, it copies the file to host, invokes an

editor and if any changes were made to the file, it copies it back to

the pyboard.

The editor which is used defaults to vi, but can be overridem using

either the --editor command line option when rshell.py is invoked, or by

using the RSHELL_EDITOR, VISUAL or EDITOR environment variables (they

are tried in the order listed).

::

Prints the size of the file, in bytes. This function is primarily