当前位置: 首页 > news >正文

STM32 HAL学习笔记:GC1808(PCM1808)的使用以及使用I2S+DMA读取

前言

我的项目需要使用一个立体声ADC对运算放大器输出的模拟音频进行读取,并通过USB Audio Class传输到PC。

在群友的指导下,我选择了STM32F042K6T6作为主控,该型号支持硬件I2S,并支持USB Device(FS)。最重要的是,该型号在淘宝售价仅3元(还包邮)。

我选择的ADC型号位GC1808,这是一款低成本立体声音频模数转换器,最高支持96KHz 24bit,I2S接口输出,可通过引脚配置为主/从、飞利浦/MSB左对齐模式。该产品为TI生产的PCM1808的Pin-to-Pin兼容(山寨)芯片(数据手册的图都是从TI手册里截的),且在立创商城的ADC目录中按价格从低到高排名第一。

ADC芯片配置及输出验证

GC1808模块原理图如下图所示。手册要求大电容使用电解电容,我这里为了省空间改成了MLCC,总之能用。三个功能选择引脚接出来,用一坨锡就能修改。

Snipaste_2025-09-15_18-25-41

我计划将音频采样率配置为48KHz,即:

\[f_S = 48KHz \]

选择$$f_{ICK} = 512 \times f_S = 24.576MHz$$

另选择工作在主机模式、数据格式为左对齐、24bit,故将引脚配置为:

引脚 电平
FMT (Pin 12)
MD1 (Pin 11)
MD0 (Pin 10)

由数据手册可知,每一帧由2个声道共32个位组成,故可计算得到BCK(位时钟)的频率为:

\[f_{BCK}=48KHz \times 64 = 3.072MHz \]

LRCK(左右时钟)的频率与输出音频采样率相同,即:

\[f_{LRCK}=f_S=48KHz \]

连接示波器,可以看到测试结果与理论值一致,如下图所示。其中,1通道(黄色)为BCK波形,2通道(青色)为LRCK波形。由于学校的包浆示波器探头找不到接地弹簧,我只能使用接地夹子测量,测量波形噪声较多、质量很差。
DS2_20250914145633

更换探头位置,1通道测量LRCK波形,2通道测量DOUT(数据输出)波形,结果如下图所示。可以看到,ADC正在发送两个声道的数据,与手册标注的格式一致。
DS2_20250914145908

STM32CubeMX配置与接线

为产生ADC所需的时钟信号,我使用了一个24.576MHz的无源晶振,并将整个单片机运行在24.576MHz。这款单片机似乎没有为I2S单独提供时钟的PLL,无法使用I2S的MCO(主时钟输出)功能输出ADC芯片所需的系统时钟,故配置时钟树将HCLK通过MCO引脚输出,连接到ADC的SCKI。时钟树如下图所示。

Snipaste_2025-09-15_18-00-40

在左侧选择I2S,页面上方模式设置为半双工从机模式,传输模式修改为从机接收,通信标准为MSB优先左对齐,数据和帧格式为在32位帧上传输的24位数据,音频频率为48KHz。可以看到,得益于专门选择的晶体频率,频率误差为0。如下图所示。

Snipaste_2025-09-15_18-37-22

切换到DMA设置标签页。点击加号添加一个DMA请求,STM32CubeMX自动帮我们配置了一些信息。我们需要将DMA设置请求中的模式切换为循环。根据参考手册,I2S接收的寄存器只有16位,32位的一帧需要DMA分两次搬运,故这里的数据宽度都选择半字(16位)。设置如下图所示。

Snipaste_2025-09-15_18-38-12

STM32CubeMX已经帮我们分配了各个引脚,从机模式的I2S占用了3个引脚,分别为WS(字选择,输入)、CK(时钟,输入)、SD(串行数据,输入)。根据我们上面的设置,接线方式如下。

STM32 GC1808
WS LRCK
CK BCK
SD DOUT
MCO SCKI

代码

整体代码如下所示。

