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

stm32利用LED配置基础寄存器+体验滴答定时器+hal库环境配置

P1 LED控制与流水灯效果实现

概述

大家好,今天我们来学习一下如何在STM32上控制LED灯,并且实现一个流水灯的效果。这不仅是一个基础的实践,也是嵌入式开发中非常常见的需求。

LED控制

1. LED初始化

首先,我们需要对LED灯对应的GPIO端口进行初始化。这个过程包括三个步骤:

  1. 开启GPIOA的时钟信号。
  2. 配置具体的IO端口的工作模式。
  3. 决定输出高电平还是低电平。
void LED_Init(void) {// 开启GPIOA的时钟信号RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;// 配置PA8为通用推挽输出模式GPIOA->CRH |= GPIO_CRH_MODE8;GPIOA->CRH &= ~GPIO_CRH_CNF8;// 设置PA8的初始状态为熄灭(输出低电平)LED_Off(LED3);
}

2. LED点亮与熄灭

接下来,我们实现了LED灯的点亮和熄灭函数。这些函数通过操作GPIOA的ODR寄存器来控制LED灯的状态。

// 点亮指定的LED灯
void LED_On(uint16_t led) {GPIOA->ODR &= ~led;
}// 熄灭指定的LED灯
void LED_Off(uint16_t led) {GPIOA->ODR |= led;
}

3. LED状态反转

我们还实现了一个LED状态反转的函数,通过异或操作来实现LED灯状态的快速切换。

// 反转指定LED灯的状态
void LED_Toggle(uint16_t led) {GPIOA->ODR ^= led;
}

流水灯效果实现

在主函数中,我们通过循环调用LED的点亮和熄灭函数,实现了流水灯效果。

int main(void) {LED_Init(); // 初始化LEDwhile (1) {LED_On(LED1);Delay_ms(500); // 延时500msLED_Off(LED1);LED_On(LED2);Delay_ms(500); // 延时500msLED_Off(LED2);LED_On(LED3);Delay_ms(500); // 延时500msLED_Off(LED3);}
}

生活中的比喻

想象一下,你在家里控制节日的彩灯串。每个LED灯就像一个小灯泡,而STM32就像一个智能开关,通过编写程序,你可以控制哪些灯泡亮起,哪些熄灭,以及它们亮起的顺序和时间。这样,你就可以创建出各种动态的灯光效果,就像编程控制STM32实现流水灯效果一样。

练习题及答案

题目: 如何在STM32上实现一个呼吸灯效果?

答案: 呼吸灯效果可以通过PWM(脉冲宽度调制)来实现。你需要配置一个定时器产生PWM波,然后通过改变PWM的占空比来控制LED的亮度,从而实现呼吸灯的效果。

好的,根据您提供的字幕内容,我将模仿尚硅谷老师的风格,将课程内容整理成Markdown格式的博客,并包含练习题及答案。以下是博客内容:


P2 RCC时钟使能的重要性

概述

大家好,今天我们来聊聊STM32中的RCC时钟使能。很多同学可能会疑惑,为什么在STM32中,我们需要先使能时钟才能配置外设寄存器。这个问题其实涉及到STM32的功耗管理和外设初始化。

RCC时钟使能的必要性

1. 省电设计

首先,我们来想想,为什么STM32要有一个专门的RCC模块来管理时钟信号。其实,这个设计的主要目的是为了省电。时钟信号是不停地在拉高和拉低,即使电路处于高阻态或断路状态,也会有微弱的电流消耗。因此,RCC模块允许我们只对需要使用的外设提供时钟信号,从而节省电量。

2. 时钟使能的顺序

在配置任何外设之前,我们必须先使能该外设的时钟信号。如果我们先配置外设寄存器,然后再使能时钟,会发生什么呢?答案是:外设可能不会按预期工作。这是因为,外设的寄存器需要时钟信号来更新其状态,如果没有时钟信号,寄存器的配置就不会生效。

3. 实践中的测试

我们可以通过一个简单的测试来验证这一点。如果我们将时钟使能放在GPIO配置之后,然后尝试点亮一个LED,我们会发现LED不会亮起。这就是因为我们没有在正确的顺序下使能时钟信号。

4. 为什么时钟信号是必须的

在数字电路中,存储电路(如触发器和寄存器)需要时钟信号来同步数据的存储和更新。如果没有时钟信号,数据就无法正确地写入寄存器。这就是为什么我们在操作外设寄存器之前,必须先使能时钟信号。

实践题及答案

题目: 如何确保STM32的外设正确初始化?

答案: 在配置任何外设寄存器之前,确保先使能该外设的时钟信号。例如,如果你要初始化GPIOA,你应该先使能GPIOA的时钟信号,然后再配置GPIOA的模式和输出。

// 使能GPIOA的时钟信号
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;// 配置GPIOA的模式和输出
GPIOA->CRL |= GPIO_CRL_MODE0;
GPIOA->CRL &= ~GPIO_CRL_CNF0;

好的,根据您提供的字幕内容,我将模仿尚硅谷老师的风格,将课程内容整理成Markdown格式的博客,并包含练习题及答案。以下是博客内容:


P3 关闭时钟信号节能的原理

概述

大家好,今天我们来聊聊为什么在STM32中关闭时钟信号可以节省电量。这个问题其实涉及到了我们对MOS管和时钟信号的理解。

时钟信号与功耗

1. MOS管的工作原理

首先,我们来回顾一下MOS管的工作原理。MOS管,也就是金属氧化物半导体场效应管,它有一个特点,就是通过改变栅极(山极)的电压来控制源极和漏极之间的导通状态。

2. 时钟信号的动态过程

时钟信号是周期性变化的,它不停地在高电平和低电平之间切换。这个过程中,即使是MOS管没有工作,也会因为时钟信号的切换而产生电荷的消耗。比如,当VCC给MOS管的栅极充电时,会产生电荷积累;而当信号变为低电平时,这些电荷又被迅速带走。这个过程即使没有电流通过,也会消耗电量。

3. RCC的作用

在STM32中,RCC(Reset and Clock Control)模块负责管理片上外设的时钟信号。当我们不需要使用某个外设时,可以通过RCC关闭该外设的时钟信号,从而切断对其内部MOS管的充电和放电,达到节省电量的目的。

4. 节能原理

关闭时钟信号可以节省电能的原理其实很简单:减少了MOS管的充电和放电次数,也就减少了电量的消耗。这对于电池供电的设备来说尤其重要,因为它们需要尽可能地延长电池寿命。

实践题及答案

题目: 如何在STM32中通过关闭时钟信号来节省电量?

答案: 在STM32中,你可以通过RCC模块来管理外设的时钟信号。当你确定某个外设暂时不需要使用时,可以通过RCC关闭该外设的时钟信号,从而节省电量。

// 假设我们要关闭GPIOA的时钟信号
RCC->APB2ENR &= ~RCC_APB2ENR_IOPAEN;

好的,根据您提供的字幕内容,我将模仿尚硅谷老师的风格,将课程内容整理成Markdown格式的博客,并包含练习题及答案。以下是博客内容:


P4 Keil Assistant插件的安装与配置

概述

大家好,今天我们来聊聊如何在VSCode中安装和配置Keil Assistant插件。这个插件虽然已经停止维护,但对于我们学习和开发STM32项目来说,还是非常有用的。

Keil Assistant插件安装

1. 插件选择

如果你有能力根据教程或者网上的文章去配置EIDE,那当然是最好的。但如果你想要一个简单快捷的解决方案,Keil Assistant插件是一个不错的选择。

2. 安装步骤

安装Keil Assistant插件非常简单,你只需要在VSCode中搜索qassistant,然后选择下载量最大的那个版本进行安装。

步骤:
1. 打开VSCode。
2. 转到插件市场,搜索`qassistant`。
3. 选择下载量最大的版本,点击安装。

3. 插件配置

安装完成后,我们需要进行一些配置,主要是指定Keil MDK的安装路径。

配置步骤:
1. 打开VSCode的设置(可以通过点击左下角的齿轮图标或使用快捷键`Ctrl + ,`)。
2. 搜索`qassistant`。
3. 找到Keil MDK的配置项,指定Keil MDK的安装路径。

4. 路径指定

在指定路径时,注意不要复制前面的字母C,因为Windows有一个老bug,会导致路径中的某些字符出现问题。

