[标准库]STM32F103R8T6 高级定时器--PWM输出和带死区互补PWM输出

news2024/11/18 7:49:51

前言

STM32F103系列的MCU,相比普通的51单片机,在输出硬件PWM这个功能上要强不少,两者实现的方式都类似,都是通过一个定时器来启用硬件PWM输出,不过在输出PWM通道的数量上,32F103要强上不少。仅通过一个高级定时器1,即TIM1就可以输出4路频率相同,占空比独立的PWM信号,这四路PWM还分别有互补通道,且带死区和刹车功能。

利用TIM1来产生4路频率相同,占空比不同的PWM信号

初始化的方法其实跟前面几篇文章初始化其他外设的步骤类似,也是先定义一个结构体变量,然后给这个结构体变量的成员配置好相应的初值,最后调用初始化函数,这样就完成外设初始化了。再通过调用开外设的函数,就可以把外设功能使能。

首先定义一个结构体变量来初始化TIM1(定义PWM信号的频率)

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;        //配置时基结构体,声明一个结构体变量方便传参

//=====================时基初始化======================//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);   //开TIMER1外设时钟

TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
// 计数器计数模式
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 10000-1;

// 时钟分频因子 - 一分频,配置死区时间需要用到
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV4;

// 重复寄存器的值,没有用到,不管
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);

我使用的是倍频到72M的时钟信号作为APB2的时钟总线,然后我分频器选择的是72分频,那么分频之后的周期就是1/1M,即TIM1往上计数一次是1us,然后计数周期我设置为了从0计数到9999,即10000次,耗时就是10ms。所以我设置的PWM频率就是100Hz的。

下一步开始设置PWM的结构体,在手册中,硬件PWM这部分内容是属于 高级定时器中的:输出/比较模式 ,所以要配置PWM,我们就要配置 输出/比较结构体。