# main.c
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
/* USER CODE END Includes *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define I2S_HALF_DMA_CACHE_SAMPLES 32 // 可按需求调整: 表示半次DMA缓冲中每个声道的采样数
/* USER CODE END PD *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */// 原始DMA接收缓冲,I2S_HALF_DMA_CACHE_SAMPLES * 2声道 * 2个uint16_t * 2(前后分开处理)
static uint16_t i2s_rx_dma_buf[8 * I2S_HALF_DMA_CACHE_SAMPLES];// 分离后的左右声道数据 (存放在 32bit 中, 低 24bit 有效),前后分开处理
static int32_t i2s_left[I2S_HALF_DMA_CACHE_SAMPLES * 2];
static int32_t i2s_right[I2S_HALF_DMA_CACHE_SAMPLES * 2];// 统计静音采样数,调试用
static uint32_t leftzero_cnt = 0;
static uint32_t rightzero_cnt = 0;
/* USER CODE END PV *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */// 合并并符号扩展 24bit 数据
static void ProcessI2SBlock(const uint16_t *src_words, uint32_t samples, uint32_t offset)
{for (uint32_t i = offset; i < samples + offset; i++){uint32_t left_word = (uint32_t)src_words[i * 4] << 16 | src_words[i * 4 + 1];uint32_t right_word = (uint32_t)src_words[i * 4 + 2] << 16 | src_words[i * 4 + 3];// 取高24bitint32_t l = (int32_t)(left_word >> 8);int32_t r = (int32_t)(right_word >> 8);// 符号扩展 24bit -> 32bit (若第23位为1则为负数,需填充高位)if (l & 0x00800000u)l |= 0xFF000000u;if (r & 0x00800000u)r |= 0xFF000000u;i2s_left[i] = l;i2s_right[i] = r;// 简单统计静音采样数,调试用if (abs(l) <= 500)leftzero_cnt++;if (abs(r) <= 500)rightzero_cnt++;}
}void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{if (hi2s->Instance == SPI1){ProcessI2SBlock(i2s_rx_dma_buf, I2S_HALF_DMA_CACHE_SAMPLES, 0);}
}void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{if (hi2s->Instance == SPI1){ProcessI2SBlock(i2s_rx_dma_buf, I2S_HALF_DMA_CACHE_SAMPLES, I2S_HALF_DMA_CACHE_SAMPLES);}
}
/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_I2S1_Init();/* USER CODE BEGIN 2 */// 启动 I2S DMA 接收: size为 2 * I2S_HALF_DMA_CACHE_SAMPLES 个 32bit 数据if (HAL_I2S_Receive_DMA(&hi2s1, i2s_rx_dma_buf, 4 * I2S_HALF_DMA_CACHE_SAMPLES) != HAL_OK){Error_Handler();}my_printf("I2S DMA started. FrameSamples=%d\r\n", I2S_HALF_DMA_CACHE_SAMPLES);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */// 每秒打印一次统计信息static uint32_t tick_last = 0;if (HAL_GetTick() - tick_last > 1000){tick_last = HAL_GetTick();my_printf("leftzero=%lu rightzero=%lu\r\n", leftzero_cnt, rightzero_cnt);for (int i = 0; i < 2 * I2S_HALF_DMA_CACHE_SAMPLES; i++){my_printf("%ld %ld\r\n", i2s_left[i], i2s_right[i]);}leftzero_cnt = 0;rightzero_cnt = 0;}}/* USER CODE END 3 */
}

STM32CubeMX已经帮我们完成了大部分代码,我们只需要完成几个弱定义的函数就可以了。

需要注意的是,在HAL库的用户手册UM1785中,对HAL_I2S_Receive_DMA的描述如下:

When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
configuration phase, the Size parameter means the number of 16-bit data length in the
transaction and when a 24-bit data frame or a 32-bit data frame is selected the Size
parameter means the number of 16-bit data length.

但这个描述是错误的。在STM32Cube_FW_F0_V1.11.5\Drivers\STM32F0xx_HAL_Driver\目录下的chm文档中,对HAL_I2S_Receive_DMA的描述如下:

When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S configuration phase, the Size parameter means the number of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data frame is selected the Size parameter means the number of 24-bit or 32-bit data length.