如何正确复制路径:
1. 右键Keil MDK的快捷方式,选择“属性”。
2. 复制“目标”中的路径,但不要复制字母`C`。
3. 在VSCode的插件配置中,粘贴路径,并在前面补上`C:`。

实践题及答案

题目: 如何在VSCode中安装Keil Assistant插件?

答案:

  1. 打开VSCode。
  2. 转到插件市场,搜索qassistant
  3. 选择下载量最大的版本,点击安装。
  4. 打开VSCode的设置,搜索qassistant
  5. 找到Keil MDK的配置项,指定Keil MDK的安装路径。
这样,你就完成了Keil Assistant插件的安装和配置,可以开始使用它来开发STM32项目了。

P5 使用VSCode编译和烧录代码

概述

大家好,今天我们来学习如何使用VSCode来编译和烧录STM32的代码。这个技能对于嵌入式开发来说非常重要,也是我们日常开发中经常用到的操作。

安装Keil Assistant插件

首先,我们需要确保VSCode中安装了Keil Assistant插件。这个插件可以帮助我们直接在VSCode中进行编译和烧录操作。

插件安装步骤

  1. 打开VSCode。
  2. 转到插件市场,搜索Keil Assistant
  3. 选择下载量最大的版本,点击安装。

插件配置

安装完成后,我们需要进行一些配置,主要是指定Keil MDK的安装路径。

  1. 打开VSCode的设置(可以通过点击左下角的齿轮图标或使用快捷键Ctrl + ,)。
  2. 搜索Keil Assistant
  3. 找到Keil MDK的配置项,指定Keil MDK的安装路径。

使用VSCode编译和烧录

打开项目

  1. 在VSCode中打开你的STM32项目目录。
  2. 注意不要打开错误的项目,确保打开的是Keil项目。

编译项目

  1. 在VSCode中,点击项目右侧的Build按钮进行编译。
  2. 编译结果会在底部窗口显示,如果有错误或警告,根据提示进行修正。

烧录项目

  1. 编译完成后,点击Download按钮进行烧录。
  2. 烧录成功后,可以通过摄像头查看LED灯的状态,验证烧录是否成功。

常见问题

编码问题

如果你在VSCode中打开项目时遇到编码乱码的问题,可以在VSCode中重新以正确的编码方式打开文件。

编译警告

有时候编译时会出现警告,比如文件最后一行没有空行结束。这通常是历史遗留问题,不影响代码运行,可以忽略。

实践题及答案

题目: 如何在VSCode中编译和烧录STM32项目?

答案:

  1. 确保VSCode中安装了Keil Assistant插件。
  2. 打开STM32项目目录。
  3. 点击Build按钮进行编译。
  4. 编译完成后,点击Download按钮进行烧录。
这样,你就可以在VSCode中完成STM32项目的编译和烧录了。

P6 如何在没有右键菜单的情况下打开Keil项目

概述

大家好,今天我们来解决一个实际问题,就是在没有右键菜单的情况下,如何在VSCode中打开Keil项目。这个问题可能因为VSCode安装时的配置不同而出现。

缺少右键菜单的问题

1. 问题原因

有些同学可能在安装VSCode时没有勾选“通过Code打开”的选项,导致在文件资源管理器中右键点击文件时,没有“通过Code打开”的选项。

2. 解决方案

不要去网上搜索修改注册表的方法,因为这可能会导致更多的问题。注册表是Windows的一个重要组成部分,错误的修改可能会导致系统不稳定。

3. 重新安装VSCode

最简单的解决方案是卸载VSCode,然后重新安装,并在安装过程中勾选“通过Code打开”的选项。

4. 手动打开项目

如果你不想重新安装VSCode,也可以直接在VSCode中手动打开项目。

步骤如下:
  1. 打开VSCode。
  2. 点击左上角的“Explorer”。
  3. 在打开的界面中,点击右侧的“+”号,选择“打开文件夹”。
  4. 导航到你的Keil项目所在的目录,选择项目文件,点击“打开”。

5. 切换工作空间

打开项目后,VSCode会提示你是否要将工作空间切换到项目所在的目录,确保选择“是”,这样你就可以在VSCode中正常编辑和编译项目了。

实践题及答案

题目: 如果在文件资源管理器中没有“通过Code打开”的选项,如何手动在VSCode中打开Keil项目?

答案:

  1. 打开VSCode。
  2. 点击左上角的“Explorer”。
  3. 点击“+”号,选择“打开文件夹”。
  4. 导航到Keil项目目录,选择项目文件,点击“打开”。
  5. 根据提示,切换工作空间到项目目录。

markdown

通过以上步骤,你就可以在没有右键菜单的情况下,手动在VSCode中打开Keil项目了。

P7 如何从旧项目创建新项目

概述

大家好,今天我们来学习一下如何从旧项目创建新项目。这是一个很常见的需求,特别是在我们做嵌入式开发的时候,很多项目都有相似的基础结构。

从旧项目创建新项目

1. 复制旧项目

首先,我们可以复制一个已经存在的项目,这样可以节省我们配置环境的时间。

markdown

步骤:
1. 使用`Ctrl+C`复制旧项目的文件夹。
2. 使用`Ctrl+V`粘贴到新的位置,创建一个新的项目文件夹。

2. 重命名项目

接下来,我们需要给新项目重新命名,以区分旧项目。

markdown

步骤:
1. 将粘贴后的文件夹重命名为`02_LEDFlow`,其中`Flow`表示流水灯的意思。
2. 保持后缀为`Register`,因为我们仍然使用寄存器来实现功能。

3. 删除自动生成的文件

在复制的项目中,有些文件是Keil自动生成的,包含了旧项目的信息,我们需要将它们删除。

markdown

步骤:
1. 删除`Objects`、`Listings`、`Debug`和`Release`文件夹。
2. 删除`UVOPTX`和`SCVD`文件,这些通常是Keil的配置文件。

4. 重命名Keil项目文件

Keil项目文件的名称会影响项目和编译文件的识别,所以我们需要重命名。

markdown

步骤:
1. 将`.uvprojx`文件重命名为`LED_Flow.uvprojx`。

5. 配置新项目

新项目创建后,我们需要做一些配置,以确保项目能够正常编译和下载。

markdown

步骤:
1. 打开Keil项目。
2. 在下载器配置中,将下载器改回`ST-Link`。
3. 在`Options for Target`中,关闭`Reset and Run`和`Pageable`选项。

6. 使用VSCode打开新项目

最后,我们可以使用VSCode来打开新项目,并开始编码。

markdown

步骤:
1. 通过VSCode打开新项目的文件夹。
2. 使用VSCode的Keil插件打开Keil项目文件。

实践题及答案

题目: 如何在Keil中从旧项目创建新项目?

答案:

  1. 复制旧项目的文件夹到新的位置。
  2. 重命名新文件夹为02_LEDFlow
  3. 删除新项目中的ObjectsListingsDebugRelease文件夹以及UVOPTXSCVD文件。
  4. 重命名.uvprojx文件为LED_Flow.uvprojx
  5. 打开Keil项目,配置下载器为ST-Link,并关闭Reset and RunPageable选项。
  6. 使用VSCode打开新项目的文件夹,并使用VSCode的Keil插件打开Keil项目文件。

markdown

通过以上步骤,你就可以在Keil中成功地从旧项目创建新项目,并开始新的开发工作了。

P8 创建新文件和目录后如何在Keil里进行添加

概述

大家好,今天我们来学习一下在Keil中如何添加新创建的文件和目录。这对于我们组织和管理项目代码非常重要。

创建新文件和目录

1. 代码组织

首先,我们来考虑一下代码该如何组织。我们的LED流水灯代码会比较多,所以我们需要合理地组织这些代码。

2. 创建硬件层目录

我们可以创建一个新的目录,比如叫做Hardware,用来存放所有硬件相关的代码。

markdown

步骤:
1. 创建一个新的目录,命名为`Hardware`。
2. 在`Hardware`目录下,创建一个子目录,命名为`LED`,专门用来存放LED相关的代码。

3. 创建源码文件和头文件

接下来,我们需要在LED目录下创建源码文件和头文件。

markdown

步骤:
1. 在`LED`目录下,创建一个文本文档,命名为`LED.c`。
2. 同样地,创建另一个文本文档,命名为`LED.h`。

4. 将新文件添加到Keil项目

现在我们需要将这些新创建的文件添加到Keil项目中。

