ESP32 I2S音频总线学习笔记(二):I2S读取INMP441音频数据
简介
在这个系列的上一篇文章中,我们介绍了ESP32 I2S音频总线的相关知识,简要了解了什么是I2S总线、它的通信格式,以及相关的底层API函数。没有看过上篇文章的可以点击文章进行回顾:
ESP32 I2S音频总线学习笔记(一):初识I2S通信与配置基础
这篇文章将介绍一个小案例——ESP32驱动INMP441读取音频数据,它是关于如何使用I2S读取数据的一个应用,主要是将ESP32读取到的音频数据发送到串口上并实时显示波形,这个我们可以通过串口绘图仪来实现。在这之前先来看一下INMP441这个模块吧
INMP441全向麦克风模块

NMP441是一款高性能、低功耗、数字输出,带底部端口的全向MEMS麦克风。该完整的INMP441解决方案由一个MEMS传感器、信号调节模块、数字混合滤波器、电源管理和行业标准的24位I²S接口组成。I²S接口允许INMP441直接连接到数字处理器,如DSP和微控制器,无需额外的音频解码器。NMP441具有高信噪比,是一种适用于近场应用的理想选择。
产品特性:
具有高精度24位数据的数字I²S接口
高信噪比为61 dBA
高灵敏度-26 dBFS
从60 Hz到15 kHz的稳定频率响应
低功耗:低电流消耗1.4 mA
高PSR:-75 dBFS
功能框图
INMP441模块使用到的芯片内置ADC,用于将采集到的模拟信号转换成数字信号,上面还有滤波器和硬件控制、电源相关的引脚。