我也让了Copilot对HAL库的.c文件作了解读,看起来HAL库会根据配置自动处理,这里只需要填写24或32比特数据的长度即可。

此外,ST的文档中似乎只字未提左右声道的问题。根据ADC的数据手册,在I2S协议中,左声道数据总是先于右声道进行传输。为了验证读取的i2s_rx_dma_buf中的规律,我加了几个函数进行调试。

运行后,程序可以正常打印两个声道的int32数据,左列位左声道,右列为右声道,如下图所示。可以看出,两个声道的数值都很接近0。

Snipaste_2025-09-15_19-39-40

用手指触摸13引脚对应的电容,数据变化如下。可以看到,左列数据发生了较大波动,不再接近0。

Snipaste_2025-09-15_19-44-03

经过多次复位后重复实验,我们可以确认,在DMA读取的数组中,左声道数据同样先于右声道数据。

相关文章:

STM32 HAL学习笔记:GC1808(PCM1808)的使用以及使用I2S+DMA读取

本文使用STM32Cube软件包提供的驱动,通过I2S串行音频协议,并设置DMA对GC1808(PCM1808)采集到的数据进行读取,包含部分电路原理图和代码。前言 我的项目需要使用一个立体声ADC对运算放大器输出的模拟音频进行读取,并通过USB Audio Class传输到PC。 在群友的指导下,我选择…...

完整教程:【视频系统】技术汇编

完整教程:【视频系统】技术汇编pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; fon…...

MSTP 单域

...

阿里云百炼平台使用避坑记录 - 详解

阿里云百炼平台使用避坑记录 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; …...

springboot的run

springboot在哪里写自己的代码。@SpringBootApplication public class FooApplication {public static void main(String[] args) {SpringApplication.run(FooApplication.class, args);} }上面是springboot的入口代码,主文件除了这个类没别的了。 网上有很多分析,springboot…...

ubuntu服务器docker日期安装mysql

# 1. 拉取 MySQL 8 官方镜像 docker pull mysql:8.0# 2. 创建数据和配置目录(实现数据持久化) mkdir -p /opt/mysql/{data,conf,logs} chmod -R 777 /opt/mysql # 赋予权限,避免容器内权限问题# 3. 创建自定义配置文件(可选,优化 MySQL 性能) cat > /opt/mysql/conf/m…...

springboot的启动流程

一文彻底弄懂Spring Boot的启动过程 一,Spring Boot启动过程 1. 启动入口 Spring Boot 应用的启动入口通常是一个包含 @SpringBootApplication 注解的主类,并调用 SpringApplication.run() 方法。@SpringBootApplication 是一个复合注解,包含了 @Configuration、@EnableAut…...

萤火虫旅行网和萤火虫文旅的关系是什么

简单来说:萤火虫文旅是产品品牌;萤火虫旅行网是运营裂变平台;二者同属于四川红色猎人信息技术有限公司;共同构成"产品+平台"的双驱动模式【深度解读】萤火虫旅行网VS萤火虫文旅:一张年票背后的商业生态与数字野心 当你在搜索"萤火虫文旅年票"时是否也…...

「微积分 A1」基础知识(连载中)