markdown

步骤:
1. 打开Keil项目。
2. 右键点击项目,选择`Add Files to Group 'Hardware/LED'`。
3. 选择`LED.c`和`LED.h`文件,添加到项目中。

5. 配置Include Path

为了让Keil能够找到我们的头文件,我们需要配置Include Path。

markdown

步骤:
1. 打开Keil的项目设置。
2. 在`C/C++`选项卡下,找到`Include Paths`。
3. 添加`Hardware/LED`目录到Include Path中。

实践题及答案

题目: 如何在Keil项目中添加新创建的LED源码文件和头文件?

答案:

  1. 在项目目录下创建Hardware文件夹,并在其中创建LED子文件夹。
  2. LED文件夹中创建LED.cLED.h文件。
  3. 打开Keil项目,将LED.cLED.h文件添加到Hardware/LED组中。
  4. 配置项目的Include Path,添加Hardware/LED目录。

markdown

通过以上步骤,你就可以在Keil项目中成功地添加新创建的LED源码文件和头文件,并开始编写代码了。

P9 编写LED控制的四个核心函数

概述

大家好,今天我们来学习一下如何在STM32中编写LED控制的四个核心函数,包括LED初始化、开灯、关灯和状态翻转。这些是嵌入式开发中非常基础且重要的操作。

LED控制函数的编写

1. LED初始化函数 LED_Init

首先,我们需要编写一个LED初始化函数,这个函数的作用是配置LED对应的GPIO端口。

c

void LED_Init(void) {// 打开GPIOA的时钟RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;// 配置PA8为通用推挽输出模式GPIOA->CRH |= GPIO_CRH_MODE8;GPIOA->CRH &= ~GPIO_CRH_CNF8;// 初始化所有LED为关闭状态LED_Off(LED1 | LED2 | LED3);
}

2. LED开灯函数 LED_On

接下来,我们编写一个开灯函数,通过操作GPIO的ODR寄存器来点亮LED。

c

void LED_On(uint16_t led) {GPIOA->ODR &= ~led;
}

3. LED关灯函数 LED_Off

然后,我们编写一个关灯函数,同样通过操作GPIO的ODR寄存器来熄灭LED。

c

void LED_Off(uint16_t led) {GPIOA->ODR |= led;
}

4. LED状态翻转函数 LED_Toggle

最后,我们编写一个状态翻转函数,使用异或操作来切换LED的状态。

c

void LED_Toggle(uint16_t led) {GPIOA->ODR ^= led;
}

宏定义的使用

为了方便调用,我们可以定义一些宏来代表特定的LED。

c

#define LED1 (1 << 0)
#define LED2 (1 << 1)
#define LED3 (1 << 8)

这样,我们就可以直接使用LED1LED2LED3来控制对应的LED灯。

实践题及答案

题目: 如何在STM32中编写LED控制函数?

答案:

  1. 编写LED_Init函数来初始化LED对应的GPIO端口。
  2. 编写LED_On函数来点亮LED。
  3. 编写LED_Off函数来熄灭LED。
  4. 编写LED_Toggle函数来切换LED的状态。
  5. 使用宏定义来简化LED控制代码。

markdown

通过以上步骤,你就可以在STM32中成功地编写LED控制函数,并控制LED的亮灭状态了。

P10 编写LED控制函数

概述

大家好,今天我们来学习一下如何在STM32中编写LED控制函数。这些函数包括LED初始化、开灯、关灯和状态翻转,这些都是嵌入式开发中非常基础的操作。

LED控制函数的编写

1. LED初始化函数 LED_Init

首先,我们需要编写一个LED初始化函数,这个函数的作用是配置LED对应的GPIO端口。

c

void LED_Init(void) {// 打开GPIOA的时钟RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;// 配置PA8为通用推挽输出模式GPIOA->CRH |= GPIO_CRH_MODE8;GPIOA->CRH &= ~GPIO_CRH_CNF8;// 初始化所有LED为关闭状态LED_Off(LED1 | LED2 | LED3);
}

2. LED开灯函数 LED_On

接下来,我们编写一个开灯函数,通过操作GPIO的ODR寄存器来点亮LED。

c

void LED_On(uint16_t led) {GPIOA->ODR &= ~led;
}

3. LED关灯函数 LED_Off

然后,我们编写一个关灯函数,同样通过操作GPIO的ODR寄存器来熄灭LED。

c

void LED_Off(uint16_t led) {GPIOA->ODR |= led;
}

4. LED状态翻转函数 LED_Toggle

最后,我们编写一个状态翻转函数,使用异或操作来切换LED的状态。

c

void LED_Toggle(uint16_t led) {GPIOA->ODR ^= led;
}

宏定义的使用

为了方便调用,我们可以定义一些宏来代表特定的LED。

c

#define LED1 (1 << 0)
#define LED2 (1 << 1)
#define LED3 (1 << 8)

这样,我们就可以直接使用LED1LED2LED3来控制对应的LED灯。

实践题及答案

题目: 如何在STM32中编写LED控制函数?

答案:

  1. 编写LED_Init函数来初始化LED对应的GPIO端口。
  2. 编写LED_On函数来点亮LED。
  3. 编写LED_Off函数来熄灭LED。
  4. 编写LED_Toggle函数来切换LED的状态。
  5. 使用宏定义来简化LED控制代码。

markdown复制

通过以上步骤,你就可以在STM32中成功地编写LED控制函数,并控制LED的亮灭状态了。

P11 流水灯效果的实现

概述

大家好,今天我们来学习一下如何在STM32上实现流水灯效果。这个项目需要我们使用之前学过的LED控制函数,包括初始化、开灯、关灯和状态翻转。

实现流水灯效果

1. 准备工作

首先,我们需要确保我们的LED控制函数已经准备好,包括LED_InitLED_OnLED_OffLED_Toggle

2. 主函数编写

接下来,我们在主函数中编写流水灯的逻辑。

c

int main(void) {// 初始化LEDLED_Init();while (1) {// 依次点亮LED1,延时,然后熄灭LED_On(LED1);Delay_ms(500);LED_Off(LED1);// 依次点亮LED2,延时,然后熄灭LED_On(LED2);Delay_ms(500);LED_Off(LED2);// 依次点亮LED3,延时,然后熄灭LED_On(LED3);Delay_ms(500);LED_Off(LED3);}
}

3. 延时函数

由于我们需要在每个LED点亮后等待一段时间,所以我们使用了一个简单的延时函数Delay_ms

c

void Delay_ms(uint16_t ms) {uint16_t i, j;for (i = 0; i < ms; i++)for (j = 0; j < 123; j++); // 简单的循环延时
}

4. 命名风格和输入法技巧

在编程中,我们有两种常见的命名风格:

  • 驼峰命名法(CamelCase):首字母大写,每个单词的首字母大写,如BadDelay
  • 下划线命名法(SnakeCase):单词间用下划线分隔,如bad_delay

此外,老师还提到了输入法的u模式,帮助我们快速输入不认识的汉字。

5. 编译和烧录

最后,我们编译和烧录代码,检查流水灯效果。

实践题及答案

题目: 如何在STM32上实现流水灯效果?

答案:

  1. 编写LED_Init函数初始化LED。
  2. 在主函数中,依次点亮每个LED,并使用延时函数Delay_ms控制每个LED的亮灭时间。
  3. 使用驼峰命名法或下划线命名法来命名函数,提高代码的可读性。
  4. 编译和烧录代码,检查流水灯效果。

markdown复制

通过以上步骤,你就可以在STM32上成功地实现流水灯效果了。

P12 主动阅读Error信息的重要性

概述

大家好,今天我们来聊聊在编程过程中,如何正确地处理和阅读错误信息。这对于我们调试程序和解决问题非常重要。

刷录不成功的问题

1. 问题描述

有些同学在尝试烧录程序时遇到了问题,编译可以通过,但是烧录不成功,会报错如errorflashlologfileattachketDLLhasbeencancelled,这通常意味着目标连接被取消了。

2. 可能的原因

这个问题大多数是因为STlink没有插牢,或者是Keil中的STlink配置有问题。

3. 解决方案

  • 确保STlink插牢。
  • 检查Keil中的STlink配置是否正确。
  • 确保在配置STlink时点击了OK而不是直接关闭了配置窗口。

阅读错误信息的能力

1. 错误信息的重要性

