ESP32-C3 入门笔记04:gpio_key 按键 (ESP-IDF + VSCode)

1.GPIO简介

ESP32-C3是QFN32封装,GPIO引脚一共有22个,从GPIO0到GPIO21。

理论上,所有的IO都可以复用为任何外设功能,但有些引脚用作连接芯片内部FLASH或者外部FLASH功能时,官方不建议用作其它用途。

通过开发板的原理图,可以看到开发板上的ESP32引脚连接情况。这里我们使用BOOT按键,来学习一下GPIO功能。

ESP32的GPIO,可以用作输入、输出,可以配置内部上拉、下拉,可以配置为中断引脚。

这里我们把连接 BOOT按键的IO9 引脚,设置为GPIO中断,接收BOOT按键请求。

在这里插入图片描述

2.编写程序

我们复制 esp-idf-v5.1.4\examples\get-started\sample_project 这个工程到我们的实验文件夹,然后把这个文件夹的名称修改为 gpio_key,方便日后搞清楚这个工程的作用。

在ESP-IDF的安装路径下,打开官方例程:D:\ESP_IDF\INS\Espressif\frameworks\esp-idf-v5.1.4\examples\get-started

在这里插入图片描述

使用 VSCode 打开 gpio_key 这个文件夹。单击打开工程一级目录下的 CMakeLists.txt 文件(注意不是 main 目录下的),然后我们把工程名字修改为 gpio_key,保存后关闭此文件。
在这里插入图片描述

点击打开main.c文件,发现里面只写了这么几行代码:

#include <stdio.h>void app_main(void)
{}

从这个工程原来的文件夹名字就可以知道,这是一个示例工程,我们现在需要实现按键中断,比较简单,所以在这个工程上写就可以了。

现在再打开一个VSCode软件,然后打开esp-idf-v5.1.4整个工程文件夹,然后我们依次找到
examples\peripherals\gpio\generic_gpio这个工程作为参考,注意不要修改这个工程中的内容和配置,只是作为参考。

在这里插入图片描述

单击gpio_example_main.c打开这个文件,找到app_main函数。