TIM_OCInitTypeDef TIM_OCInitStructure;                //配置输出比较结构体,声明一个结构体变量方便传参

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道1输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;    //互补通道使能
TIM_OCInitStructure.TIM_Pulse = 4000;               //占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
TIM_OC1Init(TIM1,&TIM_OCInitStructure);                             //初始化TIM1通道1输出PWM

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道2输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;    //互补通道失能
TIM_OCInitStructure.TIM_Pulse = 6000;               //占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
TIM_OC2Init(TIM1,&TIM_OCInitStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道3输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;    //互补通道失能
TIM_OCInitStructure.TIM_Pulse = 8000;               //占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
TIM_OC3Init(TIM1,&TIM_OCInitStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道4输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;    //互补通道失能
TIM_OCInitStructure.TIM_Pulse = 9000;               //占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
TIM_OC4Init(TIM1,&TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);                    //使能TIM1 输出比较1的预装载使能 想要改变占空比 得先输出完当前周期的波形之后 到下个波形才按照新的占空比(更新事件发生后才改变占空比)

TIM_Cmd(TIM1,ENABLE);												//开启TIM1
TIM_CtrlPWMOutputs(TIM1,ENABLE);									//开启PWM输出

其实看起来内容多,实际上都是重复的内容。高级定时器的每路PWM通道,都通过一个库函数来初始化,比如通道1就是调用TIM_OC1Init(TIM1,&TIM_OCInitStructure); 前面这个形参是配置利用哪个定时器的通道1来产生PWM信号,后面这个形参就是我们定义的结构体变量的首地址,负责传入我们配置的相应参数。

除了高级定时器,通用定时器也可以产生PWM信号,但是基本定时器是无法产生PWM信号的,基本定时器的功能只有下面这几个:
在这里插入图片描述
回到正题,配置完时基和输出/比较模式的PWM模式的寄存器之后,再把PWM四个通道的IO配置一下:

void AdvanceTim_GPIO_Config(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
	
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
	
    //刹车通道
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12);      //默认为低电平,这个脚一旦被拉高证明刹车有效,立刻停止输出PWM

    //TIM1 CHANNEL1互补通道
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
}

这里暂时只需要关注PA8、PA9、PA10、PA11这四个IO的配置,其他的是后面做刹车和互补才需要用到的。
配置起来其实很简单,但是要注意GPIO模式要配置为复用的推挽输出模式。

在设置完这些之后,就可以去主函数里面调用了。
给前面我们写的初始化时基和PWM寄存器的代码写到同一个函数里:

void AdvanceTim_Mode_Config(void)
{
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;        //配置时基结构体,声明一个结构体变量方便传参
    TIM_OCInitTypeDef TIM_OCInitStructure;                //配置输出比较结构体,声明一个结构体变量方便传参

    //=====================时基初始化======================//
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);   //开TIMER1外设时钟
    
    TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
    // 计数器计数模式
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period = 10000-1;

    // 时钟分频因子 - 一分频,配置死区时间需要用到
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV4;
    
    // 重复寄存器的值,没有用到,不管
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
    //====================================================//

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道1输出使能
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;    //互补通道使能
    TIM_OCInitStructure.TIM_Pulse = 4000;               //占空比
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
    TIM_OC1Init(TIM1,&TIM_OCInitStructure);                             //初始化TIM1通道1输出PWM

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道2输出使能
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;    //互补通道失能
    TIM_OCInitStructure.TIM_Pulse = 6000;               //占空比
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
    TIM_OC2Init(TIM1,&TIM_OCInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道3输出使能
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;    //互补通道失能
    TIM_OCInitStructure.TIM_Pulse = 8000;               //占空比
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
    TIM_OC3Init(TIM1,&TIM_OCInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道4输出使能
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;    //互补通道失能
    TIM_OCInitStructure.TIM_Pulse = 9000;               //占空比
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
    TIM_OC4Init(TIM1,&TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);                    //使能TIM1 输出比较1的预装载使能 想要改变占空比 得先输出完当前周期的波形之后 到下个波形才按照新的占空比(更新事件发生后才改变占空比)

    TIM_Cmd(TIM1,ENABLE);
    TIM_CtrlPWMOutputs(TIM1,ENABLE);

}

在主函数中:

int main(void)
{
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);	  //禁用JTAG

	AdvanceTim_GPIO_Config();
	AdvanceTim_Mode_Config();
	
	while(1)
	{

	}
}

下载到板子上,用逻辑分析仪抓取PA8/9/10/11这四个IO的波形,可以观察到,四路PWM信号的频率相同(因为都是通过TIM1产生的),但是四路PWM信号的占空比分别为40%、60%、80%、90%。这就实现了硬件PWM的输出。

输出TIM1通道1的互补信号

其实这个不用单独再拿出来讲,在配置TIM1通道1的时候,有几个结构体成员的值修改一下,即可输出通道1的互补信号。

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;       //TIM1通道1输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;    //互补通道使能
TIM_OCInitStructure.TIM_Pulse = 4000;               //占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;           //高电平有效
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;          //互补通道也是高电平有效
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;        //空闲状态 低电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      //互补通道空闲状态 低电平
TIM_OC1Init(TIM1,&TIM_OCInitStructure);                             //初始化TIM1通道1输出PWM

TIM_OutputNState 这个成员配置为TIM_OutputNState_Enable,那么互补通道就使能了;
TIM_OCNPolarity 这个成员是配置互补通道是什么电平有效;
TIM_OCNIdleState_Reset 这个成员是配置互补通道的空闲状态应该是什么电平。
一般如果要用到互补模式的话,互补通道的配置与通道1是相同的,如果需要产生错相的两路PWM信号,那么要用到中心对其模式才能做到,硬件PWM是不具备输出错相PWM波的功能的。

配置了有关PWM的寄存器之后,配置一下互补通道的GPIO,也是配置为复用推挽输出模式。不过要注意的是每路PWM信号的输出脚和互补脚都有很多个,我这边因为MCU脚位只有64个,所以还不需要选择在哪个IO输出;推测应该是如果把IO设置为了复用输出模式,那么PWM就会从那个复用脚输出出来,不需要再配置相应的寄存器了。

刹车功能的使用

这个功能我仅限于能使用,一些较为深层次的原理和使用场景我就说不出来了。

在前面定义的AdvanceTim_Mode_Config(void)函数中,多声明一个结构体成员,并且调用初始化函数来初始化 刹车 和 死区寄存器。

TIM_BDTRInitTypeDef TIM_BDTRInitStructure;            //配置有关刹车和死区结构体,声明一个结构体变量方便传参

// TIM_BDTRInitStructure这个结构体配置的是 刹车和死区寄存器(TIMx_BDTR)
// 当 BKIN 引脚检测到低电平的时候,输出比较信号被禁止,就好像是刹车一样
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;         // 运行模式下的“关闭状态”选择 - 使能
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;         // 空闲模式下的"关闭状态"选择 - 使能
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;              // 锁定等级1
TIM_BDTRInitStructure.TIM_DeadTime  = 0xFF;
TIM_BDTRInitStructure.TIM_Break     = TIM_Break_Enable;             // 刹车功能使能 - 开启刹车输入
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;   // 刹车信号 - 高电平刹车
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; // 自动输出使能
TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);