很多同学在写代码时会遇到各种问题,编译器会在底部的框里给出错误信息,这是我们排查问题的重要线索。

2. 硬读错误信息

如果你对英语阅读有为难情绪,那么你需要克服这个问题。编译器的错误信息是英文的,你需要硬读,即使看不懂也要尝试去理解。

3. 使用翻译软件

可以使用翻译软件辅助阅读错误信息,比如设置截图翻译功能,帮助理解错误信息。

4. 错误信息的解读

错误信息会告诉你具体哪里错了,这是排查问题的起点。

5. 错误信息的级别

有些错误信息可能是警告,比如文件最后一行没有换行符,这通常不影响程序运行,可以忽略。

实践题及答案

题目: 如果在烧录程序时遇到attachketDLLhasbeencancelled错误,应该如何解决?

答案:

  1. 检查STlink是否插牢。
  2. 检查Keil中的STlink配置是否正确。
  3. 确保在配置STlink时点击了OK保存配置。

markdown

通过以上步骤,你应该能够解决烧录时遇到的问题。

P13 系统滴答定时器和时间换算问题

概述

大家好,今天我们来聊聊STM32中的系统滴答定时器(SysTick)和时间换算问题。这是嵌入式开发中非常基础且重要的部分。

系统滴答定时器(SysTick)

1. SysTick定时器的作用

SysTick定时器是ARM Cortex-M系列内核中的一个内置定时器,它提供了系统滴答定时、时间测量和低功耗定时等功能。

2. SysTick定时器的工作原理

SysTick定时器是一个24位的倒计数定时器,当计数到0时,会从RELOAD寄存器中自动重装载定时初值,开始新一轮计数。

3. SysTick定时器的寄存器

  • CTRL(控制寄存器):控制SysTick定时器的启动、停止、中断使能等。
  • LOAD(重载寄存器):设置定时器的重载值。
  • VAL(当前值寄存器):显示当前的计数值。
  • CALIB(校准寄存器):用于校准定时器的精度。

4. SysTick定时器的时钟源

SysTick定时器的时钟源可以是处理器的核心时钟(HCLK)或者核心时钟除以8。这个时钟源为SysTick定时器提供了计数的基准。

时间换算问题

1. 时钟周期的计算

时钟周期是指时钟信号完成一个周期所需的时间。对于72MHz的时钟频率,周期长度为1/72MHz,即大约13.89ns。

1. 微秒和毫秒的换算

  • 微秒:1微秒等于1/1,000,000秒。
  • 毫秒:1毫秒等于1/1,000秒。

2. 公制单位和时间换算

在公制单位中,时间单位的换算遵循千进制,即每三个数量级变化一次,例如从秒到毫秒,再从毫秒到微秒。

3. 计算SysTick定时器的周期

如果我们希望SysTick定时器每500毫秒触发一次中断,我们可以这样计算:

  • 500毫秒 = 500,000微秒
  • 对于72MHz的时钟,每个周期为13.89ns,所以500毫秒内的周期数为500,000 / 13.89 ≈ 36,000周期
  • 因此,我们需要设置SysTick的LOAD寄存器为36,000 - 1 = 35,999。

实践题及答案

题目: 如何设置SysTick定时器每500毫秒触发一次中断?

答案:

  1. 计算所需的周期数:500毫秒 = 500,000微秒,72MHz时钟周期为13.89ns,周期数为500,000 / 13.89 ≈ 36,000周期。
  2. 设置SysTick的LOAD寄存器为36,000 - 1 = 35,999。
  3. 启用SysTick定时器。

markdown

通过以上步骤,你可以设置SysTick定时器每500毫秒触发一次中断。

P14 时间换算快速讲解

概述

大家好,今天我们来快速过一下时间换算的问题。这对于我们理解和使用STM32的系统滴答定时器(SysTick)非常重要。

时间换算的基本概念

1. 时钟频率与周期

我们使用的时钟频率是72MHz,这意味着一秒内有72,000,000个周期。一个周期的时间就是频率的倒数。

2. 时间单位换算

我们需要将时钟周期转换成更直观的时间单位,如微秒(μs)和毫秒(ms)。

3. 单位换算的步骤

  • 秒到毫秒:1秒 = 1,000毫秒。
  • 毫秒到微秒:1毫秒 = 1,000微秒。

4. 计算周期长度

要计算72MHz时钟频率下一个周期的长度,我们可以用1秒除以72,000,000。

5. 单位换算实例

如果我们想要计算72MHz时钟频率下一个周期的长度:

  • 1秒 / 72,000,000 = 13.89微秒(μs)

这意味着每个周期大约是13.89微秒。

6. 公制单位的特点

在公制单位中,每三个数量级变化一次,例如:

  • 1千伏(kV)= 1,000伏(V)
  • 1毫安(mA)= 1,000微安(μA)

实践题及答案

题目: 如何将72MHz的时钟频率转换为周期长度?

答案:

  1. 确定时钟频率:72MHz。
  2. 计算周期长度:1秒 / 72,000,000 = 13.89微秒。

markdown

通过以上步骤,我们可以得出72MHz的时钟频率下一个周期的长度大约是13.89微秒。

P15 创建延时函数的C和H文件

概述

大家好,今天我们来学习一下如何在项目中创建和管理延时函数。我们将创建两个文件:delay.cdelay.h,用于专门存放延时相关的代码。

创建延时函数文件

1. 创建文件

首先,我们需要在项目中创建两个新文件,一个用于实现延时函数(delay.c),另一个用于声明延时函数的原型(delay.h)。

markdown

步骤:
1. 在项目目录中创建一个新的C文件,命名为`delay.c`。
2. 在项目目录中创建一个新的H文件,命名为`delay.h`。

2. 添加文件到项目

接下来,我们需要将这两个新创建的文件添加到Keil项目中。

markdown

步骤:
1. 打开Keil项目。
2. 右键点击项目,选择`Add Files to Group`。
3. 选择`delay.c`和`delay.h`文件,添加到项目中。

3. 编写延时函数原型

delay.h文件中,我们需要声明延时函数的原型,以便在其他文件中调用。

c

// delay.h
#ifndef __DELAY_H__
#define __DELAY_H__void Delay_ms(uint16_t ms);
void Delay_us(uint16_t us);#endif /* __DELAY_H__ */

4. 实现延时函数

delay.c文件中,我们需要实现延时函数的具体逻辑。

c

// delay.c
#include "delay.h"void Delay_ms(uint16_t ms) {// 实现延时毫秒的逻辑
}void Delay_us(uint16_t us) {// 实现延时微秒的逻辑
}

5. 包含头文件

在需要使用延时函数的其他C文件中,包含delay.h头文件。

c

#include "delay.h"

实践题及答案

题目: 如何在Keil项目中创建和管理延时函数?

答案:

  1. 在项目目录中创建delay.cdelay.h两个文件。
  2. 将这两个文件添加到Keil项目中。
  3. delay.h中声明延时函数的原型。
  4. delay.c中实现延时函数的具体逻辑。
  5. 在其他C文件中包含delay.h头文件,以便使用延时函数。

markdown复制

通过以上步骤,你就可以在Keil项目中成功地创建和管理延时函数了。

P16 在User路径下管理头文件和Include Path

概述

大家好,今天我们来聊聊在STM32项目中如何管理头文件,以及如何配置Include Path。这是一个常见的问题,特别是当我们在User路径下创建新的头文件时。

User路径下的头文件管理

1. 创建头文件

之前我们提到在User路径下创建了两个文件:delay.cdelay.h。这两个文件分别用于实现和声明延时函数。

2. 配置Include Path

有同学可能会问,我们之前创建文件后都会配置Include Path,这次是否还需要配置。答案是肯定的,因为我们之前可能忘记将User目录添加到Include Path中了。

markdown

步骤:
1. 打开Keil项目。
2. 在项目设置中找到C/C++选项卡。
3. 在Include Paths部分,添加User目录到路径列表中。

3. 为什么需要配置Include Path

如果我们不配置Include Path,编译器将无法找到User目录下的头文件,这会导致编译错误。

4. 添加User目录到Include Path

现在我们需要将User目录添加到Include Path中,以便编译器能够找到delay.h文件。

markdown

步骤:
1. 在Keil的项目设置中,找到Include Paths设置。
2. 点击右侧的“Add”按钮。
3. 浏览到User目录,选择该目录并添加。

实践题及答案

