在实际开发过程中,只靠一个while1是不够用的,需要有多线程。python中是带有多线程功能的(我平时FreeRTOS用的比较多,叫任务/task已经习惯了,后续可能顺手就打成任务/task,请见谅)
可惜K230上不支持threading,只能支持_thread
在python官方文档关于_thread的内容如下:https://docs.python.org/3.5/library/_thread.html#module-thread
一.创建线程并启动
接下来我们就来写一个demo,运行后创建2个task,第一个task为闪灯task,第二个为串口task。这两个task中执行的内容就是之前我们写过的
import _thread
import time
from machine import Pin
from machine import UART
from machine import FPIOA
fpioa = FPIOA()
#闪灯task
def task_blink():
#初始化52号引脚为输出模式,不拉高,驱动能力为默认的7
LED = Pin(52, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
while True:
#开灯
LED.value(1)
time.sleep(1)
#关灯
LED.value(0)
time.sleep(1)
#串口task
def task_uart():
#初始化串口2
fpioa.set_function(11,FPIOA.UART2_TXD)
fpioa.set_function(12,FPIOA.UART2_RXD)
my_uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
#发送数据测试
my_uart.write('UART2 send test\r\n')
#一直接收数据
while True:
#读取一行,并以一个换行符结束。
recv_data = my_uart.readline()
#如果有读到数据
if recv_data != b'':
#把收到数据通过日志串口打印出来
print(recv_data)
#把收到的数据原样从串口2发出去
my_uart.write(recv_data)
time.sleep(0.1)
#创建闪灯task和串口task
_thread.start_new_thread(task_blink, ())
_thread.start_new_thread(task_uart, ())
while True:
time.sleep(0.01) #防止CPU满跑
IMG_6612
二.线程停止
2.1 由别的task摧毁某个task
在python的介绍中,_thread并没有制定摧毁某个task的接口,只有在task调用的函数退出运行,也就是要退出task中的while1
所以,我们可以使用一个flag,来决定while1是否可以运行,我这边偷懒,直接用一个全局变量,当然在多线程的环境下,各个task之间通讯用全局变量不合适,用队列比较好,不过我这边的使用场景比较简单,也不存在竞争,可以偷懒用一下
我们来改造一下刚才的代码,当串口收到“STOP”后,把闪灯的task摧毁。收到“START”后,开始闪灯TASK
import _thread
import time
from machine import Pin
from machine import UART
from machine import FPIOA
fpioa = FPIOA()
# 全局变量作为标志位
task_blink_run_flag = False
#闪灯task
def task_blink():
global task_blink_run_flag
#初始化52号引脚为输出模式,不拉高,驱动能力为默认的7
LED = Pin(52, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
while task_blink_run_flag:
#开灯
LED.value(1)
time.sleep(1)
#关灯
LED.value(0)
time.sleep(1)
#串口task
def task_uart():
global task_blink_run_flag
#初始化串口2
fpioa.set_function(11,FPIOA.UART2_TXD)
fpioa.set_function(12,FPIOA.UART2_RXD)
my_uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
#发送数据测试
my_uart.write('UART2 send test\r\n')
#一直接收数据
while True:
#读取一行,并以一个换行符结束。
recv_data = my_uart.readline()
#如果有读到数据
if recv_data != b'':
#把收到数据通过日志串口打印出来
print(recv_data)
if recv_data == b'STOP\r\n':
print('recv stop')
# 避免task_blink被多次stop
if task_blink_run_flag == True:
task_blink_run_flag = False
else:
print('stop task_blink fail')
elif recv_data == b'START\r\n':
print('recv START')
# 避免task_blink被多次start
if task_blink_run_flag == False:
task_blink_run_flag = True
_thread.start_new_thread(task_blink, ())
else:
print('start task_blink fail')
time.sleep(0.1)
#创建闪灯task和串口task
task_blink_run_flag = True
_thread.start_new_thread(task_blink, ())
_thread.start_new_thread(task_uart, ())
while True:
time.sleep(0.01) #防止CPU满跑
IMG_6619
2.2 TASK自己摧毁自己
按照上述的思路,我们可以在task内部加一个变量,用于控制task中的while1,改造代码如下(为了看得清楚,其他部分我没动,新增了一个task)
import _thread
import time
from machine import Pin
from machine import UART
from machine import FPIOA
fpioa = FPIOA()
# 全局变量作为标志位
task_blink_run_flag = False
#闪灯task
def task_blink():
global task_blink_run_flag
#初始化52号引脚为输出模式,不拉高,驱动能力为默认的7
LED = Pin(52, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
while task_blink_run_flag:
#开灯
LED.value(1)
time.sleep(1)
#关灯
LED.value(0)
time.sleep(1)
#串口task
def task_uart():
global task_blink_run_flag
#初始化串口2
fpioa.set_function(11,FPIOA.UART2_TXD)
fpioa.set_function(12,FPIOA.UART2_RXD)
my_uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
#发送数据测试
my_uart.write('UART2 send test\r\n')
#一直接收数据
while True:
#读取一行,并以一个换行符结束。
recv_data = my_uart.readline()
#如果有读到数据
if recv_data != b'':
#把收到数据通过日志串口打印出来
print(recv_data)
if recv_data == b'STOP\r\n':
print('recv stop')
# 避免task_blink被多次stop
if task_blink_run_flag == True:
task_blink_run_flag = False
else:
print('stop task_blink fail')
elif recv_data == b'START\r\n':
print('recv START')
# 避免task_blink被多次start
if task_blink_run_flag == False:
task_blink_run_flag = True
_thread.start_new_thread(task_blink, ())
else:
print('start task_blink fail')
time.sleep(0.1)
def task_destory_by_self():
flag = True
cnt = 0
while flag:
print('task_destory_by_self running')
cnt += 1
time.sleep(1)
if cnt >= 5:
flag = False
print('task_destory_by_self QUIT')
#创建闪灯task和串口task
task_blink_run_flag = True
_thread.start_new_thread(task_blink, ())
_thread.start_new_thread(task_uart, ())
_thread.start_new_thread(task_destory_by_self, ())
while True:
time.sleep(0.01) #防止CPU满跑
可以看到,task_destory_by_self running打印 5次后,打印了task_destory_by_self QUIT,说明task是已经被摧毁了
IMG_6622
在python的文档中,还有一种方法,就是调用_thread.exit()函数,可以在task中直接退出,当执行这个函数后,TASK立刻被摧毁,这个函数后面的代码都不会被执行。代码如下
import _thread
import time
from machine import Pin
from machine import UART
from machine import FPIOA
fpioa = FPIOA()
# 全局变量作为标志位
task_blink_run_flag = False
#闪灯task
def task_blink():
global task_blink_run_flag
#初始化52号引脚为输出模式,不拉高,驱动能力为默认的7
LED = Pin(52, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
while task_blink_run_flag:
#开灯
LED.value(1)
time.sleep(1)
#关灯
LED.value(0)
time.sleep(1)
#串口task
def task_uart():
global task_blink_run_flag
#初始化串口2
fpioa.set_function(11,FPIOA.UART2_TXD)
fpioa.set_function(12,FPIOA.UART2_RXD)
my_uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
#发送数据测试
my_uart.write('UART2 send test\r\n')
#一直接收数据
while True:
#读取一行,并以一个换行符结束。
recv_data = my_uart.readline()
#如果有读到数据
if recv_data != b'':
#把收到数据通过日志串口打印出来
print(recv_data)
if recv_data == b'STOP\r\n':
print('recv stop')
# 避免task_blink被多次stop
if task_blink_run_flag == True:
task_blink_run_flag = False
else:
print('stop task_blink fail')
elif recv_data == b'START\r\n':
print('recv START')
# 避免task_blink被多次start
if task_blink_run_flag == False:
task_blink_run_flag = True
_thread.start_new_thread(task_blink, ())
else:
print('start task_blink fail')
time.sleep(0.1)
def task_destory_by_self():
cnt = 0
while True:
print('task_destory_by_self running')
cnt += 1
time.sleep(1)
if cnt >= 5:
print('task_destory_by_self exit')
_thread.exit()
print('task_destory_by_self QUIT')
#创建闪灯task和串口task
task_blink_run_flag = True
_thread.start_new_thread(task_blink, ())
_thread.start_new_thread(task_uart, ())
_thread.start_new_thread(task_destory_by_self, ())
while True:
time.sleep(0.01) #防止CPU满跑
IMG_6623