diff --git a/docs/sbs/zh/BSP/GPIO.md b/docs/sbs/zh/BSP/GPIO.md index 218833c5849f9fee351eedd68f074eabf11e2b2f..73e941f9577b6bb13c731c7df492f46bf8481fc2 100644 --- a/docs/sbs/zh/BSP/GPIO.md +++ b/docs/sbs/zh/BSP/GPIO.md @@ -1,8 +1,8 @@ ## 修订历史 -| Version | Date | Author | Change expression | -| ------- | ---------- | ------ | ----------------- | -| 1.0 | 2021-09-06 | David | Initial version | +| Version | Date | Author | Change expression | +| ------- | ---------- | ---------- | ----------------- | +| 1.0 | 2021-09-06 | David.Tang | Initial version | ## PIN diff --git a/docs/sbs/zh/BSP/PWM.md b/docs/sbs/zh/BSP/PWM.md index c85bae3fb8a1995336889b342019b337d3618cf8..b569f260e5fb3af6ade608aeaa00866693bf26c2 100644 --- a/docs/sbs/zh/BSP/PWM.md +++ b/docs/sbs/zh/BSP/PWM.md @@ -1,8 +1,8 @@ ## 修订历史 -| Version | Date | Author | Change expression | -| ------- | ---------- | ------ | ----------------- | -| 1.0 | 2021-09-06 | David | Initial version | +| Version | Date | Author | Change expression | +| ------- | ---------- | ---------- | ----------------- | +| 1.0 | 2021-09-06 | David.Tang | Initial version | 文档主要基于EC600X(包括EC600S、EC600N、EC600U)介绍如何使用 QuecPython_PWM。PWM是一种对模拟信号电平进行数字编码的方法。根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。 diff --git a/docs/sbs/zh/BSP/UART.md b/docs/sbs/zh/BSP/UART.md index 7fbd5c8598bd6089419aac8df5055d69cbf7784e..c5a538beac3aa14e3f77afbb98d5c02881117e13 100644 --- a/docs/sbs/zh/BSP/UART.md +++ b/docs/sbs/zh/BSP/UART.md @@ -1,8 +1,8 @@ ## 修订历史 -| Version | Date | Author | Change expression | -| ------- | ---------- | ------ | ----------------- | -| 1.0 | 2021-09-02 | David | Initial version | +| Version | Date | Author | Change expression | +| ------- | ---------- | ---------- | ----------------- | +| 1.0 | 2021-09-02 | David.Tang | Initial version | 文档主要基于EC600X(包括EC600S、EC600N、EC600U)介绍如何使用QuecPython_UART,UART作为一种通用串行数据总线,用于异步通信,可实现全双工传输和接收。在嵌入式设计中,UART用来与PC进行通信,包括监控调试器和其它器件。通过本文你将了解到EC600X_UART的所有设置参数及使用方法。 diff --git a/docs/sbs/zh/QuecPythonPlatform/Audio.md b/docs/sbs/zh/QuecPythonPlatform/Audio.md new file mode 100644 index 0000000000000000000000000000000000000000..40caf497d1984c0422027121396fa35f70976b23 --- /dev/null +++ b/docs/sbs/zh/QuecPythonPlatform/Audio.md @@ -0,0 +1,72 @@ +## 修订历史 +| 版本 | 日期 | 作者 | 变更表述 | +|------|------|------|------| +| 1.0 | 2021-4-6 | gary.zhou | 初版 | +| 1.1 | 2021-9-16 | David.Tang | 增加多模组的适用性 | + + +## 硬件连接 + +| 开发板型号 | 开发板对应PIN脚 | 开发板上对应的连接位置 | 对应的音频通道 | +| -------------------------------------------------------- | ------------------------------ | ---------------------- | -------------- | +| EC600S_QuecPython_EVB_V1.3
EC600N_QuecPython_EVB_V1.3 | PIN21、PIN22 | J7 | 通道0 | +| EC600U_QuecPython_EVB_V1.3 | PIN21、PIN22
PIN109、PIN110 | J7
J6的PIN14、PIN15 | 通道0
通道2 | + +针对EC600S/N的硬件连接图如下: + +![audio_01](media/audio_01.png) + +针对EC600U_通道0的硬件连接图如下: + +![audio_02](media/audio_02.png) + +针对EC600U_通道2的硬件连接图如下: + +![audio_03](media/audio_03.png) + +## 下载验证 + +1. 根据测试场景,调整下面代码的注释。 + + ```python + # -*- coding: UTF-8 -*- + #备注如下: + #(1)对于EC600S和EC600N的话,下面的代码不需要做任何修改,就可以播放 + #(2)对于EC600U的通道0的话,注释掉18行(18行的配置对这个播放没有影响) + #(3)对于EC600U的通道2的话,注释掉12行和19行,取消注释13行; + import utime as time + import audio + from machine import Pin + + + def example_audio_mp3(): + aud = audio.Audio(0) # 配置通道0 + # aud = audio.Audio(2) # 配置通道2 + aud.setVolume(9) + ''' + 使能外接喇叭播放 + ''' + # Pin(Pin.GPIO11, Pin.OUT, Pin.PULL_PD, 1) # 官方板V1.1使用 + Pin(Pin.GPIO9, Pin.OUT, Pin.PULL_PD, 1) # 官方板V1.2和V1.3使用 + # U: 表示用户目录, GUI下载工具会将文件下载到 /usr 文件下 + aud.play(2, 1, "U:/example.mp3") + pass + + if __name__ == "__main__": + example_audio_mp3() + ``` + + + +2. 将随包的 example.mp3 和修改好的 example_audio_file.py 文件下载到开发板中。 + +3. 运行 example_audio_file.py 脚本即可。 + + + + +## 配套代码 + + + + 下载代码和音频文件 \ No newline at end of file diff --git a/docs/sbs/zh/QuecPythonPlatform/code/Audio.rar b/docs/sbs/zh/QuecPythonPlatform/code/Audio.rar new file mode 100644 index 0000000000000000000000000000000000000000..64e38e8f83702c2c0c98d5f04a30638ddb56f757 Binary files /dev/null and b/docs/sbs/zh/QuecPythonPlatform/code/Audio.rar differ diff --git a/docs/sbs/zh/QuecPythonPlatform/code/example.mp3 b/docs/sbs/zh/QuecPythonPlatform/code/example.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1d36dd78c62237d5a4ecd1f32841815ed3e33a3e Binary files /dev/null and b/docs/sbs/zh/QuecPythonPlatform/code/example.mp3 differ diff --git a/docs/sbs/zh/QuecPythonPlatform/code/example_audio_file.py b/docs/sbs/zh/QuecPythonPlatform/code/example_audio_file.py new file mode 100644 index 0000000000000000000000000000000000000000..84df3371f4262067e32079631fc313147558d2d3 --- /dev/null +++ b/docs/sbs/zh/QuecPythonPlatform/code/example_audio_file.py @@ -0,0 +1,25 @@ +# -*- coding: UTF-8 -*- +#备注如下: +#(1)对于EC600S和EC600N的话,下面的代码不需要做任何修改,就可以播放 +#(2)对于EC600U的通道0的话,注释掉18行(18行的配置对这个播放没有影响) +#(3)对于EC600U的通道2的话,注释掉12行和19行,取消注释13行; +import utime as time +import audio +from machine import Pin + + +def example_audio_mp3(): + aud = audio.Audio(0) # 配置通道0 + # aud = audio.Audio(2) # 配置通道2 + aud.setVolume(9) + ''' + 使能外接喇叭播放 + ''' + # Pin(Pin.GPIO11, Pin.OUT, Pin.PULL_PD, 1) # 官方板V1.1使用 + Pin(Pin.GPIO9, Pin.OUT, Pin.PULL_PD, 1) # 官方板V1.2和V1.3使用 + # U: 表示用户目录, GUI下载工具会将文件下载到 /usr 文件下 + aud.play(2, 1, "U:/example.mp3") + pass + +if __name__ == "__main__": + example_audio_mp3() diff --git a/docs/sbs/zh/QuecPythonPlatform/media/audio_01.png b/docs/sbs/zh/QuecPythonPlatform/media/audio_01.png new file mode 100644 index 0000000000000000000000000000000000000000..3c344a43085a495f5d412a085723b18fb5d44f1d Binary files /dev/null and b/docs/sbs/zh/QuecPythonPlatform/media/audio_01.png differ diff --git a/docs/sbs/zh/QuecPythonPlatform/media/audio_02.png b/docs/sbs/zh/QuecPythonPlatform/media/audio_02.png new file mode 100644 index 0000000000000000000000000000000000000000..a2511585b7ddd55e77c0a1bfebff9e2aac3ffc88 Binary files /dev/null and b/docs/sbs/zh/QuecPythonPlatform/media/audio_02.png differ diff --git a/docs/sbs/zh/QuecPythonPlatform/media/audio_03.png b/docs/sbs/zh/QuecPythonPlatform/media/audio_03.png new file mode 100644 index 0000000000000000000000000000000000000000..0d13edd79a3ab670db63680908314b8c8f67d41b Binary files /dev/null and b/docs/sbs/zh/QuecPythonPlatform/media/audio_03.png differ diff --git a/docs/sbs/zh/QuecPythonSys/filesystem.md b/docs/sbs/zh/QuecPythonSys/filesystem.md new file mode 100644 index 0000000000000000000000000000000000000000..2e4e2755e6213e1fdf329b97852ca6dfd98803da --- /dev/null +++ b/docs/sbs/zh/QuecPythonSys/filesystem.md @@ -0,0 +1,137 @@ +## 修订历史 + +| Version | Date | Author | Change expression | +| ------- | ---------- | ---------- | ----------------- | +| 1.0 | 2021-09-17 | David.Tang | Initial version | + +## 概述 + +本文主要介绍QuecPython文件系统的操作与使用。文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。通过本文您将了解到文件系统的操作与使用方法。 + +## 如何将文件存放到文件系统中 + +### 通过QPYcom工具下载操作调试文件 + +脚本下载 + +对于脚本下载,方法有多种,例如: + +(1)使用QPYcom的拖拽功能,直接将文件拖至模块中, + +(2)使用QPYcom的脚本下载功能,可一键下载脚本至模块。 + +说明:具体的脚本下载操作可见《Quectel QuecPython_QPYcom工具使用说明》 + +文件操作 + +对于QuecPython文件系统如何操作,可见[uos模块](https://python.quectel.com/wiki/#/zh-cn/api/pythonStdlib?id=uos-%e5%9f%ba%e6%9c%ac%e7%b3%bb%e7%bb%9f%e6%9c%8d%e5%8a%a1)和[uio模块](https://python.quectel.com/wiki/#/zh-cn/api/pythonStdlib?id=uio-%e8%be%93%e5%85%a5%e8%be%93%e5%87%ba%e6%b5%81) + +对于各类接口的举例操作如下: + +```python +>>> import uos +>>> uos.getcwd() #获取路径 +'/' +>>> uos.chdir('/usr') # 改变路径 +>>> uos.mkdir('QuecPython') # 在当前路径创建文件夹 +>>> uos.listdir() +['apn_cfg.json', 'a.py', 'b.py', 'V05.bin', 'system_config.json', 'checksum.json', 'b.txt', 'QuecPython'] +>>> uos.chdir('QuecPython')# 改变路径 +>>> uos.getcwd() +'/usr/QuecPython' +>>> import uio +>>> fd = uio.open('test.py', mode='w') #在当前路径新建文件,已写方式打开 +>>> fd.write('quectel') #写操作 +7 +>>> fd.close() # 关闭文件 +>>> fd = uio.open('test.py', mode='r') # 对当前路径下的文件,已读方式打开 +>>> fd.read() #读操作 +'quectel' +>>> fd.close() +``` + +### 量产文件生成bin方式 + + 对于固件合并的操作,实际上就是生成了customer_fs.bin,原理介绍如下: + +1.找到mklfs,在QPYcom解压后的目录(QPYcom_v1.7\exes\aboot)下,在mklfs工具目录下通过cmd命令打开如下: + +![filesystem_01](media/filesystem_01.jpg) + +2.创建一个文件夹,可随意命名,本文命为mount,并在此文件夹中,放置需要合并的文件,举例如下: + +![filesystem_02](media/filesystem_02.jpg) + +3.cmd命令行操作如下 + +![filesystem_03](media/filesystem_03.jpg) + +(1).bin生成命令如上,具体命令解释如下: + +![filesystem_04](media/filesystem_04.jpg) + +(2)如上图,生成的是customer_fs.bin,默认是5 MB,即图中大小是:5242880 + +(3)对于customer_backup_fs.bin,默认是200 KB,即图中输出值为:20480 + +4.生成的customer_fs.bin文件可见mklfs的工具目录,如下截图: + +![filesystem_05](media/filesystem_05.jpg) + +## 参数保存方法 + +### 动态参数的保存方法 + +开发者在开发过程中使用的临时参数,变量,字符串定义等属于动态变化的参数,对于这些动态参数,QuecPython提供了GC内存管理模块来进行内存垃圾回收。详细可以参见QuecPython官网wiki相关说明: [gc - 内存碎片回收](https://python.quectel.com/wiki/#/zh-cn/api/pythonStdlib?id=gc-%e5%86%85%e5%ad%98%e7%a2%8e%e7%89%87%e5%9b%9e%e6%94%b6) + +### 出厂参数的保存方法 + +关于出厂参数的保存,需要将配置的出厂参数先写入文件中,然后通过文件镜像生成.bin文件,具体操作方法可参考"量产文件生成bin方式"章节。 + +## 文件备份(脚本备份) + +对于文件备份,需要将备份的文件与原固件合并生成新固件,然后重新烧录至模块中,具体操作步骤见如下章节。 + +### 制作镜像文件 + +对于镜像文件的制作可以参考上面的"量产文件生成bin方式 "章节,也可以参考《Quectel_EC100Y-QuecOpen_FS镜像制作_应用指导》 + +本文对如下几个文件说明镜像文件制作: + +![filesystem_06](media/filesystem_06.png) + +制作的镜像文件是: + +![filesystem_07](media/filesystem_07.png) + +### 镜像文件替换与烧录固件 + +由于"模块会对于用户区与备份区默认烧录一个已经格式化的内容为空的镜像文件",所以需要将制作的镜像文件customer_backup_fs.bin替换原有的镜像文件,生成新的压缩包固件,使用QPYcom烧录固件,烧录步骤可参考《Quectel_QuecPython_QPYcom工具使用说明》。 + +### 文件更新 + +对于上述文件的烧录,登录QPYcom,结果如下: + +![filesystem_08](media/filesystem_08.png) + +交互界面操作如下: + +```python +>>> import checksum +>>> checksum.update('/usr/a.py') + +[{'name': '/usr/a.py', 'sha256': '454f048b9b584add8b6f67a86ec4ec01ce63baace41efba994881f608a227e30'}, {'name': '/usr/b.py', 'sha256': '3edc1bd333bc7f4caf33bb35e7602bafe5d85c6b6b2ca74a92588a470fbee917'}, {'name': '/usr/b.txt', 'sha256': 'cced28c6dc3f99c2396a5eaad732bf6b28142335892b1cd0e6af6cdb53f5ccfa'}, {'name': '/usr/V05.bin', 'sha256': 'e5d2dd354947292348a8fb29cdf78e4ffc05754f8e12ecf0dc0ff3783b6b8822'}] +>>> uos.listdir('usr/') +['apn_cfg.json', 'checksum.json', 'a.py', 'b.py', 'b.txt', 'V05.bin', 'system_config.json'] +>>> uos.listdir('/bak/usr/') +['test.txt', 'a.py', 'b.py', 'b.txt', 'V05.bin'] +>>> +``` + +操作说明: + +(1)对于更改customer_backup_fs.bin后的烧录如上图所示 + +(2)如果更新usr目录下的文件且希望下次上电后可以继续运行的话,需要使用checksum.update接口更新checksum.json文件。 + +(3)文件备份的操作就是保留合并的文件,防止后面误删文件,导致程序删除,无法恢复。 \ No newline at end of file diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_01.jpg b/docs/sbs/zh/QuecPythonSys/media/filesystem_01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1931c71147c5b749bd3c5dbbd505cc2109547ebd Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_01.jpg differ diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_02.jpg b/docs/sbs/zh/QuecPythonSys/media/filesystem_02.jpg new file mode 100644 index 0000000000000000000000000000000000000000..21b5ef0284bc874f7d0c92b9161f7b56c91913a6 Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_02.jpg differ diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_03.jpg b/docs/sbs/zh/QuecPythonSys/media/filesystem_03.jpg new file mode 100644 index 0000000000000000000000000000000000000000..322f3f654806cbc5e6ba7ed64058142583c6d442 Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_03.jpg differ diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_04.jpg b/docs/sbs/zh/QuecPythonSys/media/filesystem_04.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7c5b4a8eb58b280bbc701708f5b14b734100c05d Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_04.jpg differ diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_05.jpg b/docs/sbs/zh/QuecPythonSys/media/filesystem_05.jpg new file mode 100644 index 0000000000000000000000000000000000000000..12a9f7620876915bacffadebb9e4880e07375861 Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_05.jpg differ diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_06.png b/docs/sbs/zh/QuecPythonSys/media/filesystem_06.png new file mode 100644 index 0000000000000000000000000000000000000000..426fda2253d2726f3e5b5c3335a1fe5e031ca3ea Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_06.png differ diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_07.png b/docs/sbs/zh/QuecPythonSys/media/filesystem_07.png new file mode 100644 index 0000000000000000000000000000000000000000..90bd22f3ecefbd6a4eaff6f23d1db6f2909fb90f Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_07.png differ diff --git a/docs/sbs/zh/QuecPythonSys/media/filesystem_08.png b/docs/sbs/zh/QuecPythonSys/media/filesystem_08.png new file mode 100644 index 0000000000000000000000000000000000000000..e9600be3531d9e5c3975c86692cfb2f66ffea1d0 Binary files /dev/null and b/docs/sbs/zh/QuecPythonSys/media/filesystem_08.png differ diff --git a/docs/sbs/zh/QuecPythonWirelessNetwork/sim.md b/docs/sbs/zh/QuecPythonWirelessNetwork/sim.md index 6c931616a6e34442c2e0a28b9df1f1ac5aa03d1d..f952e5148494e6c4eefbe749d858ddf24a81e1a5 100644 --- a/docs/sbs/zh/QuecPythonWirelessNetwork/sim.md +++ b/docs/sbs/zh/QuecPythonWirelessNetwork/sim.md @@ -1,8 +1,8 @@ ## 修订记录 -| 版本 | 日期 | 作者 | 变更表述 | -| ---- | ---------- | ------ | ------------ | -| 1.0 | 2021-09-13 | Kayden | 初始版本修订 | +| 版本 | 日期 | 作者 | 变更表述 | +| ---- | ---------- | ---------- | ------------ | +| 1.0 | 2021-09-13 | David.Tang | 初始版本修订 | ## 前言 diff --git a/docs/sbs/zh/thread/code/example_thread_file.py b/docs/sbs/zh/thread/code/example_thread_file.py new file mode 100644 index 0000000000000000000000000000000000000000..c7c4fdfeed2286e8f4527486dd9a2389bb475856 --- /dev/null +++ b/docs/sbs/zh/thread/code/example_thread_file.py @@ -0,0 +1,53 @@ +import _thread +import utime +import log +from machine import UART + +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +uart_log = log.getLogger("Thread") + +state = 1 +msglen = 0 +count = 10 +uart = UART(UART.UART2, 115200, 8, 0, 1, 0) + +def uartwrite(): + global count + while count: + write_msg = "Quectel count={}".format(count) # 发送数据 + uart.write(write_msg) + uart_log.info("write msg :{}".format(write_msg)) + utime.sleep(1) + count -= 1 + if count == 0: + break + uart_log.info("uartWrite end!") + +def uartread(): + global state + global msglen + while 1: + utime.sleep_ms(10) + msgLen = uart.any() # 返回是否有可读取的数据长度 + if msgLen: + msg = uart.read(msgLen) # 当有数据时进行读取 + utf8_msg = msg.decode() # 初始数据是字节类型(bytes),将字节类型数据转STR + uart_log.info("uartread msg: {}".format(utf8_msg)) + state = 0 + break + else: + continue + +def run(): + _thread.start_new_thread(uartread, ()) # 创建一个线程来监听接收uart消息 + _thread.start_new_thread(uartwrite, ()) + + +if __name__ == "__main__": + run() + while 1: + if state: + pass + else: + break \ No newline at end of file diff --git a/docs/sbs/zh/thread/media/_thread_01.jpg b/docs/sbs/zh/thread/media/_thread_01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9d74d16a7a2fe91c1cccfae52a43f0f404ec20ee Binary files /dev/null and b/docs/sbs/zh/thread/media/_thread_01.jpg differ diff --git a/docs/sbs/zh/thread/media/_thread_02.png b/docs/sbs/zh/thread/media/_thread_02.png new file mode 100644 index 0000000000000000000000000000000000000000..7e383ac56a31aace1d39e8894a2dfab26016da6b Binary files /dev/null and b/docs/sbs/zh/thread/media/_thread_02.png differ diff --git a/docs/sbs/zh/thread/media/_thread_03.png b/docs/sbs/zh/thread/media/_thread_03.png new file mode 100644 index 0000000000000000000000000000000000000000..1926877555c918027285bccf412612a9f1bd4436 Binary files /dev/null and b/docs/sbs/zh/thread/media/_thread_03.png differ diff --git a/docs/sbs/zh/thread/media/filesystem_01.jpg b/docs/sbs/zh/thread/media/filesystem_01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1931c71147c5b749bd3c5dbbd505cc2109547ebd Binary files /dev/null and b/docs/sbs/zh/thread/media/filesystem_01.jpg differ diff --git a/docs/sbs/zh/thread/thread.md b/docs/sbs/zh/thread/thread.md index 6bd83faf1bd2ffee945bf7ebdf624c45ab4b60e5..082c47a4bf31fcf9b8e0a5e5b8cb2efc5fc49892 100644 --- a/docs/sbs/zh/thread/thread.md +++ b/docs/sbs/zh/thread/thread.md @@ -1,107 +1,137 @@ -## 多线程 应用开发指导 -本片文章主要简介 QUecPython 的使用教程,关于QuecPython 线程的API 讲解、请参考 -[QuecPython wiki thread API 讲解](https://python.quectel.com/wiki/#/zh-cn/api/pythonStdlib?id=_thread-%e5%a4%9a%e7%ba%bf%e7%a8%8b) +## 修订历史 -## 文档历史 +| Version | Date | Author | Change expression | +| ------- | ---------- | ---------- | ----------------- | +| 1.0 | 2021-09-16 | David.Tang | Initial version | -**修订记录** +## 前言 -| **版本** | **日期** | **作者** | **变更表述** | -| -------- | -------- | -------- | ------------ | -| 1.0 | 2021-4-6 | chengzhu | 初始版本 | +本文以EC600U-CN为例介绍如何使用QuecPython的多线程功能。几乎所有操作系统均支持进程(Process)概念,操作系统中正在运行中的任务一般对应一个进程。当一个程序进入内存运行时,即变成一个进程。多线程扩展了多进程的概念,使得同一个进程可以同时并发处理多个任务。线程(Thread)也被称作轻量级进程(Lightweight Process),线程是进程的执行单元。类似进程在操作系统中的地位,线程在程序中是独立的、并发的执行流。 -### 多线程/进程的基本概念 +## 硬件描述 -Python 运行在 Python 虚拟机中,用户创建的多线程只是在 Python -虚拟机中的虚拟线程,而非在操作系统中的真正的线程。也就是说,Python -中的多线程是由 Python 虚拟机来进行轮询调度,而不是操作系统。 +线程是软件层面的功能实现,硬件方面只需要足够的内存即可,此处不再赘述。 -多线程可以使同一程序同时执行多个任务。线程在执行过程中与进程存在区别,在每个独立的线程中,都分别存在程序运行的入口、顺序执行序列以及程序的出口。并且线程必须依附在某个程序中,由程序来控制多个线程的运行。 +## 软件设计 -**线程的基本操作** +thread 模块提供创建新线程的方法,并提供互斥锁,具体的功能介绍见:[_thread](https://python.quectel.com/wiki/#/zh-cn/api/pythonStdlib?id=_thread-%e5%a4%9a%e7%ba%bf%e7%a8%8b) -> 线程具有 5 种状态,状态转换的过程如下: +## 交互操作 -![线程5种状态](media/Qp_sbs_thread_01.png) +使用QPYcom工具和EC600S-CN进行交互,具体如下截图。 -> 图 **1**:线程的 **5** 种状态 - -**线程和进程的主要区别** - -线程和进程都是操作系统控制程序运行的基本单位,系统可以利用这两个特性对程序实现高并发。而线程和进程的主要区别如下: +```python +>>> import _thread +>>> _thread.get_ident() +2126467632 +>>> _thread.get_heap_size() +748032 +>>> lock = _thread.allocate_lock() +>>> lock.acquire() +True +>>> lock.locked() +True +>>> lock.release() +>>> lock.locked() +False +``` -1. 一个程序至少有一个进程;一个进程中至少包含一个线程。 +注意: -2. 进程在内存中拥有独立的存储空间,而多个线程则共享它所依赖的进程的存储空间。 +1. import _thread即为让 _thread模块在当前空间可见。 -3. 进程和线程对操作系统的资源管理的方式不同。 +2. 只有import _thread模块,才能使用 _thread内的函数和变量。 -## QuecPython 常见使用情形 +## 下载验证 -### 使用线程、传递多个参数 -[线程传递多个参数](code/Qp_thread_trans_mutil_args.py) +### 软件代码 -传递多个参数的时候, 使用**元组**来进行数据的传递。 +配套demo的参考代码为文档同目录下的example_thread_file.py文件。下载example_thread_file.py文件到EC600U-CN并运行,代码如下: ```python -import _thread as thread -import utime as time - - -def th_func(thread_id, delay): - print("thread:{} delay {}".format(thread_id, delay)) - time.sleep_ms(delay) - - -def main(): - print("线程传递多个参数测试") - for i in range(5): - thread.start_new_thread(th_func, (i + 1, 2)) - # 等待所有子线程回收 - time.sleep_ms(100) - - -main() +import _thread +import utime +import log +from machine import UART + +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +uart_log = log.getLogger("Thread") + +state = 1 +msglen = 0 +count = 10 +uart = UART(UART.UART2, 115200, 8, 0, 1, 0) + +def uartwrite(): + global count + while count: + write_msg = "Quectel count={}".format(count) # 发送数据 + uart.write(write_msg) + uart_log.info("write msg :{}".format(write_msg)) + utime.sleep(1) + count -= 1 + if count == 0: + break + uart_log.info("uartWrite end!") + +def uartread(): + global state + global msglen + while 1: + utime.sleep_ms(10) + msgLen = uart.any() # 返回是否有可读取的数据长度 + if msgLen: + msg = uart.read(msgLen) # 当有数据时进行读取 + utf8_msg = msg.decode() # 初始数据是字节类型(bytes),将字节类型数据转STR + uart_log.info("uartread msg: {}".format(utf8_msg)) + state = 0 + break + else: + continue + +def run(): + _thread.start_new_thread(uartread, ()) # 创建一个线程来监听接收uart消息 + _thread.start_new_thread(uartwrite, ()) + + +if __name__ == "__main__": + run() + while 1: + if state: + pass + else: + break ``` -### 线程退出 -暂时没有提供类似于 **join** 函数之类的操作, 前期可以使用一个全局的标志位来标志线程的退出。 -[线程退出代码](code/Qp_thread_exit.py) +### 硬件连接 -```python -import _thread as thread -import utime as time +通过type-c接口给EC600U-CN供电,UART与TTL转USB模块的连接如下表(仅供参考): -exited = False +| EC600U模组_PIN脚 | EC600U_QuecPython_EVB_V1.3 | TTL转USB模块 | +| :--------------: | :------------------------: | :----------: | +| PIN31 | J5_PIN9 | Tx | +| PIN32 | J5_PIN8 | Rx | +| / | GND | GND | +硬件连接展示图如下所示: -def th_func(thread_id, delay): - global exited - print("thread:{} delay {}".format(thread_id, delay)) - time.sleep_ms(delay) - exited = True +![_thread_01](media/_thread_01.jpg) +### 运行效果 -def main(): - print("线程传递多个参数测试") - # for i in range(5): - thread.start_new_thread(th_func, (1, 2000)) - # 等待所有子线程回收 - while exited is False: - time.sleep_ms(100) - print("等待线程退出") +(1)打开QPYcom运行example_thread_file.py,如下图: +![_thread_02](media/_thread_02.png) -main() -``` +(2)由于两个线程同时进行,故UART写数据的同时,可向EC600U-CN串口发送数据(如下只表示读写的同时进行,但是具体的log输出顺序取决于手动发送的时间)。如下是在EC600U-CN写数据的第三和第四间隙,通过TTL转USB向EC600U-CN发送“QuecPython”。 + +![_thread_03](media/_thread_03.png) -### 线程间通讯 -待补充 +## 配套代码 -### 同时访问共享变量、需要注意的问题 -待补充 + -### 设置线程优先级 -待补充 +下载代码