STM32——使用TIM输出比较产生PWM波形控制舵机转角
一、输出比较简介:
只有高级定时器和通用寄存器才有输入捕获/输出比较电路,他们有四个CCR(捕获/比较寄存器),共用一个CNT(计数器),而输出比较功能是用来输出PWM波形的。


红圈部分就是输出比较电路,其中CCR(捕获/比较寄存器)是输入捕获和输出比较共用的,输入捕获和输出比较不能同时进行,当我们进行输出比较时,它就是比较寄存器,我们可以给这个寄存器设定一个值,然后CNT计数器就会不停和这个值进行比较,根据比较结果会输出不同的电平信号(通过输出比较控制器控制,下文讲解),由此可以产生PWM信号,如下图。

二、PWM简介:
PWM的本质就是一种方法(PWM波形是一种数字信号),通过输出一段变化的波形,这个信号是一个脉冲信号,因为它只有高电平(这是逻辑电平由控制器决定,32是3.3v而51是5v)和低电平(0),而高电平就是脉冲信号,其所占整个周期的比例就是脉冲宽度,通过调整脉冲宽度就能够得到不同的模拟信号,例如右图得到一个近似的正弦信号。而任何信号都可以看作是由一系列的正弦信号合成的。

PWM(Pulse Width Modulation) 是一种模拟信号的数字化处理方式,通过微处理器的数字输出来对模拟电路进行控制。它通过对一系列脉冲的宽度进行调制,来等效地获得所需要的波形(含形状和幅值),从而达到调整电压和频率的目的。PWM广泛应用于从测量、通信到功率控制与变换的许多领域中,特别在电机控制中表现出色。
-
频率
定义:PWM频率是指1秒钟内信号从高电平到低电平再回到高电平的次数,即一秒钟内PWM的周期数。频率越快,其模拟的信号越平稳。 -
占空比
定义:占空比是一个脉冲周期内,高电平的时间与整个周期时间的比例。占空比等效为PWM波形等效出来的模拟信号的电压的大小,占空比越大,模拟信号的越趋近于高电平,反之就是趋近于低电平,等效关系一般是线性的。例如高电平是5v,占空比是50%,那模拟信号的电压就近似为2.5v。
单位:%(0%-100%) -
分辨率
就是例如,占空比以1% 2% 3% 4%…99% 100%这样的情况跳变,那么占空比的变化步距就是1%,因为上述占空比每一次变化就是加1%,这种变化步距越小,说明变化的越细腻。
总结:
- 1.PWM是一种方法,采用这个方法输出PWM波形是为了使数字输出端口(只能输出高电平和低电平两种,用于控制电机就是只能让它转或者停止)输出模拟信号,这样就能够实现电机调速、控制舵机的转动角度等等。
- 2.输出比较电路可以说是实现PWM的工具:
(1)如果CRR捕获/比较寄存器的值(红线),ARR自动重装器的值(下图黄线),蓝线就是计数器值的变化,那么黄线和红线之间的差距越小,低电平所占时间就会越短,占空比就越大,通过跳帧占空比,如果是电机,占空比越大转速越快。
(2)占空比可以看作CRR的值比ARR的值。注意这里到30就已经是低电平了,所以高电平的范围是(0~29)30个数。
(3)我们如果让CCR的值每次操作加1,那么占空比每次就加1%,分辨率就是1%。

三、通用定时器的输出比较模块如何输出PWM波形:

上图对应的就是下图电路,红色部分输出比较结果OC1REF(reference参考信号),蓝色部分根据比较结果输出比较信号OC1,最后通过黄色部分TIMx_CH1通道输出到GPIO引脚上。


1.CNT和CRR两个寄存器的值进行比较之后,其比较结果进入输出模式控制器,然后根据结果输出模式控制器会输出相应的电平OC1_ref
2.信号OC1_ref分别可以进入两条支路,一路进入主模式控制器就能够作为触发输出TRGO输出给其他定时器或者DA/DC转换
3.另一路就进入极性选择器TIMx_CCER,极性选择器置0则信号走上一路不做变换直接输出到输出使能电路,如果置1则让它走下支路可以使信号OC1_ref经过一个非门电路将其反转,高变低,低变高
4.然后再控制输出使能让其通过OC1引脚输出到GPIO引脚上,至于是哪个GPIO可以看引脚定义图

(1)输出比较控制器执行逻辑:

通过配置下图红圈的寄存器可以选择不同的模式:

四、H桥电路:
这是我在抖音搜索的,而输出比较电路一般就接一个这样的电路,这个能够实现电机的正转和反转,中级的圆圈M就代表电机。

1. 当Q1和Q4导通,当Q2和Q3截止,那么电流从电机的正极流入负极流出,电机正转
2. 当Q2和Q3导通,当Q1和Q4截止,那么电流从电机的负极进入正极流出,电机反转

五、高级定时器的输出比较电路:
高级定时器的输出比较电路比通用定时器的输出比较电路多了一个死区生成电路,之后会讲解这个电路的作用。
首先,这个电路一般会接一个H桥电路

(1)死区生成电路的作用:
- 由于如果接H桥电路,那么对于H桥电路的半桥就是左半边或者由半边,一个MOS管导通另一个MOS管就必须截止,如果同时导通或者截止就会出现问题,那么死区生成电路就是产生一段时间的死区,死区生成电路中的“死区”通常指的是在输入信号进入某个特定范围(即死区)时,电路的输出电压为零;当输入信号脱离这个范围时,电路的输出电压会随输入信号的变化而变化。这个特定范围就是死区。 所以为了防止在半桥电路中,上面MOS管还没完全关断下面的MOS管就已经导通从而出现的两个MOS管同时导通的情况(会产生功率损耗,引起器件发热)就设置了一个死区生成电路,它会在上管关断之后延迟一段时间菜导通下管,保证半桥电路中保持一个MOS管导通另一个MOS管截止的状态。
六、舵机和电机:
(1)舵机:

在这里插入图片描述
(2)电机:

注意:
逻辑电平是由控制器决定,例如32单片机为3.3v,89c51单片机为5v

七、引脚定义:
- STM32F103C8T6芯片的引脚定义如下图,例如我们代码中要使用的TIM2_OC1就是被默认接在PA0口,但是如果我要用的两个输出通道都被定义在了同一个GPIO口上,就能够通过重映射的功能将其中一个换到另一个引脚上,但不是所有的输出通道都能更换,只有具有重定义功能也就是下图中最右边一列,例如红圈中的TIM2_CH3通道就可以输出到PA2引脚或者PB10引脚上,如果你要使用ADC12_IN2又要使用TIM2_CH3,那么就可以将TIM2_CH3重映射到PB10引脚。

八、复用开漏/推挽输出:
- 首先我们看一下普通的开漏/推挽输出,这个GPIO在这个模式下,其输出电平是根据输出数据寄存器的值决定的,也就是我们给这个输出数据寄存器写什么值,对应就会输出什么电平。

- 再来看复用开漏/推挽输出模式,这个模式下输出数据寄存器和GPIO的输出控制模块是断开的,输出控制模块与单片机的外设连接,在我们这个示例中就是与TIM2_CH1连接,这时GPIO输出的电平由TIM2_CH1通道传输过来的电平信号决定。

