- 博客(33)
- 收藏
- 关注
原创 PID控制算法原理(抛弃公式,从本质上真正理解PID控制)
PID控制应该算是应用非常广泛的控制算法了。小到控制一个元件的温度,大到控制无人机的飞行姿态和飞行速度等等,都可以使用PID控制。这里我们从原理上来理解PID控制。PID(proportion integration differentiation)其实就是指比例,积分,微分控制。先把图片和公式摆出来,看不懂没关系。总的来说,当得到系统的输出后,将输出经过比例,积分,微分3种运算方式,叠加到输入中,从而控制系统的行为,下面用一个简单的实例来说明。
2024-07-26 11:38:54
1857
原创 PN结的电容效应——势垒电容和扩散电容
与Cb一样,Cd也具有非线性,它与流过PN结的正向电流i,温度的电压当量UT以及非平衡少子的寿命t有关。PN结处于平衡状态时的少子常称为平衡少子。当外加正向电压一定的时候,靠近耗尽层交界面的地方非平衡少子的浓度高,而远离交界面的地方浓度低,且浓度自高到底逐渐衰减,直至零。当外加正向电压增大时,非平衡少子的浓度增大且浓度梯度也增大,从外部看正向电流(即扩散电流)增大。当PN结外加的反向电压变化时,空间电荷区的宽度将随之变化,即耗尽层的电荷量随外加电压而增大或减小这种现象与电容器的充放电过程相同,如图所示。
2024-07-17 11:22:52
7337
原创 雪崩击穿与齐纳击穿
在低掺杂的情况下,耗尽层宽度较宽,那么低反向电压下不会产生齐纳击穿。当反向电压增加到较大数值时,耗尽层的电场使少子加快漂移速度,从而与共价键中的价电子相碰撞,把价电子撞出共价键,产生电子-空穴对。在高掺杂的情况下,因耗尽层宽度很窄,不大的反向电压就可以在耗尽层形成很强的电场,而直接破坏共价键,使价电子破坏共价键的束缚,产生电子-空穴对,致使电流急剧增大,这种击穿称为齐纳击穿。可见齐纳击穿电压较低。当二极管两端的反向电压超过一定数值U(BR)后,二极管两端的反向电流也会急剧增加,这种情况下我们称为。
2024-07-17 09:34:22
1666
原创 为什么RS232通信-15V是1,+15V是0,原因是什么
负电平被视为逻辑1,因为在旧式的电缆中,负电平相对于地线(地电位)更容易稳定地传输。因此,采用负电平来表示逻辑1,可以减少通信中的误码率,并提高通信的可靠性。RS-232通信中的逻辑电平规定是比较特殊的,通常我们认为逻辑1对应于高电平,逻辑0对应于低电平。然而,RS-232却是相反的,即逻辑1对应于负电平(-15V),逻辑0对应于正电平(+15V)虽然这种正负电平的表示方法在现代通信中已经不再普遍使用,但在一些特定的应用场景中,仍然可以见到RS-232通信的身影,特别是在一些老式设备或特殊领域的通信中。
2024-02-12 02:46:15
640
原创 STM32F103中时钟周期等于机器周期吗
在STM32F103微控制器中,时钟周期通常指的是CPU时钟周期,即处理器核心的时钟周期,其频率由外部时钟源提供并由内部时钟分频器分频。机器周期在这种微控制器上通常用来描述执行一条指令所需的时间,而一条指令的执行可能需要多个时钟周期。例如,对于STM32F103系列微控制器,大多数指令需要一个机器周期来执行,但也有一些复杂的指令需要多个机器周期。因此,虽然时钟周期和机器周期在某种程度上相关,但它们并不完全相等。机器周期更多地与指令执行相关,而时钟周期更多地与处理器的时钟频率和时钟信号有关。
2024-02-10 23:18:49
528
原创 IRQ是什么意思?
处理器在接收到中断请求后,会中断当前执行的指令流程,保存当前上下文,然后转去执行相应的中断服务程序。中断服务程序完成后,处理器会恢复之前的上下文,继续执行原来的程序。中断是一种异步事件,可以打断处理器当前的执行流程,以执行一个特定的中断服务程序(Interrupt Service Routine,ISR)来处理特定事件。中断是一种在无需处理器主动轮询的情况下,及时响应外部事件的机制,因此在嵌入式系统和实时系统中得到广泛应用。
2024-02-02 22:59:57
1483
原创 NVIC_IRQChannel是什么?
在 STM32 中,`NVIC_IRQChannel` 是一个成员变量,通常属于一个结构体,例如在你之前提供的 `NVIC_InitTypeDef` 结构体中。例如,对于USART1的中断,`NVIC_IRQChannel` 的值可能是 `USART1_IRQn`,对应着USART1的中断处理函数。这是一个用于配置中断的参数,通常用于在配置中断优先级和使能或禁用中断时标识特定的中断通道。在配置中断时,你需要设置 `NVIC_IRQChannel` 的值以指定要配置的中断通道。
2024-02-02 22:57:47
2284
原创 STM32按键检测函数的编写
函数返回类型为无符号8位整数,表示按键扫描的结果。可能返回1,表示按键松开。:进入一个循环,该循环在按键被按下的情况下一直执行。这是一个等待松手的过程。:判断按键是否被按下,如果按下(输入为高电平),则进入条件判断。:在检测到按键被松开时,函数立即返回1,表示按键已经松开。在未检测到按键按下,函数返回0,表示按键已经未被摁下。:函数的名称,用于扫描按键状态。表示 GPIO 端口类型,表示 GPIO 引脚号。
2024-01-10 15:23:44
631
1
原创 STM32GPIO输出,使用固件库点亮LED
具体来说,如果两个对应位中至少有一个位为1,则结果的对应位也为1,否则为0。这个程序的基本逻辑是通过循环,在每个循环中点亮 LED,然后进行延时,接着熄灭 LED,再进行延时,如此循环。总体来说,这段代码是配置了一个GPIO端口,将其设置为推挽输出模式,速度为50MHz,并将指定的引脚设置为高电平,用于点亮LED灯。:这里用到了按位或的操作“|”将 三组数据合并成一组二进制数据,使得一次将多个LED 端口的引脚置为低电平,熄灭 LED。:设置要配置的GPIO引脚,LED的三个颜色对应的引脚。
2024-01-10 14:18:54
915
原创 STM32固件库中的__IO与uint32_t
是一个宏,通常在嵌入式系统中用来定义一个“易失性”(volatile)变量。在嵌入式系统编程中,有时候需要确保编译器不对某些变量进行优化,以防止在编译过程中删除看似无用但实际上是关键的变量。是一个全局或静态变量,并且在任何地方没有显式的赋值语句,那么它的初始值将是0。如果它是一个局部变量,则它的初始值将是未定义的,这意味着它可能包含任何值。在C语言中,未显式初始化的全局或静态变量的初始值通常是零(0)。易失性表明该变量可能会在程序执行中的意外情况下被改变,因此编译器应该小心处理它,不要进行优化。
2024-01-10 13:48:30
2786
原创 C语言需要把变量的定义放在{}的开头吗?为什么?
在编译单元级别,C编译器需要在编译时了解所有变量的类型和大小,以便正确地分配内存和生成有效的机器代码。在C语言的函数中,变量的定义必须出现在块的开头,而不是在块的中间或结尾。这是因为在C语言中,变量的定义在编译时会被处理,并在程序执行过程中分配相应的内存空间。将变量的定义放在块的开头有助于明确定义变量的作用域,并确保在整个块中都可以访问变量。在C语言中,变量的定义必须在函数体内的块的开头,而不是在块的中间或结尾。是在一个额外的代码块内定义的变量,这说明变量的作用域可以限定在特定的块内。
2023-12-30 16:13:26
1705
原创 STM32F103,GPIO_SetBits()函数和GPIO_RestBits()函数的编写
GPIO_RestBits()函数的编写使得main.c中可以直接使用 GPIO_RestBits()函数来控制GPIO引脚输出低电平。GPIO_SetBits()函数的编写使得main.c中可以直接使用 GPIO_SetBits()函数来控制GPIO引脚输出高电平。其中GPIO_Speed()函数的编写使得,main.c中可以直接使用GPIO_Speed()来完成配置输出输入模式以及输出速度。
2023-12-30 01:55:41
1997
1
原创 STM32寄存器结构体定义(GPIOB和RCC结构体编写)
是C语言的一个关键字,用于为已有的数据类型或自定义的数据类型(如结构体、枚举等)创建一个新的类型名。上面那段代码是STM32嵌入式系统的寄存器映射和结构体的使用。的结构体类型,该结构体包含了7个成员,每个成员都是32位的无符号整数(,之后可以使用这个别名来声明结构体类型的变量。这是一个典型的C语言结构体的定义,其中使用了。用于为后面的结构体定义创建了一个新的类型名。: 这里定义了一个无名的结构体,包含了多个。关键字后面跟着的是新类型的名字,这里是。,它成为了这个结构体类型的别名。这个结构体类型的别名是。
2023-12-28 12:56:30
1570
1
原创 手撕STM32F103寄存器映射
这里APB2PERIPH_BASE为第二个高性能总线(APB2)的寄存器基地址,它在STM32F103的存储器映射表中,在基地址的基础上(将地址(GPIOB_BASE+0x00)强制类型转换为指针使用 * 过指针解引用操作,访问 GPIOB_BASE+0x00地址上的值。将地址(GPIOB_BASE+0x0C)强制类型转换为指针使用 * 过指针解引用操作,访问 GPIOB_BASE+0x0C地址上的值。是属于第一个高性能总线 (APB1) 的寄存器的基地址,那么通过这样的宏定义,你可以在代码中使用。
2023-12-26 20:24:28
2326
1
原创 STM32端口输入\输出寄存器
在 STM32 微控制器中,"ODR 寄存器" 通常指的是 GPIO(通用输入输出)端口的输出数据寄存器。这个寄存器用于控制 GPIO 引脚的输出状态,允许您设置(置位)或清除(复位)单个或多个引脚的输出状态。"BSRR" 表示 "Bit Set Reset Register",它可以分为两个部分:高位部分用于设置(置位)引脚,低位部分用于复位引脚。通常,通过设置 ODR 寄存器的特定位,您可以将相应引脚设置为高电平(1)或低电平(0),从而打开或关闭连接到该引脚的外部设备。
2023-12-26 07:57:44
1339
2
原创 时钟树HSE与HSI
在嵌入式系统和微控制器中,HSE(High-Speed External)和HSI(High-Speed Internal)通常是与时钟相关的术语,用于描述系统时钟源。这两者是针对STM32系列微控制器的术语,这是由STMicroelectronics生产的一系列32位ARM Cortex-M微控制器。在STM32系列微控制器中,你可以通过寄存器设置来选择使用HSE还是HSI作为系统时钟源,并配置相应的时钟分频等参数。当然,具体的配置可能会根据具体的微控制器型号和厂商的不同而有所差异。
2023-12-25 17:22:40
2514
2
原创 *(unsigned int*)(0x40010c0c)
需要注意的是,这样的代码通常是与底层系统编程、嵌入式系统或硬件相关的代码一起使用,而不是通用的应用程序代码。在普通应用程序中,直接引用内存地址通常是不安全的,并且应该避免使用。内存地址的具体值在不同的计算机体系结构和操作系统之间可能会有很大的差异。直接引用内存地址的代码可能不具有跨平台性,并且在不同的环境中表现不同。直接引用内存地址的代码容易受到安全漏洞的影响,例如缓冲区溢出攻击。这样的代码缺乏文档性,并且很难为其他开发人员或自己在未来的时间理解。是指针解引用操作符,它用于访问指针所指向的内存位置的值。
2023-12-08 11:15:14
1236
2
原创 keil5软件STM32F103芯片Flash Download为什么是128K和512K,它们之间如何转换的问题
我尝试过从STM32F103ZET6的模板程序中替换启动文件发现并没有,最后发现是芯片选型的问题。例如当前选择的是STM32C8T6型号,则Flash自动显示128K。同理512K变成128K也是如此,变成其他的芯片也是如此。为什么会出现有些时候是128K有些时候是512K的区别?假如程序要在STM32ZET6上运行,怎么改成512K呢。在用Keil5下载程序的时候需要选择具体芯片的内存大小。找到STM32ZET6点击后再点最下面的OK即可。这样Flash就变成512K了。
2023-11-29 10:16:31
1818
6
原创 KEY按钮的初始化函数的编写以及按键开关灯
将返回值和KEY_ON比较,KEY1被按下则让RGB灯的红色亮起,KEY2按键被按下则让RGB灯的红色熄灭,这是一个按键轮询检测的基本框架和原理,可以通过这个框架继续添加许多代码实现各种功能。总的来说,这段代码的目的是根据传入的按键类型,在不同的引脚上进行初始化配置,确保相应的外设时钟已经被启用,并设置引脚为悬空输入模式,在这个框架上可以继续很方便快捷的扩展按键的初始化程序。总的来说,这段代码的作用是检测给定的GPIO引脚上的按键状态。如果条件判断的结果为假,即按键没有被按下,那么将执行这里的代码块。
2023-08-11 11:07:57
1272
1
原创 STM32F103单个按键按键检测函数的编写以及介绍
总之,这段代码是用来初始化一个 GPIO 引脚作为按键输入的配置。它首先使能了 GPIOA 外设的时钟,然后配置了 GPIO 引脚的工作模式为浮空输入模式(表示未连接任何电平时的状态)。这样,你就可以通过读取这个 GPIO 引脚的状态来检测按键的按下。这是一个函数的声明,表明这是一个没有参数和返回值的函数,用于配置按键所用的 GPIO 引脚。它会检测 GPIOA 引脚 Pin 0 的状态,如果按键被按下且消抖结束,这是一个条件语句,它检查 GPIOA 的 Pin 0 是否为高电平(1)。
2023-08-11 08:24:32
1152
1
原创 手写stm32f103RGB初始化程序(2)
是枚举的三个值,分别表示红色、绿色和蓝色的 LED 类型。你可以通过这些符号来指定你希望初始化和控制的不同颜色的 RGB LED。,用于表示不同颜色的 RGB LED 类型。枚举类型是一种用户自定义的数据类型,它允许你在代码中使用易读的符号来代表特定的值。通过使用枚举类型,可以提高代码的可读性和易用性,因为使用可读的符号比使用数字更加直观和易于理解。宏与led.h定义的宏相对应,用于将指定的颜色引脚设置为低电平,以避免初始化引脚时灯亮起。这段代码用于初始化不同颜色的 RGB LED,并在初始化后将其熄灭。
2023-08-08 05:30:46
273
1
原创 手写stm32f103RGB初始化程序(1)
结构体的成员,以配置对应颜色 LED 的引脚参数。具体包括引脚编号(Pin)、引脚模式(Mode)、输出速度(Speed)等。包含了一个名为 "led.h" 的头文件,可能是用于定义相关的宏、函数声明或其他内容。函数用于设置对应引脚输出高电平,通过电路原因,避免 LED 在初始化引脚时亮起。分别对应红色 LED、绿色 LED 和蓝色 LED 引脚的初始化。在每个初始化函数中,首先声明了一个对应颜色的。是红色 LED 引脚的初始化结构体变量)。函数来初始化对应颜色 LED 的引脚,
2023-08-08 04:23:42
299
1
原创 在STM32F103ZET6上实现RGB控制与流水灯效果
将这三个宏的值组合在一起时,对应的位会进行逻辑或运算,形成一个新的二进制数。是一个宏,它表示用于连接绿色LED的GPIO引脚(GPIOB Pin 0)所对应的时钟使能位。将绿色LED所连接的GPIO引脚的时钟使能,从而使得该GPIO引脚可以正常工作。: 这也是一个函数调用,用于将绿色LED引脚的状态设置为高电平,即将引脚置为灭。这是我板子上的RGB灯的引脚图,可以看到对应的引脚配置成0,对应的灯即可亮起。: 这是一个函数调用,用于将绿色LED引脚的状态设置为低电平,即将引脚置为亮。
2023-08-03 02:23:54
3047
原创 ST标准库:src文件夹与inc文件夹
src和inc文件夹里面是ST公司针对每个STM32外设而编写的库函数文件,每一个外设对应一个.c和.h后缀的文件。当你在自己的代码中需要使用标准库的功能时,你需要在代码中包含相应的头文件。这样的设计使得标准库的实现和使用分离开来,方便开发者在自己的代码中使用这些功能,而不需要了解标准库的底层实现细节。在C编程中,ST标准库通常指的是标准库(Standard Library),也就是提供的一组常用功能的函数和头文件。文件夹:这个文件夹通常包含标准库的源代码文件,即标准库函数的实现代码。
2023-08-03 01:52:01
2170
原创 STM32固件库文件分析
startup_stm32f10x_hd.s:设置堆栈指针、设置PC指针、初始化中断向量表、配置系统时钟、对用C库函数_main最终去到C的世界。#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h>stm32f10x_xx.h:存放外设的初始化结构体,外设初始化结构体成员的参数列表,外设固件库函数的声明。stm32f10x.h:实现了内核之外的外设的寄存器映射。stm32f10x_xx.c:外设的驱动函数库文件。5-头文件的配置文件。
2023-07-31 04:14:46
86
1
原创 #268: declaration may not appear after executable statement in block GPIO_InitTypeDef GPIO_InitSt
错误是:变量 "GPIO_InitStructure" 的声明出现在可执行语句块中,这是不允许的。在C语言中,变量的声明必须在代码块的开始处,不能在可执行语句之后。在上面的例子中,我们将变量 "GPIO_InitStructure" 的声明放在了代码块的开始处,并在后续的代码中使用了这个变量,从而消除了错误和警告。为了解决这个问题,您需要将变量 "GPIO_InitStructure" 的声明放在可执行语句之前,并确保在后续的代码中使用了这个变量。
2023-07-26 01:19:32
3675
1
原创 GPIO初始化结构体和初始化函数中,enum枚举定义的结构体来限定Speed的模式(只有三种),Mode的模式(有八种)
定义完位操作函数后,控制GPIO输出电平的代码得到了简化,但在控制GPIO输出电平前还需要初始化GPIO引脚的各种模式,这部分代码涉及的寄存器很多,我们希望初始化GPIO也能以如此简单的方法去实现。设计这个结构体的思路是,初始化GPIO前,先定义一个这样的结构体变量,根据需要配置GPIO的模式,对这个结构体的各个成员进行赋值,如何把这个变量作为“GPIO初始化函数”的输入参数,该函数能根据这个变量值中的内容去配置寄存器,从而实现GPIO的初始化。也就是说配置了第一个值后,它后面的值都会依此类推加一。
2023-07-25 21:18:00
443
原创 通过STM32F10x中文参考手册的端口位设置/清除寄存器,与端口位清除寄存器,进行GPIO_SetBits(),GPIO_ResetBits()函数的编写
因为我们写的是GPIO_SetBits()只需要置高就可以了,所以按照STM32F10x中文参考手册,端口位设置/清除寄存器的说明可以看到,0-15位是置高的,16-31是置低的,所以我们只用到了0-15低16位,所以数据类型就用uint16_t来定义刚刚好(占2个字节)。这样的位操作是常见的,它允许在一个寄存器中同时设置多个引脚的状态,而不影响其他引脚的状态。的某一位为1,表示设置对应的 GPIO 引脚为高电平,在stm32f10x_gpio.h里我们定义了每一个引脚所对应的十六进制值。
2023-07-25 00:26:35
1782
原创 关于为什么要有#ifndef预处理器指令
对于用户定义的标识符,通常建议使用单个下划线或字母开头,并尽量避免使用两个下划线开头,以免与编译器或库定义的标识符冲突。总的来说,大写字母作为宏名称是一种常见的编程约定,有助于提高代码的可读性和可维护性,特别是在使用预定义宏的情况下。保留标识符:C/C++语言规范中规定了一些保留的标识符,这些标识符用于特定的目的,并在编程中不应该用作用户定义的标识符。通过使用双下划线开头,这个宏名称更不容易与其他自定义标识符冲突,因为在C/C++中,双下划线通常被认为是保留的或者是与编译器或库相关的特殊标识符。
2023-07-24 22:44:50
452
原创 stm32f10x_gpio.c(1): warning: #1-D: last line of file ends without a newline
总的来说,文件末尾添加换行符是一种良好的编程习惯,可以避免潜在的问题,并使代码更加整洁、可读性更高。虽然在某些情况下缺少换行符可能不会导致实际问题,但是为了保持一致性和遵循最佳实践,建议在文件末尾添加一个换行符。兼容性:在某些编程语言和操作系统中,文件末尾没有换行符可能会导致一些问题,特别是在处理文件时。例如,在Unix/Linux系统中,如果文件末尾没有换行符,一些文本处理工具可能会不正确地处理最后一行。在很多编程语言和操作系统中,文件的最后一行通常应该以一个换行符结尾,这是一种良好的编程实践。
2023-07-24 22:18:45
999
原创 STM32寄存器结构体定义
因为unit32_t是32位的,也就是四个字节,CRL就从GPIOB_BASE的地址开始占四个字节的位置,CRH存放的地址就自动+4个字节了,正好是偏移量,就免去了每次都用#define去根据基地址去偏移了。这个表达式的作用是将GPIOB外设的基地址转换为指向该外设的结构体指针,使得程序可以通过指针访问该外设的寄存器,并进行相关的控制和配置。: 这是一个类型名称,是在特定的微控制器或嵌入式系统中定义的结构体类型,用于表示GPIO外设的寄存器映射。类型的指针,可以将该地址解释为GPIO外设的寄存器映射结构。
2023-07-24 00:28:52
1023
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人