/* GPIO ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"/*** Brief:* This test code shows how to configure GPIO and how to use GPIO interrupts.** GPIO status:* GPIO18: output (ESP32C2/ESP32H2 uses GPIO8 as the second output pin)* GPIO19: output (ESP32C2/ESP32H2 uses GPIO9 as the second output pin)* GPIO4:  input, pulled up, interrupt from rising edge and falling edge* GPIO5:  input, pulled up, interrupt from rising edge.** Note. These are the default GPIO pins to be used in the example. You can* change IO pins in menuconfig.** Test:* Connect GPIO18(8) with GPIO4* Connect GPIO19(9) with GPIO5* Generate pulses on GPIO18(8)/19(9), that triggers interrupt on GPIO4/5*/#define GPIO_OUTPUT_IO_0    CONFIG_GPIO_OUTPUT_0
#define GPIO_OUTPUT_IO_1    CONFIG_GPIO_OUTPUT_1
#define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))#define GPIO_INPUT_IO_0     CONFIG_GPIO_INPUT_0
#define GPIO_INPUT_IO_1     CONFIG_GPIO_INPUT_1
#define GPIO_INPUT_PIN_SEL  ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志的宏定义// 将 GPIO 中断事件发送到这个队列gpio_evt_queue,以便在任务中处理。
// gpio_evt_queue 被用来接收中断处理程序发送的 GPIO 事件然后由 gpio_task_example 任务处理这些事件。static QueueHandle_t gpio_evt_queue = NULL; // 静态队列句柄// ISR 中断服务函数
static void IRAM_ATTR gpio_isr_handler(void* arg)
{uint32_t gpio_num = (uint32_t) arg;//xQueueSendFromISR是在 ISR(中断服务例程)中发送数据到 FreeRTOS 队列的函数调用。//gpio_evt_queue:要发送数据的队列句柄。//&gpio_num:要发送的数据,这里是指向 GPIO 编号的指针,表示触发中断的引脚。//NULL:优先级参数xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); }// GPIO 任务函数
static void gpio_task_example(void* arg)
{uint32_t io_num;for(;;) {// 任务处理  处理gpio_evt_queue里面的任务if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));}}
}void app_main(void)
{// 零初始化配置结构gpio_config_t io_conf = {};// 配置输出引脚io_conf.intr_type = GPIO_INTR_DISABLE; // 禁用中断io_conf.mode = GPIO_MODE_OUTPUT; // 设置为输出模式io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // 设置引脚gpio0/gpio1io_conf.pull_down_en = 0; // 禁用下拉模式io_conf.pull_up_en = 0; // 禁用上拉模式gpio_config(&io_conf); // 配置 GPIO// 配置输入引脚io_conf.intr_type = GPIO_INTR_POSEDGE; // 上升沿中断io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL; // 设置引脚gpio0/gpio1io_conf.mode = GPIO_MODE_INPUT; // 设置为输入模式io_conf.pull_up_en = 1; // 启用上拉模式gpio_config(&io_conf); // 配置 GPIO// 改变 GPIO 中断类型gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE); // 任何边缘中断// 创建队列以处理 ISR 的 GPIO 事件gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));// 启动 GPIO 任务xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);// 安装 GPIO ISR 服务gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);// 钩住 ISR 处理程序gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);// 从 GPIO 中移除 ISR 处理程序(可选)gpio_isr_handler_remove(GPIO_INPUT_IO_0);gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0); // 再次钩住 ISRprintf("Minimum free heap size: %"PRIu32" bytes\n", esp_get_minimum_free_heap_size());int cnt = 0;while(1) {printf("cnt: %d\n", cnt++);vTaskDelay(1000 / portTICK_PERIOD_MS);gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2); // 切换输出引脚状态gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2); // 切换输出引脚状态}
}

复制它的前几行语句(第80~93行)到我们自己的gpio_key工程中,如下所示:

#include <stdio.h>void app_main(void)
{//zero-initialize the config structure.gpio_config_t io_conf = {};//disable interruptio_conf.intr_type = GPIO_INTR_DISABLE; // 关闭中断//set as output modeio_conf.mode = GPIO_MODE_OUTPUT; // 输出模式//bit mask of the pins that you want to set,e.g.GPIO18/19io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // 配置引脚号//disable pull-down modeio_conf.pull_down_en = 0; // 上下拉电阻,0是关闭,1是打开//disable pull-up modeio_conf.pull_up_en = 0; //configure GPIO with the given settingsgpio_config(&io_conf);// 使用gpio_config函数进行配置
}

在这里插入图片描述

gpio_example_main.c文件中的GPIO_INTR_DISABLE上单击右键,然后选择“转到定义”,就可以找到这几个宏定义,如下所示:

typedef enum {
GPIO*INTR_DISABLE = 0, //*!< Disable GPIO interrupt 禁用 GPIO 中断 _/
GPIO_INTR_POSEDGE = 1, //_!< GPIO interrupt type : rising edge 中断类型:上升沿_/
GPIO_INTR_NEGEDGE = 2, //_!< GPIO interrupt type : falling edge 中断类型:下降沿_/
GPIO_INTR_ANYEDGE = 3, //_!< GPIO interrupt type : both rising and falling edge 中断类型:上升沿和下降沿均可_/
GPIO_INTR_LOW_LEVEL = 4, //_!< GPIO interrupt type : input low level trigger 中断类型:低电平触发_/
GPIO_INTR_HIGH_LEVEL = 5,//_!< GPIO interrupt type : input high level trigger 中断类型:高电平触发\_/
GPIO_INTR_MAX,
} gpio_int_type_t;

上面的代码,总结来说一下,就是先定义一个GPIO结构体,然后给GPIO结构体成员变量赋值,然后使用GPIO配置函数配置GPIO。给结构体成员变量赋值,也可以在定义的时候直接赋值,如下代码所示:

方法1:

void app_main(void)
{
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_NEGEDGE, //falling edge interrupt
.mode = GPIO_MODE_INPUT, //set as input mode
.pin_bit_mask = 1<<GPIO_NUM_9, //bit mask of the pins GPIO9
.pull_down_en = 0, //disable pull-down mode
.pull_up_en = 1 //enable pull-up mode
};
//configure GPIO with the given settings
gpio_config(&io_conf);
}

方法2:

void app_main(void)
{
//zero-initialize the config structure.
gpio_config_t io_conf = {};
//falling edge interrupt
io_conf.intr_type = GPIO_INTR_NEGEDGE;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//bit mask of the pins GPIO9
io_conf.pin_bit_mask = 1<<GPIO_NUM_9;
//disable pull-down mode
io_conf.pull_down_en = 0;
//enable pull-up mode
io_conf.pull_up_en = 1;
//configure GPIO with the given settings
gpio_config(&io_conf);
}

接下来,我们再复制gpio_example_main.c文件中的第108~116行代码到我们的main.c文件中。

    //create a queue to handle gpio event from isrgpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));//start gpio taskxTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);//install gpio isr servicegpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);//hook isr handler for specific gpio pingpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);

开始,定义了一个队列句柄,用来处理gpio队列消息。

然后,定义了两个函数。

第一个函数是gpio 中断服务函数,当GPIO产生中断的时候呢,会进入这个函数,xQueueSendFromISR函数将参数GPIO_NUM_9添加到队列消息。

第二个函数是gpio的 任务函数,在任务函数中,接收队列消息,当接收到一个队列消息时,打印字符串。

PRIu32 是C语言中用于格式化输出的宏,用于打印32位无符号整数。它是由C99标准引入的,位于inttypes.h头文件中。在使用该宏时,需要包含inttypes.h头文件。

gpio_get_level函数用于获取引脚的电平。 这些内容,不需要做修改。 接下来,我们再把需要的头文件添加到我们的main.c文件就可以了。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

使用printf函数,需要添加stdio.h头文件。string.h和stdlib.h我们这里用不着,可以去掉。接下来是3个freeRTOS的头文件,最后一个头文件是用于gpio的配置。

3.编译和下载

接下来,依次配置VSCode左下角的配置选项,串口号、目标芯片、下载方式、menuconfig里面,把FLASH大小修改为8MB,其它不做修改。

在这里插入图片描述

中断输入是项目中常用的方式,如果你想试试查询法,可以不开中断,使用gpio_get_level函数查询引脚电平。 引脚设置为输出,可以使用gpio_set_level来控制引脚的电平。具体使用方法,可以查看我们刚才参考的gpio例程。 ESP32还有一个特殊的引脚,就是GPIO11,它默认是VDD_SPI引脚,VDD_SPI默认是一个3.3V输出的电源引脚,可以用来给外部的FLASH芯片供电,这个引脚也可以修改为GPIO11,作为通用引脚使用。需要注意的是,这个修改是不可逆的,修改成GPIO11以后,就不能再修改为3.3V输出电源引脚了。我们在设计电路的时候,可以根据需求,决定是否用这个引脚给外部FLASH供电。我们的开发板没有用这个引脚给外部FLASH供电,而是作为GPIO引脚。这个引脚设置为GPIO的方法,我们会在I2S音频接口章节介绍。



源文件 main.c

#include <stdio.h>
#include <inttypes.h>// C99标准  PRIu32无符号32位数据类型
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"// 声明一个静态队列句柄,用于处理 GPIO 事件
static QueueHandle_t gpio_evt_queue = NULL;// GPIO 中断服务例程(ISR)处理函数
static void IRAM_ATTR gpio_isr_handler(void* arg)
{uint32_t gpio_num = (uint32_t) arg; // 获取触发中断的 GPIO 编号xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); // 将 GPIO 编号发送到队列
}// GPIO 任务示例
static void gpio_task_example(void* arg)
{uint32_t io_num; // 存储接收到的 GPIO 编号for(;;) {// 从队列中接收 GPIO 事件,阻塞直到有数据可用  portMAX_DELAY表示如果没有接收到消息,则会一直等待if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {// 打印触发中断的 GPIO 编号及其当前电平值printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));// gpio_set_level( GPIO_NUM_9,1)}}
}// 主应用程序入口
void app_main(void)
{// 零初始化配置结构gpio_config_t io_conf = {.intr_type =  GPIO_INTR_NEGEDGE, // 设置为下降沿中断.mode = GPIO_MODE_INPUT,         // 设置为输入模式.pin_bit_mask = 1ULL << GPIO_NUM_9, // 设置引脚位掩码,指定为 GPIO_NUM_9.pull_down_en = 0,               // 禁用下拉模式.pull_up_en = 1                   // 启用上拉模式};// 根据配置设置 GPIOgpio_config(&io_conf);// 创建一个队列(句柄),用于处理 ISR 发送的 GPIO 事件gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));// 创建一个任务xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);//任务的函数、任务的名称、堆栈大小、传递给任务函数的参数、任务的优先级,值越大表示优先级越高、用于接收任务句柄的指针// 安装 GPIO ISR 服务gpio_install_isr_service(0); // 默认值0// 为特定 GPIO 引脚钩住 ISR 处理程序gpio_isr_handler_add(GPIO_NUM_9, gpio_isr_handler, (void*) GPIO_NUM_9);// 中断源 中断函数的名称 中断函数的入口参数(void* arg)
}

xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL); 是用于在 FreeRTOS 中创建新任务的函数调用。具体说明如下:

参数说明:

  1. gpio_task_example:要执行的任务函数名。
  2. "gpio_task_example":任务的名称,用于调试和监控。
  3. 2048:为任务分配的堆栈大小(以字节为单位),这里为 2048 字节。
  4. NULL:任务的参数,这里设置为 NULL,表示没有传递参数。
  5. 10:任务的优先级,值越大优先级越高。这里设置为 10。
  6. NULL:用于接收任务句柄的指针,这里设置为 NULL,表示不需要句柄。

功能:

  • 创建一个名为 gpio_task_example 的任务,该任务将运行 gpio_task_example 函数。
  • 这个任务将负责从 GPIO 中断队列中接收事件,并处理这些事件。

如果你有更多问题或需要进一步的解释,请告诉我!

4.实验效果

在这里插入图片描述


5.参考资料

  • [1] 立创·实战派ESP32-C3开发板 立创开发板技术文档中心
  • [2] 【B站】立创·实战派ESP32-C3【手把手带你拥有项目经验】教程-04-gpio_key按键

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/452596.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自由学习记录(11)

Surface Effector 2D Platform Effector 2D 向上跳跃穿过天花板的功能 平台效应器不用变Trigger&#xff0c;因为本来就是要有碰撞的 use one way grouping是让所有相关联的碰撞器都可以单面跳墙 默认不勾选&#xff0c;左右两边没有摩擦力和弹力&#xff0c;要自己先设置sid…