TIM_OSSRState 和 TIM_OSSIState 这两个成员配置的是 TIMx_BDTR寄存器里面的 OSSR位 和 OSSI位,其他的成员,互相之间是有关联的,比如 TIM_LOCKLevel 锁定等级如果配置的是 2 或者 3,那么 TIMx_BDTR这个寄存器在配置完之后,有一些成员是没法再改变值的,这是ST对这个功能的一些保护机制。后面的几个成员就比较好理解,注释有写,不再过多解释。
关于TIM_DeadTime 这个成员,配置的是DTG[7:0]这七位数据,这7位数据比较有意思,手册是这样写的:
在这里插入图片描述
5-7位填入不同的值,Tdtg的值不同,Tdts是我们在配置时基那里配置的,我为了让死区时间更加明显,所以我配置的都比较久,Tdts我配置为了TIM1时钟的四分频,我的TIM1时钟配置为了1M,那么Tdts就是250Khz 的频率,Tdtg=16/250Khz,在乘以(32+(0-4位配置的数值))。

配置了BDTR寄存器之后,配置一下刹车通道的输入,这里是我当时比较疑惑的,我不太明白为什么刹车通道也是配置为复用推挽输出模式。反正按照这样设置完之后,把PB12这个IO一拉高,所有的硬件PWM信号全部停止输出,会全部回到空闲状态我配置的那个电平状态。

//刹车通道
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12);      //默认为低电平,这个脚一旦被拉高证明刹车有效,立刻停止输出PWM

到这,TIM1的PWM输出、互补输出、死区、刹车,这几个功能就全都实现了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/338677.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.Redis 实现点赞 优化登陆(验证码 token..)