题目: 如何在Keil项目中添加User目录到Include Path?

答案:

  1. 打开Keil项目。
  2. 进入项目设置,找到C/C++选项卡。
  3. 在Include Paths部分,添加User目录到路径列表中。

markdown

通过以上步骤,你可以确保编译器能够找到User目录下的头文件,从而避免编译错误。

P17 编写延时函数的原型

概述

大家好,今天我们来学习一下如何在C语言项目中编写延时函数的原型。这对于嵌入式开发中的定时和延时操作非常重要。

延时函数的编写

1. 准备工作

首先,我们需要确保项目环境已经准备好,相关的文件也已经添加到项目中。

2. 移动函数实现

为了避免主文件越来越长,我们将badDelay函数移动到delay.c文件中,并在其他文件中使用时,需要包含delay.h头文件。

c

// delay.c
#include "delay.h"void BadDelay(void) {// 延时函数的实现
}

3. 编写函数原型

delay.h文件中,我们需要声明三个延时函数的原型:微秒延时、毫秒延时和秒延时。

c

// delay.h
#ifndef __DELAY_H__
#define __DELAY_H__void Delay_us(uint16_t us);
void Delay_ms(uint16_t ms);
void Delay_s(uint16_t s);#endif /* __DELAY_H__ */

4. 包含头文件

在需要使用延时函数的其他C文件中,包含delay.h头文件。

c

#include "delay.h"

5. 为什么使用uint16_t

这里我们使用uint16_t作为参数类型,而不是uint8_tuint32_t。这是因为uint16_t可以提供足够的范围来表示毫秒和秒级别的延时,同时避免了uint32_t可能带来的资源消耗。

实践题及答案

题目: 为什么在延时函数中使用uint16_t作为参数类型?

答案:

uint16_t可以提供足够的范围来表示毫秒和秒级别的延时,同时避免了uint32_t可能带来的资源消耗。例如,对于一个最大值为65535的uint16_t变量,我们可以表示的最大延时是65.535秒,这对于大多数嵌入式应用来说是足够的。

markdown

通过以上步骤,你可以在C语言项目中成功地编写和使用延时函数。

P18 延时函数的封装

概述

大家好,今天我们来学习一下如何在C语言中封装延时函数。这将帮助我们更好地控制程序中的延时操作,使代码更加模块化和可重用。

延时函数的封装

1. 延时函数的基本思路

我们已经有了微秒级的延时函数Delay_us,现在我们需要在此基础上封装出毫秒级和秒级的延时函数。

2. 毫秒级延时函数 Delay_ms

毫秒级的延时函数可以通过调用微秒级的延时函数来实现。例如,要实现1毫秒的延时,我们可以调用Delay_us函数1000次。

c

void Delay_ms(uint16_t ms) {while (ms--) {Delay_us(1000); // 调用微秒级延时函数1000次,实现1毫秒延时}
}

3. 秒级延时函数 Delay_s

同样,秒级的延时函数可以通过调用毫秒级的延时函数来实现。例如,要实现1秒的延时,我们可以调用Delay_ms函数1000次。

c

void Delay_s(uint16_t s) {while (s--) {Delay_ms(1000); // 调用毫秒级延时函数1000次,实现1秒延时}
}

4. 避免溢出和循环的使用

在实现这些延时函数时,我们需要注意参数的类型和可能的溢出问题。使用循环而不是乘法可以避免溢出,并且使代码更加健壮。

实践题及答案

题目: 如何在C语言中实现毫秒级和秒级的延时函数?

答案:

  1. 通过调用微秒级延时函数Delay_us1000次来实现毫秒级延时函数Delay_ms
  2. 通过调用毫秒级延时函数Delay_ms1000次来实现秒级延时函数Delay_s
  3. 使用循环而不是乘法来避免可能的溢出问题。

markdown

通过以上步骤,你可以在C语言项目中成功地封装毫秒级和秒级的延时函数。

P19 编写 delay_us 函数

概述

大家好,今天我们来学习一下如何在STM32中编写微秒级的延时函数 delay_us。这个函数对于精确控制时间间隔非常有用。

delay_us 函数的实现

1. 理解SysTick定时器

首先,我们需要理解系统滴答定时器(SysTick)的工作原理。SysTick定时器是一个24位的倒计数定时器,它从预设的重载值开始递减,每次递减1,直到达到0,然后重置为初始值。

2. 配置SysTick定时器

我们需要给SysTick定时器的重载寄存器(LOAD)配置一个初始值,这个值决定了定时器溢出的时间。

c

SysTick->LOAD = 72 * us - 1; // 设置SysTick定时器的重载值

这里,我们假设系统时钟频率为72MHz,所以每微秒需要72个时钟周期。

3. 使能SysTick定时器

接下来,我们需要使能SysTick定时器,并等待它溢出。

c

SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 使能SysTick定时器

4. 等待溢出

然后,我们需要等待SysTick定时器的COUNTFLAG标志位变为1,表示定时器已经溢出。

c

while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)) {// 等待SysTick定时器溢出
}

5. 关闭SysTick定时器

最后,我们需要关闭SysTick定时器,以避免它继续计数。

c

SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 关闭SysTick定时器

实践题及答案

题目: 如何在STM32中实现微秒级的延时函数 delay_us

答案:

  1. 配置SysTick定时器的重载寄存器(LOAD)。
  2. 使能SysTick定时器。
  3. 等待SysTick定时器溢出。
  4. 关闭SysTick定时器。

c

void delay_us(uint16_t us) {SysTick->LOAD = 72 * us - 1; // 设置SysTick定时器的重载值SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 使能SysTick定时器while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)) {// 等待SysTick定时器溢出}SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 关闭SysTick定时器
}

P20 延时函数效果验证

概述

大家好,今天我们来验证一下我们之前编写的延时函数的效果。我们会通过一个简单的流水灯实验来测试延时函数的准确性。

延时函数测试

1. 测试准备

我们已经在delay.c文件中实现了延时函数,并且将它们声明在delay.h头文件中。现在我们需要在主函数中测试这些函数。

2. 修改主函数

我们将在主函数中使用delay_msdelay_s函数来控制三个LED灯的亮灭时间,以此来验证延时函数的效果。

c

#include "delay.h"int main(void) {LED_Init(); // 初始化LEDwhile (1) {LED_On(LED1);Delay_ms(500); // 延时500毫秒LED_Off(LED1);LED_On(LED2);Delay_s(1); // 延时1秒LED_Off(LED2);LED_On(LED3);Delay_s(2); // 延时2秒LED_Off(LED3);}
}

3. 编译和烧录

我们将代码编译并烧录到STM32开发板上,然后观察LED灯的行为是否符合预期。

4. 观察结果

通过观察LED灯的亮灭时间,我们可以验证延时函数是否准确。如果LED灯按照设定的时间亮灭,那么说明我们的延时函数工作正常。

实践题及答案

题目: 如何验证延时函数的效果?

答案:

  1. 在主函数中使用delay_msdelay_s函数控制LED灯的亮灭时间。
  2. 编译并烧录代码到STM32开发板上。
  3. 观察LED灯的亮灭时间是否符合预期。

markdown复制

通过以上步骤,我们可以验证延时函数的准确性。如果LED灯按照设定的时间亮灭,那么说明我们的延时函数工作正常。

P21 延时函数的标志位清零和n减不减一的问题

概述

大家好,今天我们来讨论一下在编写延时函数时遇到的两个常见问题:标志位如何清零,以及在设置定时器时是否需要n减一。

延时函数的标志位清零

1. 问题提出

有同学可能会问,delay_us 函数里面将 VAL 设置为零是否有必要。这个操作看起来好像是多余的,因为一旦开始计数,VAL 的值就会被自动更新。

2. 分析解释

实际上,这个操作确实不是必需的。因为SysTick定时器一旦使能,会自动将 LOAD 的值加载到 VAL 中。所以,即使我们不手动设置 VAL,它也会从 LOAD 的值开始倒数。

3. 编译和烧录测试

我们可以编译和烧录代码,然后观察程序的运行情况。结果表明,即使没有手动设置 VAL 为零,程序也能正常运行,LED灯的流水效果也符合预期。

n减不减一的问题

1. 问题的提出

另一个问题是关于定时器设置时是否需要n减一。这个问题在文档中有不同的说法,有的说要减一,有的说不用减一。

2. 实际影响分析