三菱PLC伺服-停止位置不正确故障排查

停止位置不正确时&#xff0c;请确认以下项目。 1)请确认伺服放大器(驱动单元)的电子齿轮的设定是否正确。 2&#xff09;请确认原点位置是否偏移。 1、设计近点信号(DOG)时&#xff0c;请考虑有足够为0N的时间能充分减速到爬行速度。该指令在DOG的前端开始减速到爬行速度&…

计算机毕业设计 基于Web的景区管理系统的设计与实现 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

市场上几个跨平台开发框架?

跨平台桌面应用开发框架是一种工具或框架&#xff0c;它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上&#xff0c;开发者需要为每个操作系统编写不同的代码&#xff0c;使用不同的开发工具和语言。而跨平台桌面应用开发框架通过…

【网络】IP协议的地址管理

【网络】IP协议的地址管理 一. IP协议格式二. 地址管理1.动态分配IP地址2.NAT机制2.1 NAT机制下网络的请求/响应 3. 网段划分3.1 特殊的IP地址 4.路由选择5.DNS域名解析系统 一. IP协议格式 4位版本号(version): 指定IP协议的版本&#xff08;IPv4/IPv6&#xff09;, 对于IPv4来…

一起搭WPF架构之livechart的MVVM使用介绍

一起搭WPF架构之livechart使用介绍 前言ModelViewModelView界面设计界面后端 效果总结 前言 简单的架构搭建已经快接近尾声了&#xff0c;考虑设计使用图表的形式将SQLite数据库中的数据展示出来。前期已经介绍了livechart的安装&#xff0c;今天就详细介绍一下livechart的使用…

第6篇:无线与移动网络

目录 引言 6.1 无线网络的基础概念 6.2 无线局域网&#xff08;WLAN&#xff09;与IEEE 802.11 6.3 蓝牙与无线个域网&#xff08;WPAN&#xff09; 6.4 无线城域网&#xff08;WMAN&#xff09;与WiMax 6.5 ZigBee与智能家居 6.6 移动蜂窝网络&#xff08;3G/4G/5G&…

SpringCloudStream使用StreamBridge实现延时队列