引脚定义
| VDD | 输入电源,1.8V至3.3V |
|---|---|
| GND | 电源地 |
| SCK | I²S接口的串行数据时钟 |
| WS | 用于I²S接口的串行数据字选择 |
| SD | I²S接口的串行数据输出 |
| L/R | 左/右声道选择 |
其中L/R是 左/右声道选择。设置为低电平时,麦克风在I²S帧的左声道输出信号。设置为高电平时,麦克风在右声道输出信号。
安装I2S驱动
上篇文章我们在介绍I2S底层API函数提到,在使用I2S通信时需要加载I2S驱动,不知道小伙伴们还记不记得。这个加载I2S驱动的函数就是:esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue),里面有4个参数需要配置,在上次都有提到每个参数的意义。 其中比较复杂的是i2s_config这个结构体变量,我们需要对结构体的每个参数进行配置,如下:
typedef struct {i2s_mode_t mode; /*< 设置 I2S 的工作模式 */uint32_t sample_rate; /*!< 设置音频采样率 */i2s_bits_per_sample_t bits_per_sample; /*!< 设置采样位数 */i2s_channel_fmt_t channel_format; /*!< 设置数据通道格式.*/i2s_comm_format_t communication_format; /*!< 设置I2C数据传输格式 */int intr_alloc_flags; /*!< 设置中断相关标志位*/int dma_buf_count; dma缓存个数, int dma_buf_len;
} i2s_driver_config_t;typedef i2s_driver_config_t i2s_config_t;
除了后面几个整型变量,每个结构体成员其实是一个枚举类型
I2S工作模式mode
typedef enum {I2S_MODE_MASTER = (0x1 << 0), /*!< Master mode*/I2S_MODE_SLAVE = (0x1 << 1), /*!< Slave mode*/I2S_MODE_TX = (0x1 << 2), /*!< TX mode*/I2S_MODE_RX = (0x1 << 3), /*!< RX mode*/
#if SOC_I2S_SUPPORTS_DAC//built-in DAC functions are only supported on I2S0 for ESP32 chip.I2S_MODE_DAC_BUILT_IN = (0x1 << 4), /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
#endif // SOC_I2S_SUPPORTS_DAC
#if SOC_I2S_SUPPORTS_ADCI2S_MODE_ADC_BUILT_IN = (0x1 << 5), /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
#endif // SOC_I2S_SUPPORTS_ADC// PDM functions are only supported on I2S0 (all chips).I2S_MODE_PDM = (0x1 << 6), /*!< I2S PDM mode*/
} i2s_mode_t;
音频采样率bits_per_sample
typedef enum {I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< data bit-width: 8 */I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< data bit-width: 16 */I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< data bit-width: 24 */I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< data bit-width: 32 */
} i2s_bits_per_sample_t;
通道格式channel_format
typedef enum {I2S_CHANNEL_FMT_RIGHT_LEFT, /*!< Separated left and right channel */I2S_CHANNEL_FMT_ALL_RIGHT, /*!< Load right channel data in both two channels */I2S_CHANNEL_FMT_ALL_LEFT, /*!< Load left channel data in both two channels */I2S_CHANNEL_FMT_ONLY_RIGHT, /*!< Only load data in right channel (mono mode) */I2S_CHANNEL_FMT_ONLY_LEFT, /*!< Only load data in left channel (mono mode) */
#if SOC_I2S_SUPPORTS_TDM// Multiple channels are available with TDM featureI2S_CHANNEL_FMT_MULTIPLE, /*!< More than two channels are used */
#endif
} i2s_channel_fmt_t;
通信传输格式communication_format
typedef enum {I2S_COMM_FORMAT_STAND_I2S = 0X01, /*!< I2S communication I2S Philips standard, data launch at second BCK*/I2S_COMM_FORMAT_STAND_MSB = 0X02, /*!< I2S communication MSB alignment standard, data launch at first BCK*/I2S_COMM_FORMAT_STAND_PCM_SHORT = 0x04, /*!< PCM Short standard, also known as DSP mode. The period of synchronization signal (WS) is 1 bck cycle.*/I2S_COMM_FORMAT_STAND_PCM_LONG = 0x0C, /*!< PCM Long standard. The period of synchronization signal (WS) is channel_bit*bck cycles.*/I2S_COMM_FORMAT_STAND_MAX, /*!< standard max*///old definition will be removed in the future.I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/I2S_COMM_FORMAT_I2S_LSB __attribute__((deprecated)) = 0x02, /*!< I2S format LSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_LSB) correspond to `I2S_COMM_FORMAT_STAND_MSB`*/I2S_COMM_FORMAT_PCM __attribute__((deprecated)) = 0x04, /*!< I2S communication format PCM, correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/I2S_COMM_FORMAT_PCM_SHORT __attribute__((deprecated)) = 0x04, /*!< PCM Short, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_SHORT) correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/I2S_COMM_FORMAT_PCM_LONG __attribute__((deprecated)) = 0x08, /*!< PCM Long, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG) correspond to `I2S_COMM_FORMAT_STAND_PCM_LONG`*/
} i2s_comm_format_t;
知道了每个参数的含义以及知道它可以配置哪些参数,就可以调用i2s_driver_install这个函数了。
这里我们举一个安装I2S驱动的例子,就比较容易理解了。同时配置的时候,我们把它放在一个函数里面,起名为i2s_install( )。
// 安装I2S驱动void i2s_install(){// 配置I2S接收i2s_config_t i2s_config = {.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),.sample_rate = SAMPLE_RATE,.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),.intr_alloc_flags = 0,.dma_buf_count = 16,.dma_buf_len = bufferLen,.use_apll = false };if (ESP_OK != i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL)) {Serial.println("Install I2S driver failed");return;}
}
配置I2S引脚
I2S通信最重要的三个信号是位时钟BCK、字时钟WS、数据引脚SD,因此我们需要对其引脚进行配置,设置I2S引脚的函数是
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin),第一个参数传入I2S端口,填I2S_NUM_0或I2S_NUM_1, 第二个参数是结构体如下:
typedef struct {int mck_io_num; /*!< MCK in out pin. Note that ESP32 supports setting MCK on GPIO0/GPIO1/GPIO3 only*/int bck_io_num; /*!< BCK in out pin*/int ws_io_num; /*!< WS in out pin*/int data_out_num; /*!< DATA out pin*/int data_in_num; /*!< DATA in pin*/
} i2s_pin_config_t;
其中mck_io_num; bck_io_num,ws_io_num等都是整型变量,data_out_num如果我们没有用到就传入-1,在driver/i2s.h头文件定义了
#define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */
假设我们要配置的引脚位时钟BCK、字时钟WS、数据引脚SD分别是D13, D12, D14,同样把要配置的参数写入一个函数i2s_setpin()里面,配置I2S引脚示例如下:
// 配置I2S引脚
#define I2S_MIC_WS 12
#define I2S_MIC_SD 14
#define I2S_MIC_BCK 13void i2s_setpin(){i2s_pin_config_t pin_config = {};pin_config.bck_io_num = I2S_MIC_BCK;pin_config.ws_io_num = I2S_MIC_WS;pin_config.data_out_num = I2S_PIN_NO_CHANGE;pin_config.data_in_num = I2S_MIC_SD;if (ESP_OK != i2s_set_pin(I2S_PORT, &pin_config)) {Serial.println("I2S set pin failed");return;}}
安装完I2S驱动和配置好I2S引脚后,我们只要在setup()函数里面调用这两个函数就可以了。
void setup() {Serial.begin(115200);Serial.println("Setup I2S ...");delay(1000);i2s_install();i2s_setpin();delay(500);
}
读取I2S数据
上面只是对I2S进行了一下初始化,要通过INMP441读取i2s数据,我们只需要调用esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait);这个函数。因为前面在初始化I2S时的量化位数是16位,所以每个采样点的数据大小为2字节,我们将读取到的数据放入一个缓存区数组sBuffer,将数组长度bufferLen定义为64,确保每次从I2S接口读取时能获得足够的音频数据。 如果读取成功2s_read这个函数会返回一个ESP_OK,成功后就进入数据处理部分。这里我们将读取到的音频数据求均值然后可以用串口绘图仪观察它的数据波形,代码如下:
void loop() {size_t bytesIn = 0;esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);if (result == ESP_OK){int samples_read = bytesIn / 2;if (samples_read > 0) {float mean = 0;for (int i = 0; i < samples_read; ++i) {mean += (sBuffer[i]);}mean /= samples_read;Serial.println(mean);delay(50);}}
}
完整代码
#include "driver/i2s.h"
#define SAMPLE_RATE (44100)#define I2S_MIC_WS 12
#define I2S_MIC_SD 14
#define I2S_MIC_BCK 13
#define I2S_PORT I2S_NUM_0
#define bufferLen 64int16_t sBuffer[bufferLen];// 安装I2S驱动void i2s_install(){// 配置I2S接收i2s_config_t i2s_config = {.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),.sample_rate = SAMPLE_RATE,.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),.intr_alloc_flags = 0,.dma_buf_count = 16,.dma_buf_len = bufferLen,.use_apll = false };if (ESP_OK != i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL)) {Serial.println("Install I2S driver failed");return;}
}// 配置I2S引脚void i2s_setpin(){i2s_pin_config_t pin_config = {};pin_config.bck_io_num = I2S_MIC_BCK;pin_config.ws_io_num = I2S_MIC_WS;pin_config.data_out_num = I2S_PIN_NO_CHANGE;pin_config.data_in_num = I2S_MIC_SD;if (ESP_OK != i2s_set_pin(I2S_PORT, &pin_config)) {Serial.println("I2S set pin failed");return;}}void setup() {Serial.begin(115200);Serial.println("Setup I2S ...");delay(1000);i2s_install();i2s_setpin();i2s_start(I2S_PORT);delay(500);
}void loop() {size_t bytesIn = 0;esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);if (result == ESP_OK){int samples_read = bytesIn / 2;if (samples_read > 0) {float mean = 0;for (int i = 0; i < samples_read; ++i) {mean += (sBuffer[i]);}mean /= samples_read;Serial.println(mean);delay(50);}}}
接线图
写完代码后就可以开始接线了,接线图如下图所示:供电这里接3.3V,L/R接地。