Redis(1)简介Redis 是一个高性能的 key-value 数据库原子 – Redis的所有操作都是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。非关系形数据库数据全部存在内存中,性能高。(2&#…

Docker中安装MySQL 8

前言 上一期在Windows中安装好了Docker环境,这一期在Docker中完成MySQL 8安装和配置。 启动Docker Desktop后在cmd窗口中输入docker -v即可查看到安装的docker版本 Docker启动容器的原理流程 Docker启动一个容器(应用)时,大致原理流程如下图&#x…

安全技术与防火墙工具iptables

目录 安全技术 安全技术 补充防水墙 防火墙的分类 按保护范围划分 按实现方式划分 按网络协议划分 iptables iptables的五表五链 三种报文流向 iptables基本语法 数据包常见的控制类型 iptables的基本选项 显示扩展模块 保存规则 持久保存规则 加载规则 开机自…

上岸!轻轻松松打工!Python数据分析证

俗话说的好,活到老学到🤔这个大内卷的时代掌握一项技能还是很重要🙈的,这不趁着下班时间的功夫,偷偷去考了个证 就是一个不论含金量,还是对实习和求职都非常有益的一个双协会认证的高含金量证书~BDA数据分析…

电影订票网站的设计与开发

技术:Java、JSP等摘要:随着科技的发展,时代的进步,互联网已经成为了人们生活中不可缺少的一部分,网上购物已然是一种时代的象征。纵观市场,电影行业的发展尤为迅速,电影种类和数量的增多导致客流…

Portraiture全新4.0最新版人像磨皮插件更新内容

Portraiture是一款智能磨皮插件,为Photoshop和Lightroom添加一键磨皮美化功能,快速对照片中皮肤、头发、眉毛等部位进行美化,无需手动调整,大大提高P图效率。全新4版本,升级AI算法,并独家支持多人及全身模式…

ROS小车研究笔记2/11/2023:使用ssh远程登录小车

1 SSH简介: SSH全称Secure Shell,是一种建立在应用层的安全网络协议。其安全性又非对称加密(RSA)实现 对称加密:使用同一密钥对信息进行加密和解密,但是一旦该密钥被窃取就会威胁通信安全 非对称加密:使用公钥和私钥。…

【Java基础】018 -- 面向对象阶段项目下(拼图小游戏扩展)

文章目录切换游戏图片的业务分析:1,所需要的技术点2,分析业务逻辑项目实现步骤:添加组件绑定事件:代码实现登录界面的业务分析:1,所需要的技术点2,分析业务逻辑项目实现步骤:主界面设…

Day885.NextKeyLock加锁规则 -MySQL实战

NextKeyLock加锁规则 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于NextKeyLock加锁规则的内容。 加锁规则前提说明&#xff1a; MySQL 后面的版本可能会改变加锁策略&#xff0c;所以这个规则只限于截止到现在的最新版本&#xff0c;即 5.x 系列 <5.7.24&#…

搭建流媒体推流/拉流服务(RTMP/RTSP/HLS/HTTP-FLV)

一、什么是流媒体流媒体&#xff08;streaming media&#xff09;是指将一连串的媒体数据压缩后&#xff0c;经过网上分段发送数据&#xff0c;在网上即时传输影音以供观赏的一种技术与过程&#xff0c;此技术使得数据包得以像流水一样发送&#xff1b;如果不使用此技术&#x…

ffmpeg转码转封装小工具开发

如下图所示&#xff0c;是本人开发的一个转码转封装小工具 其中目标文件视频编码格式支持&#xff1a;H264&#xff0c;H265&#xff0c;VP8&#xff0c;VP9。 目标文件封装格式支持&#xff1a;mp4,mkv,avi,mov,flv。 目标文件音频编码格式支持两个&#xff0c;COPY和AAC&am…

安全寒假作业nginx反向代理+负载均衡上传webshell重难点+apache漏洞

1.应用场景 负载均衡作为现今解决web应用承载大流量访问问题的一种方案&#xff0c;在真实环境中得到广泛的部署。实现负载均衡的方式有很多种&#xff0c;比如 DNS 方式、HTTP 重定向方式、IP 负载均衡方式、反向代理方式等等。 比如基于dns的负载均衡&#xff1a; 当然还有…

LTD212次升级 | 官网社区支持PC端展示 • 官网新增证件查询应用,支持条形码扫码查询

1、新增证件查询应用&#xff0c;支持条形码扫码查询&#xff1b; 2、新增用户社区PC端功能&#xff1b; 01证件查询应用 1、新增证件查询应用功能 支持证件信息录入、打印功能&#xff0c;支持条形码扫码识别。 后台管理操作路径&#xff1a;官微中心 - 应用 - 证件查询 …

这才是CSDN最系统完整的网络安全学习路线(建议收藏)

01 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

linux head命令(head指令)(获取文件或管道输出结果前n行,默认前10行)与sed命令区别

head命令是一个在Linux系统中常用的命令&#xff0c;用于读取文件的前几行&#xff08;默认读取前10行&#xff09; 文章目录使用方法读取文件的前10行&#xff1a;head filename读取文件的前n行&#xff1a;head -n行数 filename读取多个文件的前几行&#xff1a;head -n 行数…

六、Java框架之SpringBoot

黑马课程 文章目录1. SpringBoot入门1.1 SpringBoot入门案例步骤1&#xff1a;创建SpringBoot项目高版本springboot常见错误步骤2&#xff1a;创建BookController步骤3&#xff1a;启动服务器并运行程序pom.xml示例1.2 官网创建SpringBoot1.3 SpringBoot工程快速启动问题导入打…

网络安全实验室6.解密关

6.解密关 1.以管理员身份登录系统 url&#xff1a;http://lab1.xseclab.com/password1_dc178aa12e73cfc184676a4100e07dac/index.php 进入网站点击忘记密码的链接&#xff0c;进入到重置密码的模块 输入aaa&#xff0c;点击抓包&#xff0c;发送到重放模块go 查看返回的链接…

VScode 结合clangd 构建linux源代码阅读环境

1、背景介绍上一篇文章&#xff1a;VScode 结合Global构建linux源代码阅读环境 &#xff0c;介绍了在VS Code工具中通过remote-ssh远程登陆到Linux远程服务器&#xff0c;使用Global构建linux源代码阅读环境&#xff0c;对linux kernel代码进行解析&#xff0c;实现全局搜索、自…

Vue2创建移动端项目

一、Vscode Vscode 下载安装以及常用的插件 1、Vscode 下载 下载地址&#xff1a;Vscode 中文语言插件 搜索 chinese 主题 Atom 主题 文件图标主题 搜索 icon 源代码管理插件GitLens 搜索 GitLens Live Server _本地服务器 搜索 Live Server Prettier - Code formatt…

405 Method Not Allowed,CORS跨域,来也自动化OCR接口报错,Nginx处理OPTIONS请求

在使用来也的OCR接口时&#xff0c;请求报错了&#xff0c;提示CORS跨域。POST请求&#xff0c;请求url&#xff1a;http://mage.uibot.com.cn/v1/mage/ocr/bills&#xff0c;官方文档&#xff1a;请求与响应&#xff1a;预检请求OPTIONS正式请求错误信息看控制台和网络栏位内容…