实际上,无论是减一还是不减一,对定时器的精度影响非常小,只差七十二分之一微秒。因此,这个问题并不需要过于纠结。

3. 手册解释

根据ARM Cortex-M3的权威指南,有两种情况:一种是需要减一(multiple shots),另一种是不需要减一(single shot)。在我们的情况下,因为我们没有让定时器自动重载,所以实际上不需要减一。

实践题及答案

题目: 在STM32中编写延时函数时,是否需要将SysTick定时器的 VAL 设置为零,以及是否需要在设置定时器时n减一?

答案:

  1. VAL 设置为零并不是必需的,因为SysTick定时器会自动从 LOAD 加载值。
  2. 在我们的用法中,不需要减一,因为我们没有让定时器自动重载。

markdown

通过以上分析,我们可以得出结论:在编写延时函数时,这两个操作都不是必需的。

P22 如何安装STM32CubeMX

概述

大家好,今天我们来学习一下如何安装STM32CubeMX,这是一个基于Java开发的软件,对于STM32的开发来说非常重要。

安装前的准备

1. Java运行环境

首先,我们需要确保电脑上已经安装了Java运行环境。STM32CubeMX是基于Java开发的,所以这是安装CubeMX的前提条件。

markdown

步骤:
1. 打开CMD。
2. 输入命令`java -version`检查Java是否已安装。
3. 如果未安装,需要先安装Java运行时环境。

2. 下载Java运行时环境

如果系统中没有Java运行环境,可以从以下链接下载并安装:

markdown