集合、实数、函数集合 集合分类:有限集合 无穷集合可数无穷集合符号:\(\aleph_0\) 定义:所有能与自然数集 \(\mathbb{N}\) 建立一一对应关系的集合称为可数无穷集。不可数无穷集合符号:\(\aleph_x\) (基数更大的无穷)勒贝格测度: 勒贝格测度的目标是给实数轴上的子集(尤…...

第2周-预习作业

Java 相关问题解答 1. 方法相关问题 1.1 changeStr与changeArr的功能各是什么?changeStr功能:该方法接收一个String参数x,并尝试将x赋值为"xyz"。但由于String是不可变类,且Java采用值传递,所以该方法不会改变原始字符串的值。它只会修改方法内部局部变量x的引用…...

P12546 [UOI 2025] Convex Array

\(b_{i-1}+b_{i+1}\ge b_i\) 等价 \(b_{i+1}-b_i\ge b_i-b_{i-1}\) 即 \(b\) 数组差分数组单调不降。 若出现次数为 2,则必定是最小值在排列中左右各有 1 个。(不能相同元素放一起否则差分为 0)。 若存在元素出现次数大于 2 且不为最小值,则必定无解(多余的元素无论放在哪…...

一个新词:测试可靠性

提高测试可靠性是为了让我们的测试值得信任。 以前都在讲软件的健壮性、可靠性,好像都在对开发质量提出要求。今天,为了证明自己的工作是值得信任的,提高测试的可靠性势在必行。 提高测试的可靠性,传统做法有哪些呢?测试用例评审、交叉测试、测试复盘总结、线上问题跟踪学…...

CF827F Dirty Arkadys Kitchen

先把 \((u,v,l,r)\) 变成 \((u,v,l,r-1)\)。 不能停留,所以每个时刻有两种选择在某一条边上用 2 个时刻走一个来回浪费时间等某一条需要的边开启。走到下一个点。第 1 种选择启发若时刻 \(t\) 能到 \(u\),那么若存在边 \((u,v,l,r)\),那么所有时刻 \(T\in[l,r],T\equiv t\pm…...

P2839 [国家集训队] middle

经典的二分答案 \(mid\),\(\ge mid\) 的数权值为 1,\(<mid\) 权值为 -1,答案合法当且仅当存在区间 \([l,r]\) 使得权值和 \(\ge 0\),做前缀和 \(s\),即等价于 \(s_r-s_{l-1}\ge 0\to s_r\ge s_{l-1}\)。 对于询问 \((a,b,c,d)\) 只需要 \(\max_{i=c}^ds_i\ge \min_{i=a…...

wuti

...

友链

...

向量化存储与知识图谱的比较

以下内容来自AI对话生成简单来说,它们的核心区别是:向量化存储追求“语义上的相似”,而知识图谱追求“逻辑上的关联”。 我们可以用一个经典的例子来区分:问题:“苹果公司的创始人史蒂夫乔布斯最喜欢吃什么水果?” 向量化存储:可能会找到一段描述“史蒂夫乔布斯饮食习惯…...

力扣17题 电话号码的字母组合

归类:回溯算法 回溯三部曲: 1.确定回溯函数参数 首先需要一个字符串s来收集叶子节点的结果,然后用一个字符串数组result来保存起来,这两个变量依然定义为全局。 参数指定是有题目中给的string digits,然后还有一个参数就是int型的index。 index是用来记录遍历第几个数字了…...

萤火虫文旅年票、为什么能做到低至4.2元一张景区门票、还能高达50%的毛利润?

【商业揭秘萤火虫文旅年票】低至4.2元/张景区门票,毛利润竟超50%!萤火虫文旅年票的盈利模式为何让行业震惊?【商业揭秘萤火虫文旅年票】低至4.2元/张景区门票,毛利润竟超50%!萤火虫文旅年票的盈利模式为何让行业震惊? 当看到"4.2元一张景区门票"这个价格时你的…...

ubuntu服务器docker容器安装nacos

docker pull nacos/nacos-server:latest TOKEN=$(echo -n "nacos-token-$(date +%s)" | base64) # 随机令牌 IDENTITY_KEY="nacos-identity-key" # 自定义身份键 IDENTITY_VALUE="nacos-identity-value" # 自定…...

PWN手的成长之路-02-r3m4ke

启动环境,并下载附件。远程连接之后,输入了一些命令,发现无反应。开始分析附件。 先用checksec查看一下文件的安全属性。 文件是64位的且只开启了NX防御(这个保护开启就是意味着栈中数据没有执行权限,如此一来, 当攻击者在堆栈上部署自己的 shellcode 并利用缓冲区溢出等手…...

SAP 采购订单税率及含税金额取数

税码 联查A003及KONP "采购税码的税率SELECT a~mwskz, "税码k~kbetr "税率INTO TABLE @DATA(t_sl)FROM a003 AS a INNER JOIN konp AS kON a~knumh = k~knumhWHERE a~mwskz IN ( J0 , J1 , J2 , J3 , J4 , J5 , J6 )AND a~aland = CN.SORT t_sl BY mwskz.....…...

深入解析:Linux x86 stability和coredump

深入解析:Linux x86 stability和coredumppre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !impor…...

9.15更新linux命令

...

Jenkins 容器和 Kubernetes Agent

Jenkins 容器和 Kubernetes Agent安装 Jenkins [root@control-plane jenkins]# cat compose.yaml services:jenkins:# Jenkins 2.516.2image: jenkins/jenkins:ltsports:- "8080:8080"# https://github.com/jenkinsci/docker/blob/master/README.md#connecting-agen…...

LGP7916 [CSP-S 2021] 交通规划 学习笔记

LGP7916 [CSP-S 2021] 交通规划 学习笔记 Luogu Link 前言仔细读了十遍题面,硬是一个字都没和交通规划扯上关系,很有可能是出题人编了一个故事,发现编不下去了。——\(\texttt{OMG-WC}\)。题意简述 有一个 \(n\times m\) 个点的网格图。对于这个网格图的最外侧,有些网格线会…...

详细介绍:【Kubernetes】常见面试题汇总(十四)

详细介绍:【Kubernetes】常见面试题汇总(十四)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace…...

萤火虫文旅年票、为何能成为撬动万亿文旅市场的利器

萤火虫文旅年票隶属于四川红色猎人信息技术有限公司、成立于2020年7月24日、致力于为B端企业用户和C端个人用户提供超高性价比的景区门票.用互联网OTA技术整合了全国7000多家景点、用自助餐模式搭建了四款产品:省级版景区门票、大区版景区门票、全国版景区门票、以及企业定制版…...

Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用

Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用牵牛老人 已于 2025-07-25 09:24:54 修改 阅读量645 收藏 10 点赞数 11 文章链接:https://blog.csdn.net/qianniulaoren/article/details/149138758一:USB摄像头开发基础与框架 1.1 QtMultimedia的优势与局限​ 跨平台兼…...

详细介绍:C++(静态函数)

详细介绍:C++(静态函数)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-siz…...

2025.9.15日软件工程学习日志

HBase科技成果管理系统设计与实现 今日设计一个基于HBase的科技成果信息填报系统。 系统分析与设计思路 前端需要实现科技成果信息填报表单,包含多种输入类型和验证 后端使用HBase作为数据库存储数据 需要实现数据的增删改查功能 成果编号需要按规则自动生成 HBase表设计: 表…...

RocketMQ快速实战及核心概念

RocketMQ学习笔记 一、MQ简介 MQ定义MQ:Message Queue,消息队列Message:消息,不同进程之间传递的数据Queue:队列,具有FIFO(先进先出)特性,用于缓存数据广义上,只要能实现消息跨进程传输及队列数据缓存,都可称为消息队列MQ的作用异步例子:快递员发快递,先放到菜鸟驿站…...

【南方科技大学主办】第五届电气工程与机电一体化手艺国际学术会议(ICEEMT 2025)

【南方科技大学主办】第五届电气工程与机电一体化手艺国际学术会议(ICEEMT 2025)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &qu…...

为什么不建议在 Docker 中跑 MySQL?

前言 今天我们来聊聊一个很有趣的话题:为什么我不建议在Docker中运行MySQL数据库? 有些小伙伴在工作中可能为了部署方便,习惯将所有组件都容器化,但数据库真的适合放在容器里吗? 今天就专门跟大家一起聊聊这个话题,希望对你会有所帮助。 一、容器化与数据库:天生的矛盾?…...

reLeetCode 热题 100-1 指针283. 移动零 - MKT

reLeetCode 热题 100-1 指针283. 移动零 class Solution { public:void moveZeroes(vector<int>& nums) {// int cout_=0;// for(int i =0; i<nums.size();i++){// if(nums[i]==0){// cout_++;// }// }// std::cout<< " 0s all …...

解决c# DocX生成的word文档wps打开排版外边距错乱微软office正常问题

public void insertBreak(DocX document, String filename) { DocX tempDocx = DocX.Create(filename); setPageMargin(tempDocx); document.InsertDocument(tempDocx);document.InsertSectionPageBreak(true); }改为public vo…...

The 2025 ICPC Asia East Continent Online Contest (II)

The 2025 ICPC Asia East Continent Online Contest (II)比赛链接 Review 这场非常有参与感哈哈,因为我签到题 C 贪心写了两小时,中间下机若干次让队友过题,写完已经完全不知道队友进度是啥了,后续就当小黄鸭被带飞了哈哈。 Solution C. Jiaxun! 那我确实需要 jiaxun 额额贪…...

工厂方法模式(Factory Method) - 指南

工厂方法模式(Factory Method) - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !importa…...

拾忆录

████,也即言多██,就是少点██,不容易发生██——来自于多种████的通理 择一███,遇一人██——收集自███,████ 知行合一心学理论——王阳明...

从零搭建RAG应用:跳过LangChain,掌握文本分块、向量检索、指代消解等核心技术实现

RAG(检索增强生成)本质上就是给AI模型外挂一个知识库。平常用ChatGPT只能基于训练数据回答问题,但RAG可以让它查阅你的专有文档——不管是内部报告、技术文档还是业务资料,都能成为AI的参考资源。 很多人第一反应是用LangChain或LlamaIndex这些现成框架,确实能快速搭起来。…...

python高阶技巧

闭包:在函数嵌套前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数叫做闭包 简单闭包: def outer(logo): def inner(msg): print(f"<{logo}>{msg}>{logo}") return inner fn1=outer("黑马程…...

机器视觉之图像处理篇 - 指南

机器视觉之图像处理篇 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-s…...

尝试hikari和jdbctemplate

试着基于jdbctemplate包装一个MysqlHelper类。连接池采用springboot默认的hikari。jdbctemplate提供基本的防注入,它的写法比jdbc好看,jdbc还需要putint,putstr。提供的另一个功能是结果集的转换。写完,测试代码的面貌如下:var sqlhp = new SqlHelper();sqlhp.configAddress…...

配置Nginx根据IP地址进行流量限制以及返回JSON格式数据

要在Nginx中根据IP地址进行流量限制并返回JSON格式数据,你需要结合Nginx的 ngx_http_limit_req_module模块和一些配置技巧。这个模块允许你基于定义的键值,比如IP地址,限制请求的速率。不过在进入细节前,别忘了备份你的Nginx配置文件 划重点:配置透视战斗护甲 (limit_req_…...

回归

最近因为████导致██发生████,长期的██也不是办法,我决定以███████发文。 我的很多比如███,███都发生了██,所以██的██████视█。 重新██...

CSS纯文本渐变动效

创建一个令人印象深刻的CSS文本渐变动效就像是在文字上施展魔法。想象你的文字就像是一幅幻灯片,色彩在背后流转,让每个字母都像是被彩虹绘制过一样。 为了让这种魔法发生,你需要进入CSS的巫术领地。我们将把渐变动效的制作分解为简单步骤,这样即使你不是CSS的大师,也能轻…...

泛微流程共享

第一步: 第二步:打开合同审批数据,点击右键,选择共享。 第三步:共享权限的查看,可见Giada没有查看权限。 第四步:添加权限,依次进入下面的选项。...

MySQL报错:未知系统变量tx_isolation及隔离级别查询

MySQL在其各个版本中进行了诸多变更和优化,包括系统变量、参数命名、功能等方面的调整。在这个情况中,遇到“未知系统变量tx_isolation”这个错误是因为在MySQL 8.0及以后的版本中,系统变量 tx_isolation已经被重命名为 transaction_isolation。 如果你像老朋友一样寻找 tx_…...

Redssion

1.使用 // 设置锁定资源名称 RLock disLock = redissonClient.getLock("DISLOCK"); //尝试获取分布式锁 boolean isLock= disLock.tryLock(500, 15000, TimeUnit.MILLISECONDS); if (isLock) {try {//TODO if get lock success, do something;Thread.sleep(15000);} …...

if __name__ == __main__:

if __name__ == "__main__": 是 Python 中的一个标准代码块,用于检查一个脚本是否是直接运行的。 工作原理 当一个 Python 脚本被解释器执行时,它会自动定义一些特殊变量。其中一个就是 __name__。如果脚本是直接运行的,Python 会将 __name__ 变量的值设置为 &quo…...