九、引脚重映射:
(1)方法:
这里要用到AFIO,关于AFIO的库函数被包含在GPIO的文件中。
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
/*** @brief Changes the mapping of the specified pin.* @param GPIO_Remap: selects the pin to remap.* This parameter can be one of the following values:* @arg GPIO_Remap_SPI1 : SPI1 Alternate Function mapping* @arg GPIO_Remap_I2C1 : I2C1 Alternate Function mapping* @arg GPIO_Remap_USART1 : USART1 Alternate Function mapping* @arg GPIO_Remap_USART2 : USART2 Alternate Function mapping* @arg GPIO_PartialRemap_USART3 : USART3 Partial Alternate Function mapping* @arg GPIO_FullRemap_USART3 : USART3 Full Alternate Function mapping* @arg GPIO_PartialRemap_TIM1 : TIM1 Partial Alternate Function mapping* @arg GPIO_FullRemap_TIM1 : TIM1 Full Alternate Function mapping* @arg GPIO_PartialRemap1_TIM2 : TIM2 Partial1 Alternate Function mapping* @arg GPIO_PartialRemap2_TIM2 : TIM2 Partial2 Alternate Function mapping* @arg GPIO_FullRemap_TIM2 : TIM2 Full Alternate Function mapping* @arg GPIO_PartialRemap_TIM3 : TIM3 Partial Alternate Function mapping* @arg GPIO_FullRemap_TIM3 : TIM3 Full Alternate Function mapping* @arg GPIO_Remap_TIM4 : TIM4 Alternate Function mapping* @arg GPIO_Remap1_CAN1 : CAN1 Alternate Function mapping* @arg GPIO_Remap2_CAN1 : CAN1 Alternate Function mapping* @arg GPIO_Remap_PD01 : PD01 Alternate Function mapping* @arg GPIO_Remap_TIM5CH4_LSI : LSI connected to TIM5 Channel4 input capture for calibration* @arg GPIO_Remap_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping* @arg GPIO_Remap_ADC1_ETRGREG : ADC1 External Trigger Regular Conversion remapping* @arg GPIO_Remap_ADC2_ETRGINJ : ADC2 External Trigger Injected Conversion remapping* @arg GPIO_Remap_ADC2_ETRGREG : ADC2 External Trigger Regular Conversion remapping* @arg GPIO_Remap_ETH : Ethernet remapping (only for Connectivity line devices)* @arg GPIO_Remap_CAN2 : CAN2 remapping (only for Connectivity line devices)* @arg GPIO_Remap_SWJ_NoJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST* @arg GPIO_Remap_SWJ_JTAGDisable : JTAG-DP Disabled and SW-DP Enabled* @arg GPIO_Remap_SWJ_Disable : Full SWJ Disabled (JTAG-DP + SW-DP)* @arg GPIO_Remap_SPI3 : SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices)* When the SPI3/I2S3 is remapped using this function, the SWJ is configured* to Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST. * @arg GPIO_Remap_TIM2ITR1_PTP_SOF : Ethernet PTP output or USB OTG SOF (Start of Frame) connected* to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices)* If the GPIO_Remap_TIM2ITR1_PTP_SOF is enabled the TIM2 ITR1 is connected to * Ethernet PTP output. When Reset TIM2 ITR1 is connected to USB OTG SOF output. * @arg GPIO_Remap_PTP_PPS : Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices)* @arg GPIO_Remap_TIM15 : TIM15 Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_TIM16 : TIM16 Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_TIM17 : TIM17 Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_CEC : CEC Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_TIM1_DMA : TIM1 DMA requests mapping (only for Value line devices)* @arg GPIO_Remap_TIM9 : TIM9 Alternate Function mapping (only for XL-density devices)* @arg GPIO_Remap_TIM10 : TIM10 Alternate Function mapping (only for XL-density devices)* @arg GPIO_Remap_TIM11 : TIM11 Alternate Function mapping (only for XL-density devices)* @arg GPIO_Remap_TIM13 : TIM13 Alternate Function mapping (only for High density Value line and XL-density devices)* @arg GPIO_Remap_TIM14 : TIM14 Alternate Function mapping (only for High density Value line and XL-density devices)* @arg GPIO_Remap_FSMC_NADV : FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices)* @arg GPIO_Remap_TIM67_DAC_DMA : TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices)* @arg GPIO_Remap_TIM12 : TIM12 Alternate Function mapping (only for High density Value line devices)* @arg GPIO_Remap_MISC : Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, * only for High density Value line devices) * @param NewState: new state of the port pin remapping.* This parameter can be: ENABLE or DISABLE.* @retval None*/
(1)第一个参数是重映射的模式,这个可以参考手册
如果我们想将TIM2_CH1_ETR从PA0改成PA15就可以选择第一个部分重映像或者完全重映像

那么就对应:
GPIO_PartialRemap1_TIM2 //TIM2 Partial1 Alternate Function mapping
或者
GPIO_FullRemap_TIM2 // TIM2 Full Alternate Function mapping
但是注意,PA15的主功能是作为调试端口JTDI,也就是上电之后其默认为调试端口JTDI,还需要先关闭它调试端口的复用,才能够让它作为普通的GPIO口或复用定时器通道。

(2) 关闭引脚调试功能:
使用的还是GPIO_PinRemapConfig函数:
根据下面这几个参数能够实现
* @arg GPIO_Remap_SWJ_NoJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST* @arg GPIO_Remap_SWJ_JTAGDisable : JTAG-DP Disabled and SW-DP Enabled* @arg GPIO_Remap_SWJ_Disable : Full SWJ Disabled (JTAG-DP + SW-DP)
这几个参数对应的情况可以查看手册:

因此我们选择:
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
如果你把所有调试功能的引脚都关闭你就下载不了程序了。不会的不要这么干
十、参数计算:
推荐参数:
ARR = 20K + 1
PSC = 72 + 1
CCR = 500 ~ 2500 对应0° ~ 180°
//ARR自动重装器的值TIM_TIM2_InitStructure.TIM_Period = 20000 - 1;//ARR//PSC预分频器的值TIM_TIM2_InitStructure.TIM_Prescaler = 72 - 1;//PSC

七、采用PWM输出信号控制电机程序实现:
总代码:
主函数在第七步
示例中只让舵机转到0°位置,理解后可以通过TIM_SetCompare1函数结合按键或者其他外设更改CCR的值从而实现不同角度的转换。

#include "stm32f10x.h" // Device header//初始化舵机
void Steering_EngineInit(void)
{//RCC打开TIM2、GPIO、AFIO的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//引脚重映射GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);//关闭PA15的调试功能,之后TIM2_CH1就由PA0->PA15GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//初始化GPIOA15:GPIO_InitTypeDef GPIO_PA15_InitStructure;GPIO_PA15_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_PA15_InitStructure.GPIO_Pin = GPIO_Pin_15;GPIO_PA15_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_PA15_InitStructure);//PB1:GPIO_InitTypeDef GPIO_PB1_InitStructure;GPIO_PB1_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_PB1_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_PB1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_PB1_InitStructure);//选择时钟源TIM_InternalClockConfig(TIM2);//配置时基单元//初始化定时器2时基单元的结构体TIM_TimeBaseInitTypeDef TIM_TIM2_InitStructure;/*TIM_ClockDivision 是这个结构体中的一个字段,用于设置定时器的时钟分频。具体来说,它决定了定时器时钟(TIMxCLK)的频率与内部时钟(CK_INT)之间的关系。TIM_CKD_DIV1 表示不进行分频,即 CK_INT = TIMxCLK。换句话说,定时器的内部时钟频率与输入的定时器时钟频率相同。*/TIM_TIM2_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//计数器模式:选择向上计数模式TIM_TIM2_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;//ARR自动重装器的值TIM_TIM2_InitStructure.TIM_Period = 20000 - 1;//ARR//PSC预分频器的值TIM_TIM2_InitStructure.TIM_Prescaler = 72 - 1;//PSC//重复计数器的值,高级计数器才有TIM_TIM2_InitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TIM2_InitStructure);//配置输出比较单元CCR:TIM_OCInitTypeDef TIM_OCInitStructure;//给TIM2_CH1的初始化结构体先进行一次初始化把用不到的关于高级定时器的成员也初始化//然后再对要用到的成员变量进行更改TIM_OCStructInit(&TIM_OCInitStructure);//输出比较模式TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较极性//高极性 = 极性不反转;低极性反之,这里选的高极性TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;//输出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//CCR比较寄存器的值TIM_OCInitStructure.TIM_Pulse = 0;//CCRTIM_OC1Init(TIM2, &TIM_OCInitStructure);//启动定时器TIM_Cmd(TIM2,ENABLE);}
void PWM_SetCompare(uint16_t compare)
{TIM_SetCompare1(TIM2,compare);
}
实现步骤:

第一步:使用RCC开启外设的时钟
这里涉及GPIO、AFIO、TIM2三个外设。
//RCC打开TIM2、GPIO、AFIO的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
第二步:配置好时基单元还有时钟源选择
//选择时钟源TIM_InternalClockConfig(TIM2);//配置时基单元//初始化定时器2时基单元的结构体TIM_TimeBaseInitTypeDef TIM_TIM2_InitStructure;/*TIM_ClockDivision 是这个结构体中的一个字段,用于设置定时器的时钟分频。具体来说,它决定了定时器时钟(TIMxCLK)的频率与内部时钟(CK_INT)之间的关系。TIM_CKD_DIV1 表示不进行分频,即 CK_INT = TIMxCLK。换句话说,定时器的内部时钟频率与输入的定时器时钟频率相同。*/TIM_TIM2_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//计数器模式:选择向上计数模式TIM_TIM2_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;//ARR自动重装器的值TIM_TIM2_InitStructure.TIM_Period = 20000 - 1;//ARR//PSC预分频器的值TIM_TIM2_InitStructure.TIM_Prescaler = 72 - 1;//PSC//重复计数器的值,高级计数器才有TIM_TIM2_InitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TIM2_InitStructure);
第三步:配置输出比较单元
注意:
这里提醒一下输出使能部分:TIM_OCInitStructure.TIM_OutputState
和
TIM_OCInitStructure.TIM_OutputNState
的区别只有一个N,但是加了N的是高级定时器的部分,所以这里错了舵机会不动。
//配置输出比较单元CCR:TIM_OCInitTypeDef TIM_OCInitStructure;//给TIM2_CH1的初始化结构体先进行一次初始化把用不到的关于高级定时器的成员也初始化//然后再对要用到的成员变量进行更改TIM_OCStructInit(&TIM_OCInitStructure);//输出比较模式TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较极性//高极性 = 极性不反转;低极性反之,这里选的高极性TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;//输出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//CCR比较寄存器的值TIM_OCInitStructure.TIM_Pulse = 0;//CCRTIM_OC1Init(TIM2, &TIM_OCInitStructure);
第四步:配置GPIO
把PWM对应的GPIO口初始化为复用推挽输出的配置:
因为这里我们使用的是PA15,而TIM2_CH1M默认是接在PA0,我们需要对引脚进行重映射。
//引脚重映射,选择部分重映射1GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);//关闭PA15的调试功能,之后TIM2_CH1就由PA0->PA15GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//初始化GPIOA15:GPIO_InitTypeDef GPIO_PA15_InitStructure;GPIO_PA15_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_PA15_InitStructure.GPIO_Pin = GPIO_Pin_15;GPIO_PA15_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_PA15_InitStructure);
第五步:运行控制,启动计数器
//启动定时器TIM_Cmd(TIM2,ENABLE);
第六步:更改CCR值的函数TIM_SetCompare1
通过传给compare的值可以更改CCR的值
void PWM_SetCompare(uint16_t compare)
{TIM_SetCompare1(TIM2,compare);
}
第七步:在主函数中调用
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Steering_Engine.h"int main()
{Steering_EngineInit();PWM_SetCompare(500); //对应的是0度while(1){}
}
相关文章:
STM32——使用TIM输出比较产生PWM波形控制舵机转角
一、输出比较简介: 只有高级定时器和通用寄存器才有输入捕获/输出比较电路,他们有四个CCR(捕获/比较寄存器),共用一个CNT(计数器),而输出比较功能是用来输出PWM波形的。 红圈部分…...
第十五章 集合(set)(Python)
文章目录 前言一、集合 前言 集合(set)是一个无序的不重复元素序列。 一、集合 set {1, 2, 3, 4}...
面试-javaIO机制
1.BIO BIO:是传统的javaIO以及部分java.net下部分接口和类。例如,socket,http等,因为网络通信同样是IO行为。传统IO基于字节流和字符流进行操作。提供了我们最熟悉的IO功能,譬如基于字节流的InputStream 和OutputStream.基于字符流…...
在.NET Core中,config和ConfigureServices的区别和作用
在.NET Core中,config和ConfigureServices是两个不同的概念,它们在应用程序的启动和配置过程中扮演着不同的角色。 ConfigureServices:这是ASP.NET Core应用程序中的一个方法,位于Startup类的内部。它的作用是配置依赖注入(DI)容器…...
App Inventor 2 如何实现多个定时功能?
1、可以使用多个“计时器”组件。 2、也可以用一个计时器,定时一分钟。也就是一分钟就会触发一次事件执行,定义一个全局数字变量,在事件中递增,用逻辑判断这个变量的值即可完成多个想要定时的任务(о∀о) 代码块请参考…...
技术驱动的音乐变革:AI带来的产业重塑
📑引言 近一个月来,随着几款音乐大模型的轮番上线,AI在音乐产业的角色迅速扩大。这些模型不仅将音乐创作的门槛降至前所未有的低点,还引发了一场关于AI是否会彻底颠覆音乐行业的激烈讨论。从初期的兴奋到现在的理性审视࿰…...
重生之我要学后端0--HTTP协议和RESTful APIs
http和RESTful APIs HTTP协议RESTful APIs设计RESTful API设计实例 HTTP协议 HTTP(超文本传输协议)是用于分布式、协作式和超媒体信息系统的应用层协议。它是网页数据通讯的基础。工作原理简述如下: 客户端请求(Request…...
深度之眼(二十八)——神经网络基础知识(三)-卷积神经网络
文章目录 一、前言二、卷积操作2.1 填充(padding)2.2 步长2.3 输出特征图尺寸计算2.4 多通道卷积 三、池化操作四、Lenet-5及CNN结构进化史4.1 Lenet-5 一、前言 卷积神经网络–AlexNet(最牛)-2012 Lenet-5-大规模商用(1989) 二、…...
AI Infra简单记录
向量数据库的作用 1. 在AI大模型训练过程中,向量数据库可以有效提升数据检索、特征提取等任务的效率。 2、在AI大模型推理过程中,向量数据库为大模型提供外挂知识库,提升模型时效性与准确性,提供缓存能力,减少调用开…...
三英战吕布 | 第5集 | 温酒斩华雄 | 竖子不足与谋 | 三国演义 | 逐鹿群雄
🙋大家好!我是毛毛张! 🌈个人首页: 神马都会亿点点的毛毛张 📌这篇博客分享的是《三国演义》文学剧本第Ⅰ部分《群雄逐鹿》的第5️⃣集《三英战吕布》的经典语句和文学剧本全集台词 文章目录 1.经典语句2.文学剧本台…...
【C语言】自定义类型:结构体
目录 1. 结构体类型的声明 1.1. 结构的一般声明 1.2. 结构的特殊声明 2. 结构体变量的创建和初始化 3. 结构体的自引用 4. 结构体内存对齐 4.1. 对其规则(面试考点) 4.2. 为什么存在内存对齐? 4.2.1. 平台原因(移植…...
算法金 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost 算法大全
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 决策树是一种简单直观的机器学习算法,它广泛应用于分类和回归问题中。它的核心思想是将复杂的决策过程分解成一系列简单的决…...
[每周一更]-(第103期):GIT初始化子模块
文章目录 初始化和更新所有子模块分步骤操作1. 克隆包含子模块的仓库2. 初始化子模块3. 更新子模块 查看子模块状态提交子模块的更改处理子模块路径错误的问题 该问题的缘由是因为:在写某些代码的时候,仓库中有些文件夹,只提交了文件夹名称到…...
单例模式---线程安全实现
文章目录 1.单例模式的特点😊2.单例模式两种实现🤣🤗😊2.1 饿汉式2.2 懒汉式 3.传统单例模式的线程安全问题4.解决方法4.1静态局部变量4.2加锁4.3双重检查锁(DCL)4.4pthread_once 1.单例模式的特点…...
Agent技术在现代软件开发与应用中的探索
一、引言 随着计算机科学的快速发展,Agent技术作为人工智能和分布式计算领域的重要分支,已经渗透到软件开发的各个方面。Agent技术通过赋予软件实体自主性和交互性,使得软件系统能够更加智能、灵活地响应环境变化和用户需求。本文将对Agent技…...
c语言中extern定义和引用其他文件的变量,(sublime text)单独一个文件编译不会成功
关键字extern的作用 这个很常见的都知道是定义一个外部变量或函数,但并不是简单的建立两个文件,然后在用extern 定义在另一个非最初定义变量的文件里 区分文件和编译运行的文件 例如,一个文件夹里有文件a.c和文件b.c,在sublime text中直接…...
时序数据中的孤立野点、异常值识别及处理方法
目录 参考资料 对时序数据做差分; 参考资料 [1] 离群点(孤立点、异常值)检测方法 2017.6;...
JetBrains PyCharm 2024 mac/win版编程艺术,智慧新篇
JetBrains PyCharm 2024是一款功能强大的Python集成开发环境(IDE),专为提升开发者的编程效率和体验而设计。这款IDE不仅继承了前代版本的优秀特性,还在多个方面进行了创新和改进,为Python开发者带来了全新的工作体验。 JetBrains PyCharm 20…...
MCU解决800V电动汽车牵引逆变器的常见设计挑战的3种方式
电动汽车 (EV) 牵引逆变器是电动汽车的。它将高压电池的直流电转换为多相(通常为三相)交流电以驱动牵引电机,并控制制动产生的能量再生。电动汽车电子产品正在从 400V 转向 800V 架构,这有望实现: 快速充电 – 在相同…...
《逆向投资 邓普顿的长赢投资法》
接下来跟大家一起学习《逆向投资 邓普顿的长赢投资法》。邓普顿被誉为20世纪最伟大的选股人之一,我非常确信林奇在他的《战胜华尔街》里也提到了邓普顿,可惜实在想不起来林奇是怎么形容邓普顿的。 邓普顿拥有70多年的投资生涯,在他晚年时曾总…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