下载地址:[Java Runtime Environment](https://www.oracle.com/java/technologies/javase-jdk8-downloads.html)

安装STM32CubeMX

1. 下载安装包

可以从STM32官方网站下载STM32CubeMX的安装包,或者直接从提供的资料中获取。

markdown

步骤:
1. 访问STM32官方网站或打开提供的资料包。
2. 下载STM32CubeMX的安装包。

2. 运行安装程序

下载完成后,直接双击安装包中的setup.exe文件开始安装。

markdown

步骤:
1. 双击`setup.exe`文件。
2. 根据提示完成安装。

3. 配置安装选项

在安装过程中,可以选择为所有用户安装或仅为当前用户安装,通常我们选择为当前用户安装即可。

markdown

步骤:
1. 选择安装范围(For all users或Just for me)。
2. 接受许可协议。
3. 选择安装路径,避免路径中包含中文。

4. 完成安装

完成上述步骤后,STM32CubeMX就安装成功了。安装完成后,可以在开始菜单或桌面找到STM32CubeMX的快捷方式。

markdown

步骤:
1. 完成安装向导。
2. 在开始菜单或桌面找到STM32CubeMX的快捷方式。

实践题及答案

题目: 如何检查Java运行环境是否已安装?

答案:

打开CMD,输入命令java -version,如果能够显示版本信息,则说明Java运行环境已安装。

markdown

通过以上步骤,你可以确认Java运行环境是否已安装,并继续进行STM32CubeMX的安装。

P23 STM32CubeMX软件安装教程

大家好,今天我们来学习如何给STM32CubeMX安装180的软件开发包。如果你是第一次接触STM32CubeMX,或者需要更新你的软件包,那么这个教程将非常适合你。

软件界面介绍

首先,我们打开STM32CubeMX软件,可以看到界面分为几个部分:

  • 左侧:显示当前电脑上存在的STM32CubeMX项目。
  • 右侧:创建项目的向导。

创建新项目

创建新项目有三种方式:

  1. 从MCU型号创建项目:选择一个MCU型号来创建项目。
  2. 从STboard创建项目:选择一个官方支持的开发板来创建项目。
  3. 从例子开始项目:从官方提供的示例开始一个项目。

通常情况下,我们会选择第三种方式来创建项目。

联网下载MCU数据库

在创建项目之前,STM32CubeMX会联网下载一个包含所有支持的MCU芯片的数据库。如果你的网络条件不佳,这个过程可能会非常缓慢。

选择MCU型号

在软件内部,我们可以直接搜索所需的MCU型号,例如STM32F103C8。找到型号后,选中它,就可以开始创建项目了。

安装芯片支持包

在创建项目之前,我们需要确保已经安装了芯片的支持包。如果没有安装,创建的项目可能会出现问题。

管理嵌入式软件包

我们可以通过点击Help菜单中的Manage Enbedded Software Packages来管理软件包。

本地安装软件包

由于网络问题,我们可能需要从本地安装软件包。以下是步骤:

  1. 打开Help菜单,选择Manage Enbedded Software Packages
  2. 点击From Local,选择本地的软件包进行安装。

判断安装是否成功

安装完成后,我们可以在STM32CubeMX中查看软件包的版本号,如果显示为绿色框,则表示安装成功。


练习题

  1. 如何创建一个新的STM32CubeMX项目?
    • 答案:选择从MCU型号、STboard或从例子开始项目中的一个选项来创建新项目。
  2. 如果网络不佳,如何安装STM32CubeMX的软件包?
    • 答案:选择From Local选项,从本地选择软件包进行安装。
  3. 如何判断STM32CubeMX软件包是否安装成功?
    • 答案:在软件中查看软件包的版本号,如果显示为绿色框,则表示安装成功。

相关文章:

stm32利用LED配置基础寄存器+体验滴答定时器+hal库环境配置

P1 LED控制与流水灯效果实现 概述 大家好&#xff0c;今天我们来学习一下如何在STM32上控制LED灯&#xff0c;并且实现一个流水灯的效果。这不仅是一个基础的实践&#xff0c;也是嵌入式开发中非常常见的需求。 LED控制 1. LED初始化 首先&#xff0c;我们需要对LED灯对应…...

Spark RDD sortBy算子执行时进行数据 “采样”是什么意思?

一、sortBy 和 RangePartitioner sortBy 在 Spark 中会在执行排序时采用 rangePartitioner 进行分区&#xff0c;这会影响数据的分区方式&#xff0c;并且这一步骤是通过对数据进行 “采样” 来计算分区的范围。不过&#xff0c;重要的是&#xff0c;sortBy 本身仍然是一个 tr…...

Ubuntu24.04下的docker问题

按官网提示是可以安装成功的&#xff0c;但是curl无法使用https下载&#xff0c;会造成下述语句执行失败 # Add Dockers official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https…...

Tri Mode Ethernet MAC IP核详解

本文对 Vivado 的三速 MAC IP 核&#xff08;Tri Mode Ethernet MAC&#xff0c;TEMAC&#xff09;进行介绍。 在自行实现三速以太网 MAC 控制器时&#xff0c;GMII/RGMII 接口可以通过 IDDR、ODDR 原语实现&#xff0c;然而实际使用中自己实现的模块性能不是很稳定&#xff08…...

【U盘车载音乐】某宝198的3068首车载专用音乐合集【高音质】24G

「【U盘车载音乐】某宝198的3068首车载专用音乐合集【高音质】24G」 复制下方口令&#xff0c;打开最新版「夸克APP」即可获取保存&#xff08;防止和谐&#xff01;&#xff01;&#xff01;&#xff09; 口令&#xff1a; 动作懿范鉴真渡多好备用口令&#xff1a; /~19dc35…...

android 实现答题功能

一、效果 二、实现思路 1、界面实现 实现起来其实不难&#xff0c;首先我们可以看到&#xff0c;界面是由答题进度、题目、选项ABCD组成&#xff0c;现在就是要考虑实现方式&#xff0c;答题进度可以使用Textviewprogressbar实现&#xff0c;题目直接使用Textview&#xff0c;…...

JSONP处理跨域请求

JSONP 背景 由于浏览器存在安全策略&#xff0c;所以当访问的请求中的协议、域名、端口其中一个与本站不同时就会形成跨域&#xff0c;这里介绍一种比较简单的方案——jsonp。 原理 浏览器对 script、img这些带有src属性的的标签在发送请求时是不会触发跨域的校验&#xff…...

栈的应用,力扣394.字符串解码力扣946.验证栈序列力扣429.N叉树的层序遍历力扣103.二叉树的锯齿形层序遍历

目录 力扣394.字符串解码 力扣946.验证栈序列 力扣429.N叉树的层序遍历 力扣103.二叉树的锯齿形层序遍历 力扣394.字符串解码 看见括号&#xff0c;由内而外&#xff0c;转向用栈解决。使用两个栈处理&#xff0c;一个用String,一个用Integer 遇到数字:提取数字放入到数字栈…...

华为手机启用ADB无线调试功能

打开开发者模式,勾选USB调试,和“仅充电”模式下允许ADB调试 确认 设置添加adb路径到PATH变量 使用adb查看安卓设置 切换为无线模式: 查看手机IP...

HTML 元素类型介绍

目录 1. 块级元素&#xff08;Block-level Elements&#xff09; 2. 行级元素&#xff08;Inline Elements&#xff09; 3. 行内块级元素&#xff08;Inline-block Elements&#xff09; 4. 表格相关元素 5. 列表相关元素 6. 表单相关元素 示例代码 示例效果 ​编辑 …...

前端反向代理的配置和實現

反向代理是位於客戶端和服務器之間的一個中間層&#xff0c;它代表客戶端向伺服器發起請求&#xff0c;然後將伺服器的回應返回給客戶端。與傳統的正向代理不同&#xff0c;反向代理是由伺服器端配置的&#xff0c;客戶端通常不知道它的存在。在前端開發中&#xff0c;反向代理…...

日志分析工具

一、nginx_log_analysis工具 1、工具下载&#xff0c;http://linux5588.blog.51cto.com/&#xff0c;它是用python语言写的&#xff0c;只是用来分析nginx日志&#xff0c;它的输出比较简单&#xff0c;以IP为主&#xff0c;可以查看每个IP的访问的流量&#xff0c;次数&#…...

python: Serialize and Deserialize complex JSON using jsonpickle

# encoding: utf-8 # 版权所有 2024 ©涂聚文有限公司 # 许可信息查看&#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎 # Serialize and Deserialize complex JSON in Python # 描述&#xff1a;pip install jsonpickle https://github.com/jsonpi…...

【分布式锁解决超卖问题】setnx实现

目录 使用场景的描述 并发安全问题 悲观锁与乐观锁问题 一人一单的问题 服务器负载均衡问题 分布式锁 分布式锁的实现 获取锁 释放锁 实现思路 误删情况的分析 解决误删的方法 代码优化 分布式锁的原子性分析 文章代码地址&#xff1a;分布式锁1.0 使用场景的描述 今天的主人…...

【MySQL实战45讲笔记】基础篇——事务隔离

系列文章 基础篇——MySQL 的基础架构 基础篇——redo log 和 binlog 目录 系列文章1. 事务隔离1.1 隔离性与隔离级别1.2 如何实现事务隔离1.3 事务的启动方式1.4 思考&#xff1a; 使用什么方案来避免长事务 1. 事务隔离 简单来说&#xff0c;事务就是要保证一组数据库操作&…...

RFdiffusion calculate_igso3函数解读

calculate_igso3 函数旨在对 IGSO(3) 分布的概率密度函数 (PDF)、累积分布函数 (CDF)、以及相关统计量进行数值近似计算,特别用于预计算以加速后续操作(例如采样、反向扩散等)。 calculate_igso3函数源代码: def calculate_igso3(*, num_sigma, num_omega, min_sigma, ma…...

Vue3 + Vite 项目引入 postcss + tailwindcss

一、PostCSS 1. 简介 PostCSS 是一个强大的 CSS 处理工具&#xff0c;它本身是一个工具库&#xff0c;但其核心功能是通过插件扩展&#xff0c;来对 CSS 进行编译、转换和优化。它适用于现代 CSS 开发&#xff0c;提供更灵活、高效的方式来处理样式表。 2. 主要作用 增强 CS…...

AI Large Language Model

AI 的 Large Language model LLM , 大语言模型&#xff1a; 是AI的模型&#xff0c;专门设计用来处理自然语言相关任务。它们通过深度学习和庞大的训练数据集&#xff0c;在理解和生成自然语言文本方面表现出色。常见的 LLM 包括 OpenAI 的 GPT 系列、Google 的 PaLM 和 Meta…...

Linux系统性能优化技巧

系统性能优化 在当今的信息技术领域&#xff0c;Linux系统的性能优化变得越来越重要。随着Linux操作系统的广泛应用&#xff0c;从桌面环境到大型服务器集群&#xff0c;性能优化不仅可以提升系统的响应速度和吞吐量&#xff0c;还能降低资源消耗&#xff0c;从而延长硬件使用…...

基于CNN+RNNs(LSTM, GRU)的红点位置检测(pytorch)

1 项目背景 需要在图片精确识别三跟红线所在的位置&#xff0c;并输出这三个像素的位置。 其中&#xff0c;每跟红线占据不止一个像素&#xff0c;并且像素颜色也并不是饱和度和亮度极高的红黑配色&#xff0c;每个红线放大后可能是这样的。 而我们的目标是精确输出每个红点的…...

【AI系统】GPU 架构回顾(从2018年-2024年)

Turing 架构 2018 年 Turing 图灵架构发布&#xff0c;采用 TSMC 12 nm 工艺&#xff0c;总共 18.6 亿个晶体管。在 PC 游戏、专业图形应用程序和深度学习推理方面&#xff0c;效率和性能都取得了重大进步。相比上一代 Volta 架构主要更新了 Tensor Core&#xff08;专门为执行…...

Vue 内置组件 keep-alive 中 LRU 缓存淘汰策略和实现

LRU&#xff08;Least Recently Used&#xff0c;最近最少使用&#xff09;是通过记录缓存项的访问顺序来决定淘汰的策略&#xff1a;当缓存满时&#xff0c;移除最久未被使用的项。 核心概念&#xff1a; 缓存存储&#xff1a;使用 Map 存储键值对&#xff0c;用于快速访问缓…...

联邦学习安全聚合算法综述(论文解析)以及如何确定自己研究方向的方法

自己写相关论文的方法&#xff1a; 可以重点看看综述类论文的未来研究方向和引言中前人已经做过的内容 联邦学习安全聚合算法综述 auth:江萍 1 通讯作者 李芯蕊 1 赵晓阳 2 杭永凯 摘要 摘要&#xff1a;随着深度学习技术的发展&#xff0c;人工智能在社会的各个方面有着重要…...

【JAVA 笔记】12 带有数据库文件的完整的JDBC访问例子,命令行界面

【JAVA 笔记】12 带有数据库文件的完整的JDBC访问例子&#xff0c;命令行界面 代码结构解析 1. 导入必要的包 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.sql.PreparedStatement; impo…...

基于java+SpringBoot+Vue的在线宠物用品交易网站设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven mysql5.7或8.0等等组成&#x…...

智慧社区管理系统平台提升物业运营效率与用户体验

内容概要 智慧社区管理系统平台是一个集成了多项功能的综合性解决方案&#xff0c;旨在通过先进的技术手段提升物业管理的效率和居民的生活质量。该平台不仅关注物业运营的各个方面&#xff0c;还强调用户体验的重要性。随着科技的发展&#xff0c;社区管理方式正发生着翻天覆…...

el-table-column自动生成序号在序号前插入图标

实现效果&#xff1a; 代码如下&#xff1a; 在el-table里加入这个就可以了&#xff0c;需要拿到值可以用scope.$index ​​​​​​​<el-table-column type"index" label"序号" show-overflow-tooltip"true" min-width"40">…...

深度学习之目标检测的常用标注工具

1 LabelImg ​ LabelImg 是一款开源的图像标注工具&#xff0c;标签可用于分类和目标检测&#xff0c;它是用 Python 编写的&#xff0c;并使用Qt作为其图形界面&#xff0c;简单好用。注释以 PASCAL VOC 格式保存为 XML 文件&#xff0c;这是 ImageNet 使用的格式。 此外&…...

「Mac玩转仓颉内测版21」基础篇1 - 仓颉程序的基本组成

本篇将系统介绍Cangjie编程语言中程序的基本组成部分&#xff0c;涵盖 main 函数的定义、包与模块的使用、变量类型、作用域和代码结构原则&#xff0c;帮助开发者理解Cangjie程序的整体结构。 关键词 程序入口点main函数包与模块变量类型与作用域值类型与引用类型代码结构与规…...

【计算机网络】解决bind error

服务器有时可以立即重启&#xff0c;有时候无法立即重启 — bind error 首先要知道&#xff1a;四次挥手动作完成之后&#xff0c;主动断开连接的一方要维持一段时间的TIME_WAIT bind error原因&#xff1a;因为是服务器主动断开的&#xff0c;所以服务器要去维持TIME_WAIT状…...

【SVN和GIT】版本控制系统详细下载使用教程

文章目录 ** 参考文章一、什么是SVN和GIT二、软件使用介绍1 SVN安装1.1 服务端SVN下载地址1.2 客户端SVN下载地址2 SVN使用2.1 服务端SVN基础使用2.1.1 创建存储库和用户成员2.1.2 为存储库添加访问人员2.2 客户端SVN基础使用2.2.1 在本地下载库中的内容2.2.2 版本文件操作--更…...

初识 Pynecone:构建现代化 Web 应用的 Python 框架

初识 Pynecone&#xff1a;构建现代化 Web 应用的 Python 框架 引言 在 Web 开发的世界里&#xff0c;Python 是后端开发的常客&#xff0c;但如果想用 Python 直接构建现代化的前端应用会怎样&#xff1f;这正是 Pynecone 框架的用武之地&#xff01;Pynecone 是一个全栈 Pyt…...

Go-RPC关键指标分析与企业实践

1.稳定性-保障策略 熔断&#xff1a;保护调用方 限流&#xff1a;保护被调用方 超时控制&#xff1a;避免浪费 2.稳定性-请求成功率&#xff08;用重复发送 负载均衡&#xff09; 3.稳定性-长尾请求&#xff08;用备份请求&#xff09; 4.稳定性-注册中间件 易用性&#xff1a…...

社交电商专业赋能高校教育与产业协同发展:定制开发AI智能名片及2+1链动商城小程序的创新驱动

摘要&#xff1a;本文围绕社交电商有望成为高校常态专业这一趋势展开深入探讨&#xff0c;剖析国家政策认可下其学科发展前景&#xff0c;着重阐述在专业建设进程中面临的师资短缺及实践教学难题。通过引入定制开发AI智能名片与21链动商城小程序&#xff0c;探究如何借助这些新…...

Ubuntu下安装Qt

1.如图1所示&#xff0c;在Index of /archive上下载安装包&#xff1b; 图1 2.将图1安装包下载好之后&#xff0c;通过共享文件夹的方式拷贝到ubutntu&#xff0c;如图2所示&#xff1b; 图2 3.如图3所示&#xff0c;执行chmod x qt-creator-opensource-linux-x86_64-10.0.2.…...

《FreeRTOS任务删除篇》

任务删除函数 源码1. 进入临界区1.1 第一步1.2 第二步1.3 第三步1.4 第四步 2. 获取待删除任务的任务控制块TCB3. 从就绪/延迟列表中删除任务4. 从事件列表中删除任务5. 如果待删除任务是当前运行的任务6. 如果待删除任务是其它任务7. 退出临界区7.1 第一步7.2 第二步7.3 第三步…...

取电快充协议芯片,支持全协议、内部集成LDO支持从UART串口读取电压电流消息

H004D 是一款支持全协议的受电端诱骗取电协议芯片&#xff0c;支持宽电压输入 3.3V~30V&#xff0c;芯片内部集成LDO&#xff0c;可输出 3.3V电压, 支持 通过UART 串口读取电压电流&#xff0c;支持定制功能&#xff0c;芯片采用QFN_20封装&#xff0c;线路简单&#xff0c;芯片…...

Linux:自定义Shell

本文旨在通过自己完成一个简单的Shell来帮助理解命令行Shell这个程序。 目录 一、输出“提示” 二、获取输入 三、切割字符串 四、执行指令 1.子进程替换 2.内建指令 一、输出“提示” 这个项目基于虚拟机Ubuntu22.04.5实现。 打开终端界面如图所示。 其中。 之前&#x…...

git 基础之 merge 和 rebase 的比较

在团队软件开发过程中&#xff0c;代码合并是一个基本且频繁执行的任务。 Git 提供了多种合并代码的策略&#xff0c;其中最常用的是 merge 和 rebase。 尽管二者的终极目标是相同的——整合代码变更——它们的方法和推荐的使用场景却有所区别。本文将详细介绍和比较这两种策…...

pve 磁盘选错位置修改

选中磁盘选择磁盘操作&#xff0c;移动存储 改到你要迁移的位置&#xff0c;迁移后原来的文件如果没选择删除源不会删除&#xff0c;需要确认数据没问题后选择相应的文件&#xff0c;如果有快照&#xff0c;快照可能也需要提前删除&#xff0c;删除前请做好备份。...

C语言第十二周课——有趣的小程序

目录 1.我是猪关机程序 1.1dos命令&#xff08;强制关机&#xff09; 1.2思路 1.3源码 2.猜数字 2.1介绍 2.2思路 2.3源码 1.我是猪关机程序 效果:运行程序后电脑在60s后关机&#xff0c;如果输入“我是猪”则取消关机&#xff1b;如果输入“你是猪”则立即关机&…...

【Linux学习】【Ubuntu入门】1-7 ubuntu下磁盘管理

1.准备一个U盘或者SD卡&#xff08;插上读卡器&#xff09;&#xff0c;将U盘插入主机电脑&#xff0c;右键点击属性&#xff0c;查看U盘的文件系统确保是FAT32格式 2.右键单击ubuntu右下角图标&#xff0c;将U盘与虚拟机连接 参考链接 3. Ubuntu磁盘文件&#xff1a;/dev/s…...

解决Windows + Chrome 使用Blob下载大文件时,部分情况下报错net:ERR_FAILED 200 (OK)的问题

背景&#xff1a; 部分线上用户反馈&#xff0c;下载文件会报错&#xff0c;但重启电脑又好了。测试无法复现。遂远程客户&#xff0c;发现在下载超过一定阈值大小的文件时&#xff0c;会报错。 但直接点击下载链接&#xff0c;可以正常下载 查阅代码&#xff0c;以前的写法是…...

SpringBoot多文件上传

多文件上传是在单文件上传的基础上修改而来&#xff0c;不了解单文件上传可以参考上一篇。以下在将修改部分展示如下&#xff1a; 一、修改upload.html文件&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title&g…...

Jenkins修改LOGO

重启看的LOGO和登录页面左上角的LOGO 进入LOGO存在的目录 [roottest-server01 svgs]# pwd /opt/jenkins_data/war/images/svgs [roottest-server01 svgs]# ll logo.svg -rw-r--r-- 1 jenkins jenkins 29819 Oct 21 10:58 logo.svg #jenkins_data目录是我挂载到了/opt目录&…...

幼儿园管理系统|Java|SSM|Vue| 前后端分离

【重要①】前后端源码万字文档部署文档 【重要②】正版源码有问题包售后 【包含内容】 【一】项目提供非常完整的源码注释 【二】相关技术栈文档 【三】源码讲解视频 【其它服务】 【一】可以提供远程部署安装&#xff0c;包扩环境 【…...

Unity 实现界面拖拽功能的脚本,通过IDragHandler 实现

using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems;namespace Assets.Scripts._1024 {class EVENTdome : MonoBehaviour, IPointerDownHandler, IBeginDragHandler, IDragHandler{//Unity 事件处理的几种方式//1 通过编辑…...

【042A】基于51单片机门禁系统【Proteus仿真+Keil程序+报告+原理图】

☆、设计硬件组成&#xff1a;51单片机最小系统RFID读卡器继电器蜂鸣器LED灯。 1、设计采用STC89C51/52、AT89C51/52、AT89S51/52作为主控芯片&#xff1b; 2、通过RC522读卡器读取IC卡信息&#xff0c;信息匹配继电器吸合门锁打开&#xff1b; 3、可通过上位机对IC卡进行注…...

数据库中的增删改查操作、聚合函数、内置函数、分组查询

数据库中的增删改查操作、聚合函数、内置函数、分组查询 CRUD简介Create 新增语法示例单⾏数据全列插⼊单⾏数据指定列插⼊多⾏数据指定列插⼊ Retrieve 检索语法⽰例构造数据 Select全列查询指定列查询查询字段为表达式为查询结果指定别名语法⽰例 结果去重查询 Order by 排序…...

递归------深度优先搜索

深度优先搜索&#xff08;Depth-First Search&#xff0c;简称DFS&#xff09;是一种用于遍历或搜索树或图的算法。它从一个顶点开始&#xff0c;尽可能深地搜索树的分支。深度优先搜索沿着一条路径深入&#xff0c;直到无法继续为止&#xff0c;然后回溯并尝试其他路径。这种搜…...