实验效果
一开始接收到的是外界的声音,波形是杂乱无章的。后面用嘴吹气,波形会跟着吹气变化,不吹气波形是平缓不变的,后面大概吹了几次,可以看到波形变化,如下图:

总结
本篇文章介绍了通过ESP32的I2S通信实时读取INMP441麦克风模块的音频数据,并通过串口绘图仪显示音频数据波形。后面我们还会介绍使用INMP441采集音频并实时播放音频,感兴趣的可以先关注收藏一下!
相关文章:
ESP32 I2S音频总线学习笔记(二):I2S读取INMP441音频数据
简介 在这个系列的上一篇文章中,我们介绍了ESP32 I2S音频总线的相关知识,简要了解了什么是I2S总线、它的通信格式,以及相关的底层API函数。没有看过上篇文章的可以点击文章进行回顾: ESP32 I2S音频总线学习笔记(一&a…...
本地大模型编程实战(03)语义检索(2)
文章目录 准备按批次嵌入加载csv文件,分割文档并嵌入测试嵌入效果总结代码 上一篇文章: 本地大模型编程实战(02)语义检索(1) 详细介绍了如何使用 langchain 实现语义检索,为了演示方便,使用的是 langchain 提供的内存数据库。 在实…...
LabVIEW橡胶动态特性测试系统
本文介绍了一个利用LabVIEW软件和NI高速数据采集设备构建的橡胶动态特性测试系统。该系统实现了橡胶材料动态性能的精确测量,并通过虚拟仪器技术,提高了测试数据的处理效率和准确性。系统支持实时数据处理和多种信号的动态分析,适用于工业和科…...
SpringBoot开发(二)Spring Boot项目构建、Bootstrap基础知识
1. Spring Boot项目构建 1.1. 简介 基于官方网站https://start.spring.io进行项目的创建. 1.1.1. 简介 Spring Boot是基于Spring4框架开发的全新框架,设计目的是简化搭建及开发过程,并不是对Spring功能上的增强,而是提供了一种快速使用Spr…...
使用 Vue 3 的 watchEffect 和 watch 进行响应式监视
Vue 3 的 Composition API 引入了 <script setup> 语法,这是一种更简洁、更直观的方式来编写组件逻辑。结合 watchEffect 和 watch,我们可以轻松地监视响应式数据的变化。本文将介绍如何使用 <script setup> 语法结合 watchEffect 和 watch&…...
Vue.js 高级组件开发
Vue.js 高级组件开发:构建一个智能动态表单生成器 ——从可复用架构到性能优化的全链路实践 引言:为什么需要高级组件? 在现代前端开发中,组件不仅是UI的封装,更是业务逻辑的载体。一个“高级”Vue组件应当具备&…...
React应用深度优化与调试实战指南
一、渲染性能优化进阶 1.1 精细化渲染控制 typescript 复制 // components/HeavyComponent.tsx import React, { memo, useMemo } from react;interface Item {id: string;complexData: {// 复杂嵌套结构}; }const HeavyComponent memo(({ items }: { items: Item[] }) &g…...
Linux 内核学习(4) --- devfreq 动态调频框架
目录 Linux devfreq 简介核心数据结构devfreq_dev_profile 结构体devfreq_governor 结构体devfreq 结构体 工作流程devFreq framework 初始化governor 初始化devfreq Device 注册动态变频的实现device_unregister 流程 用户空间节点参考文章 Linux devfreq 简介 现在的 Soc 由…...
Spring Boot 无缝集成SpringAI的函数调用模块
这是一个 完整的 Spring AI 函数调用实例,涵盖从函数定义、注册到实际调用的全流程,以「天气查询」功能为例,结合代码详细说明: 1. 环境准备 1.1 添加依赖 <!-- Spring AI OpenAI --> <dependency><groupId>o…...
Ansible自动化运维实战--yaml的使用和配置(7/8)
文章目录 一、YAML 基本语法1.1. 缩进1.2. 注释1.3. 列表1.4. 字典 二、Ansible 中 YAML 的应用2.1. Ansible 剧本(Playbooks)2.2. 变量定义2.3. 角色(Roles)2.4. Inventory 文件2.5. 数据类型2.6. 引用变量 在 Ansible 里&#x…...
kamailio-5.8.4-centos9编译
安装必要的依赖包 在开始编译之前,你需要安装编译 Kamailio 所需的一些基础依赖包: dnf install -y make gcc gcc-c flex bison libxml2-devel openssl-devel sqlite-devel mysql-devel pcre-devel libcurl-devel下载并解压 Kamailio 源码包 假设你已经…...
单例模式 - 单例模式的实现与应用
引言 单例模式(Singleton Pattern)是设计模式中最简单且最常用的模式之一。它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式常用于需要全局唯一对象的场景,如配置管理、日志记录、线程池等。 本文将详细介…...
hadoop==docker desktop搭建hadoop
hdfs map readuce yarn https://medium.com/guillermovc/setting-up-hadoop-with-docker-and-using-mapreduce-framework-c1cd125d4f7b 清理资源 docker-compose down docker system prune -f...
zookeeper的介绍和简单使用
1 zookerper介绍 zookeeper是一个开源的分布式协调服务,由Apache软件基金会提供,主要用于解决分布式应用中的数据管理、状态同步和集群协调等问题。通过提供一个高性能、高可用的协调服务,帮助构建可靠的分布式系统。 Zookeeper的特点和功能…...
DiffuEraser: 一种基于扩散模型的视频修复技术
视频修复算法结合了基于流的像素传播与基于Transformer的生成方法,利用光流信息和相邻帧的信息来恢复纹理和对象,同时通过视觉Transformer完成被遮挡区域的修复。然而,这些方法在处理大范围遮挡时常常会遇到模糊和时序不一致的问题࿰…...
CentOS/Linux Python 2.7 离线安装 Requests 库解决离线安装问题。
root@mwcollector1 externalscripts]# cat /etc/os-release NAME=“Kylin Linux Advanced Server” VERSION=“V10 (Sword)” ID=“kylin” VERSION_ID=“V10” PRETTY_NAME=“Kylin Linux Advanced Server V10 (Sword)” ANSI_COLOR=“0;31” 这是我系统的版本,由于是公司内网…...
World of Warcraft [CLASSIC] Jewelcrafting Gemstone 2
World of Warcraft [CLASSIC] Jewelcrafting & Gemstone 2 珠宝加工与常用宝石列表(紫色史诗级): World of Warcraft [CLASSIC] Jewelcrafting & Gemstone_wlk宝石属性一览表-CSDN博客...
AI刷题-最小化团建熟悉程度和
目录 问题描述 输入格式 输出格式 解题思路: 状态表示 状态转移 动态规划数组 预处理 实现: 1.初始化: 2.动态规划部分: (1)对于已分组状态的,跳过: (2&…...
一文详解Filter类源码和应用
背景 在日常开发中,经常会有需要统一对请求做一些处理,常见的比如记录日志、权限安全控制、响应处理等。此时,ServletApi中的Filter类,就可以很方便的实现上述效果。 Filter类 是一个接口,属于 Java Servlet API 的一部…...
应用层协议 HTTP 讲解实战:从0实现HTTP 服务器
🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 HTTP 协议 🦋 认识 URL🦋 urlencode 和 urldecode 二:🔥 HTTP 协议请求与响应格式 🦋 HTTP 请求…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
如何通过git命令查看项目连接的仓库地址?
要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...
