gd32 i2c 中断 主机从机双向通信例程
Master
I2C0_SCL PB8 AF4
I2C0_SDA PB9 AF4
Slave
I2C1_SCL PB10 AF4
I2C1_SDA PB11 AF4
//主机中断发送
void i2c_master_transmit_it(uint32_t address, uint8_t* buff, uint32_t size);
//主机中断接收
void i2c_master_receive_it(uint32_t address, uint8_t* buff, uint32_t size, uint32_t* size_out);
//从机中断发送
void i2c_slave_transmit_it(uint8_t* buff, uint32_t size);
//从机中断接收
void i2c_slave_receive_it(uint8_t* buff, uint32_t* size_out);
main.c
/*!\file main.c\brief running LED\version 2023-03-31, V1.0.0, firmware for GD32H7xx
*/#include "gd32h7xx.h"
#include "systick.h"#include "string.h"
#include "stdio.h"#define I2C_SLAVE_ADDRESS7 0x82/*!\brief enable the CPU Chache\param[in] none\param[out] none\retval none
*/
static void cache_enable(void)
{/* Enable I-Cache */SCB_EnableICache();/* Enable D-Cache */
// SCB_EnableDCache();
}void led_config()
{rcu_periph_clock_enable(RCU_GPIOJ);gpio_mode_set(GPIOJ, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_8);gpio_output_options_set(GPIOJ, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);gpio_mode_set(GPIOJ, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_9);gpio_output_options_set(GPIOJ, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);gpio_bit_set(GPIOJ, GPIO_PIN_8);gpio_bit_set(GPIOJ, GPIO_PIN_9);}void usart_config()
{rcu_periph_clock_enable(RCU_GPIOB);rcu_periph_clock_enable(RCU_USART0);gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_6);gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_7);gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7);gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);usart_deinit(USART0);usart_word_length_set(USART0, USART_WL_8BIT);usart_stop_bit_set(USART0, USART_STB_1BIT);usart_parity_config(USART0, USART_PM_NONE);usart_baudrate_set(USART0, 921600U);usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);usart_receive_config(USART0, USART_RECEIVE_ENABLE);usart_enable(USART0);
}void usart_transmit(char* buff, int size)
{for (int i = 0; i < size; ++i) {usart_data_transmit(USART0, buff[i]);while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) {}}
}/** Master* I2C0_SCL PB8 AF4* I2C0_SDA PB9 AF4*/
void i2c0_config()
{rcu_periph_clock_enable(RCU_GPIOB);gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_8 | GPIO_PIN_9);gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8 | GPIO_PIN_9);gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8 | GPIO_PIN_9);rcu_periph_clock_enable(RCU_I2C0);i2c_deinit(I2C0);i2c_timing_config(I2C0, 0x3, 0x9, 0x0);i2c_master_clock_config(I2C0, 0x96, 0xda);i2c_enable(I2C0);nvic_irq_enable(I2C0_EV_IRQn, 2, 0);nvic_irq_enable(I2C0_ER_IRQn, 2, 1);
}uint8_t* master_tx_buff;
uint8_t* master_rx_buff;
uint32_t* master_rx_recv_cnt;void I2C0_EV_IRQHandler()
{if (RESET != i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_STPDET)) {i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_STPDET);} else if (RESET != i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TI)) {i2c_data_transmit(I2C0, *master_tx_buff++);} else if (RESET != i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE)) {*master_rx_buff++ = i2c_data_receive(I2C0);*master_rx_recv_cnt += 1;} else if (RESET != i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TC)) {i2c_stop_on_bus(I2C0);i2c_interrupt_disable(I2C0, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_TI | I2C_INT_RBNE | I2C_INT_TC);}
}void I2C0_ER_IRQHandler()
{if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) {i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR);}if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) {i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB);}if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) {i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR);}if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) {i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR);}if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TIMEOUT)) {i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_TIMEOUT);}if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) {i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT);}i2c_interrupt_disable(I2C0, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_RBNE | I2C_INT_TI | I2C_INT_TC);
}void i2c_master_transmit_it(uint32_t address, uint8_t* buff, uint32_t size)
{master_tx_buff = buff;i2c_master_addressing(I2C0, address, I2C_MASTER_TRANSMIT);i2c_transfer_byte_number_config(I2C0, size);i2c_interrupt_enable(I2C0, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_TI | I2C_INT_TC);while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { } //等待总线空闲I2C_STAT(I2C0) |= I2C_STAT_TBE;i2c_start_on_bus(I2C0);
}void i2c_master_receive_it(uint32_t address, uint8_t* buff, uint32_t size, uint32_t* size_out)
{master_rx_buff = buff;master_rx_recv_cnt = size_out;*master_rx_recv_cnt = 0;i2c_master_addressing(I2C0, address, I2C_MASTER_RECEIVE);i2c_transfer_byte_number_config(I2C0, size);i2c_interrupt_enable(I2C0, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_RBNE | I2C_INT_TC);while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { } //等待总线空闲i2c_start_on_bus(I2C0);
}/** Slave* I2C1_SCL PB10 AF4* I2C1_SDA PB11 AF4*/
void i2c1_config()
{rcu_periph_clock_enable(RCU_GPIOB);gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_10 | GPIO_PIN_11);gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10 | GPIO_PIN_11);gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10 | GPIO_PIN_11);rcu_periph_clock_enable(RCU_I2C1);i2c_deinit(I2C1);i2c_address_config(I2C1, I2C_SLAVE_ADDRESS7, I2C_ADDFORMAT_7BITS);i2c_enable(I2C1);nvic_irq_enable(I2C1_EV_IRQn, 2, 2);nvic_irq_enable(I2C1_ER_IRQn, 2, 3);
}uint8_t* slave_tx_buff;
uint8_t* slave_rx_buff;
uint32_t* slave_rx_recv_cnt;void I2C1_EV_IRQHandler()
{if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_ADDSEND);I2C_STAT(I2C1) |= I2C_STAT_TBE;} else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RBNE)) {*slave_rx_buff++ = i2c_data_receive(I2C1);*slave_rx_recv_cnt += 1;} else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_TI)) {i2c_data_transmit(I2C1, *slave_tx_buff++);} else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_STPDET)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_STPDET);i2c_interrupt_disable(I2C1, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_ADDM | I2C_INT_TI | I2C_INT_RBNE);}
}void I2C1_ER_IRQHandler()
{if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_BERR)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_BERR);}if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_LOSTARB)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_LOSTARB);}if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_OUERR)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_OUERR);}if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_PECERR)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_PECERR);}if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_TIMEOUT)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_TIMEOUT);}if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBALT)) {i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBALT);}i2c_interrupt_disable(I2C1, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_ADDM | I2C_INT_RBNE | I2C_INT_TI);
}void i2c_slave_transmit_it(uint8_t* buff, uint32_t size)
{slave_tx_buff = buff;i2c_interrupt_enable(I2C1, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_ADDM | I2C_INT_TI);
}void i2c_slave_receive_it(uint8_t* buff, uint32_t* size_out)
{slave_rx_recv_cnt = size_out;*slave_rx_recv_cnt = 0;slave_rx_buff = buff;i2c_interrupt_enable(I2C1, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_ADDM | I2C_INT_RBNE);
}/*!\brief main function\param[in] none\param[out] none\retval none
*/
int main(void)
{/* enable the CPU Cache */cache_enable();/* configure systick */systick_config();led_config();usart_config();i2c0_config();i2c1_config();while(1) {//-----------------------------------------------------------------------uint8_t tx1[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};uint8_t rx1[8] = {0};uint32_t rx1_recv_bytes = 0;i2c_slave_receive_it(rx1, &rx1_recv_bytes);i2c_master_transmit_it(I2C_SLAVE_ADDRESS7, tx1, 8);delay_1ms(10);//上位机应接收到 "0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88"usart_transmit(rx1, rx1_recv_bytes);//-----------------------------------------------------------------------uint8_t tx2[4] = {0x44, 0x33, 0x22, 0x11};uint8_t rx2[4] = {0};uint32_t rx2_recv_bytes = 0;i2c_slave_receive_it(rx2, &rx2_recv_bytes);i2c_master_transmit_it(I2C_SLAVE_ADDRESS7, tx2, 4);delay_1ms(10);//上位机应接收到 "0x44, 0x33, 0x22, 0x11"usart_transmit(rx2, rx2_recv_bytes);//-----------------------------------------------------------------------uint8_t tx3[4] = {0x12, 0x34, 0x56, 0x78};uint8_t rx3[4] = {0};uint32_t rx3_recv_bytes = 0;i2c_slave_transmit_it(tx3, 4);i2c_master_receive_it(I2C_SLAVE_ADDRESS7, rx3, 4, &rx3_recv_bytes);delay_1ms(10);//上位机应接收到 "0x12, 0x34, 0x56, 0x78"usart_transmit(rx3, rx3_recv_bytes);//-----------------------------------------------------------------------uint8_t tx4[4] = {0xaa, 0xbb, 0xcc, 0xdd};uint8_t rx4[4] = {0};uint32_t rx4_recv_bytes = 0;i2c_slave_transmit_it(tx4, 4);i2c_master_receive_it(I2C_SLAVE_ADDRESS7, rx4, 4, &rx4_recv_bytes);delay_1ms(10);//上位机应接收到 "0xaa, 0xbb, 0xcc, 0xdd"usart_transmit(rx4, rx4_recv_bytes);delay_1ms(1000);}
}
相关文章:
gd32 i2c 中断 主机从机双向通信例程
Master I2C0_SCL PB8 AF4 I2C0_SDA PB9 AF4 Slave I2C1_SCL PB10 AF4 I2C1_SDA PB11 AF4 //主机中断发送 void i2c_master_transmit_it(uint32_t address, uint8_t* buff, uint32_t size); //主机中断接收 void i2c_master_receive_it(uint32_t address, uint8_t* buff, uint…...
程序员在AI时代:重塑核心竞争力,共舞智能未来
程序员在AI时代:重塑核心竞争力,共舞智能未来 在这个日新月异的科技时代,人工智能生成内容(AIGC)技术,尤其是以ChatGPT、Midjourney、Claude等为代表的大语言模型,正以前所未有的速度渗透到编程…...
apex发送邮件中显示饼状图和条形图
在 Apex 中发送带有嵌入图表(如饼状图和条形图)的电子邮件,您可以通过以下步骤实现: 生成图表图像:使用外部库或服务生成图表图像并获取图像的 URL 或 Base64 编码。创建电子邮件模板:在 HTML 邮件模板中嵌…...

【HarmonyOS NEXT星河版开发学习】小型测试案例07-弹性布局小练习
个人主页→VON 收录专栏→鸿蒙开发小型案例总结 基础语法部分会发布于github 和 gitee上面(暂未发布) 前言 在鸿蒙(HarmonyOS)开发中,Flex布局是一种非常有用的布局方式,它允许开发者创建灵活且响…...
Sparksql array相关函数
前言 Apache Spark SQL 是 Spark 的一个重要模块,用于处理结构化数据。它提供了 DataFrame 和 Dataset API,使得开发者能够使用 SQL 查询语言(称为 Spark SQL)对数据进行高效的操作。在本文中,我们将介绍 Spark SQL 中所有与array相关的函数。 环境 sparksql版本<dep…...

软件测试学习笔记
测试学习 1. 测试流程2. Bug的提出什么是bugbug 的描述bug 级别 3. 测试用例的设计什么是测试用例测试用例应如何设计基于需求的设计方法等价类边界值场景法正交表法判定表法错误猜测法 4. 自动化测试回归测试自动化分类 5. 安装 webdriver-manager 和 selenium第一个web自动化…...
Centos 8系统ext4文件系统类型进行扩容缩容 (LVM)
Centos 8系统ext4文件系统类型进行扩容缩容 (LVM) 1.磁盘情况:2.缩容home分区1.备份home数据:2.查找使用 /home 的进程:3.终止这些进程:4.卸载 /home 分区5.检查文件系统一致性 (e2fsck):6.调整…...
常考常考高频率
1.快排(双指针) 快排,归并排序,堆排序 #快速排序O(nlogn) def quick_sort(array, left, right):if left < right:mid partition(array, left, right)quick_sort(array, left, mid)quick_sort(array, …...

Linux项目环境的搭建 (Red hat 9.0Linux操作系统)
一、目的: 1.搭建Linux操作系统项目所需的项目环境构件; 2.了解 Linux的组成,学会编译内核。 二、内容: 安装Red hat 9.0Linux操作系统; 三、步骤: 3.1 正确安装Redhat9.0操作系统。 3.2 rpm -Uvh *.…...

Study--Oracle-08-ORACLE数据备份与恢复(一)
一、ORACLE数据保护方案 1、oracle数据保护方案 2、数据库物理保护方案 oracle数据库备份可以备份到本地集群存储,也可以备份到云存储。 3、数据库逻辑数据保护方案 二、ORACLE数据体系 1、ORACLE 数据库的存储结构 2、oracle物理和逻辑存储结构 3、数据库进程 4、数据库日…...

FreeIPA安装
一、环境准备 主机名IP角色master. bhlu. com192.168.22.10服务端node1. bhlu. com192.168.22.11客户端 两台服务器关闭防火墙和 selinux配置好 yum 源 1.1 配置 chronyd 配置好 chronyd,使用 chronyc source -v 可以验证 # 这里写了一个playbook作为示例了 --…...
mysql数据库:SQL语言基础和基本查询
mysql数据库:SQL语言基础和基本查询 SQL语言简介 Structured Query Language, 结构化查询语言非过程性语言为加强SQL的语言能力,各厂商增强了过程性语言的特征如:Oracle的PL/SQL 过程性处理能力,SQL Server、Sybase的T-SQLSQL是用…...

strimzi operator 部署kafka集群(可外部访问)
Strimzi介绍 官方文档:https://strimzi.io/docs/operators/0.42.0/overview#kafka-components_str Strimzi介绍 Strimzi 是一个用于 Apache Kafka 在 Kubernetes 上部署和管理的开源项目。它提供了一组 Kubernetes 自定义资源定义(Custom Resource Definitions,CRDs)、控制…...

【网络安全】探索AI 聊天机器人工作流程实现RCE
未经许可,不得转载。 文章目录 前言正文前言 我发现了一个广泛使用的AI聊天机器人平台中的远程代码执行漏洞。该漏洞存在于聊天机器人的自定义工作流响应代码中,这些工作流允许开发人员通过创建定制的流程来扩展机器人的功能。 正文 在浏览自动化聊天机器人的多个特定功能…...
虚拟DOM、Vue渲染流程
虚拟DOM(Virtual DOM)是一种在前端开发中广泛使用的技术,它用JavaScript对象来表示真实DOM(文档对象模型)的结构和状态。虚拟DOM的核心思想是将页面的状态和结构保存在内存中,而不是直接操作真实的DOM。这一…...
centos7 启动python后端服务与停止服务的sh脚本
centos7 启动python后端服务与停止服务 分别在工程目录下新建启动脚本和停止脚本。 1、启动服务脚本 start_srv.sh: python3 start_srv.py运行 nohup ./start_srv.sh & 以守护进程的方式启动这个服务。 2、停止服务脚本 stop_srv.sh: sp_pidps -ef | grep start_srv…...

访问网站显示不安全怎么办?
访问网站时显示“不安全”,针对不同的原因有不同的解决方式,下面是常见的几种原因和对应的解决办法。 1.未启用HTTPS协议 如果网站仅使用HTTP协议,数据传输没加密,因此会被浏览器标记为“不安全”。解决办法是启用HTTPS协议,给…...
Scala与集合框架:高效数据处理的利器
Scala与集合框架:高效数据处理的利器 Scala 是一种现代化的编程语言,融合了面向对象编程和函数式编程的特性。其集合框架为处理数据提供了强大而灵活的工具,使得数据处理变得高效且富有表达力。本文将深入探讨 Scala 的集合框架,…...

基于 JWT 的模拟登录爬取实战
准备工作 1. 了解 JWT 相关知识 2. 安装 requests 库,并了解其基本使用 案例介绍 爬取网站: https://login3.scrape.center/ 用户名和密码是: admin 模拟登录 基于 JWT 的网站通常采用的是前后端分离式, 前后端的数据传输依…...
力扣(2024.08.06)
1. 144:二叉树的前序遍历 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def preorderTravers…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...