利用RabbitMQ实现消息的延迟队列 一、安装RabbitMQ 1、安装rabbitmq 安装可以看https://blog.csdn.net/qq_38618691/article/details/118223851,进行安装。 2、安装插件 安装完毕后,exchange是不支持延迟类型的,需要手动安装插件,需要和安装的rabbitmq版本一致 https:…

深入探讨C++多线程性能优化

深入探讨C多线程性能优化 在现代软件开发中&#xff0c;多线程编程已成为提升应用程序性能和响应速度的关键技术之一。尤其在C领域&#xff0c;多线程编程不仅能充分利用多核处理器的优势&#xff0c;还能显著提高计算密集型任务的效率。然而&#xff0c;多线程编程也带来了诸…

62天框架安全(学习)

发现学了之后没有去复习&#xff0c;每天都要问自己学了什么&#xff0c;复习了吗&#xff0c;下次还能记住吗 一下内容来自【小迪安全2023】第62天:服务攻防-框架安全&CVE复现&Spring&Struts&Laravel&ThinkPHP_小迪安全文档2023-CSDN博客 一个网站的源码…

排序算法 —— 直接插入排序

目录 1.直接插入排序的思想 2.直接插入排序的实现 实现分析 实现代码 3.直接插入排序的分析 时间复杂度分析 空间复杂度分析 稳定性 1.直接插入排序的思想 直接插入排序的思想就是把待排序的元素按其关键码值的大小依次插入到一个已经排好序的有序序列中&#xff0c…

一种基于OCR图像识别技术的发票采集管理系统及方法

一种基于OCR图像识别技术的发票采集管理系统及方法 摘要 本发明涉及了一种基于OCR图像识别技术的发票采集管理系统及方法&#xff0c;该系统的发票信息采集单元采集发票图片信息数据&#xff0c;OCR图像识别单元基于OCR图像识别技术并结合人工智能深度学习算法对发票图片信息数…

vscode默认添加python项目的源目录路径到执行环境(解决ModuleNotFoundError: No module named问题)

0. 问题描述 vscode中编写python脚本&#xff0c;导入工程目录下的其他模块&#xff0c;出现ModuleNotFoundError: No module named 错误 在test2的ccc.py文件中执行print(sys.path) 查看路径 返回结果发现并无’/home/xxx/first_demo’的路径&#xff0c;所以test2下面的文…

Vue-router 路由守卫执行流程图

vue-router 路由守卫执行的流程图&#xff08;个人理解&#xff09; 图1 - 图2

【MR开发】在Pico设备上接入MRTK3(一)——在Unity工程中导入MRTK3依赖

写在前面的话 在Pico上接入MRTK3&#xff0c;目前已有大佬开源。 https://github.com/Phantomxm2021/PicoMRTK3 也有值得推荐的文章。 MRTK3在PICO4上的使用小结 但由于在MacOS上使用MRTK3&#xff0c;无法通过Mixed Reality Feature Tool工具管理MRTK3安装包。 故记录一下…

jmeter使用文档

文章目录 一、安装使用1、下载2、bin/jmeter.properties介绍 二、windows使用1、微调&#xff08;1&#xff09;界面样式&#xff08;2&#xff09;修改语言 2、简单使用3、各组件详解&#xff08;1&#xff09;CSV 数据文件配置&#xff08;2&#xff09;BeanShell取样器 三、…

Pair的基本概念

概述 当一个方法需返回两个值、并且两个值都有重要意义时&#xff0c;我们一般会用Map的key、value来表达。 但是如果仅返回两个值&#xff0c;就用管理一堆key/value键值对的HashMap等结构&#xff0c;有点大材小用&#xff0c;增加了数据结构的复杂度。所以便出现了pair这个…

RAG流程的实现与改进

一、 RAG流程图 数据入库&#xff1a;读取本地数据并切成小块&#xff0c;并把这些小块经过编码embedding后&#xff0c;存储在一个向量数据库中&#xff08;下图1——6步&#xff09;&#xff1b;相关性检索&#xff1a;用户提出问题&#xff0c;问题经过编码&#xff0c;再在…

探索Python中的多线程与多进程

在Python编程中&#xff0c;多线程和多进程是两个重要的概念&#xff0c;它们被用来提高程序的执行效率。本文将深入探讨这两个概念&#xff0c;并对比它们在Python中的实现方式。 一、多线程 多线程是一种并发执行的程序设计方法。在Python中&#xff0c;我们可以使用thread…