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

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

前言

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输出PWMTIM_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模式1TIM_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输出PWMTIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //PWM模式1TIM_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模式1TIM_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模式1TIM_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);	  //禁用JTAGAdvanceTim_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输出、互补输出、死区、刹车,这几个功能就全都实现了。

相关文章:

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

前言 STM32F103系列的MCU,相比普通的51单片机,在输出硬件PWM这个功能上要强不少,两者实现的方式都类似,都是通过一个定时器来启用硬件PWM输出,不过在输出PWM通道的数量上,32F103要强上不少。仅通过一个高级…...

Camtasia2023最新版电脑视频录屏记录编辑软件

在Mac或Wind上有各种可用的视频记录和编辑软件,其中Camtasia被称为视频记录器和视频编辑器。录屏软件Camtasia2023到底有什么特色功能?本文将帮助您选择理想的选择来开始视频捕获,创建和编辑。Camtasia2023是Mac/win平台上一款使用非常简单的…...

管理用户安全性

每个数据库用户帐户都包括以下项:唯一的用户名验证方法 默认表空间临时表空间用户概要文件初始使用者组帐户状态验证用户口令验证、外部验证、全局验证管理员验证操作系统安全性:• DBA 必须具有创建或删除文件的操作系统权限。• 普通数据库用户不应具有…...

分享113个JS菜单导航,总有一款适合您

分享113个JS菜单导航,总有一款适合您 113个JS菜单导航下载链接:https://pan.baidu.com/s/1d4nnh-UAxNnSp9kfMBmPAw?pwdcw23 提取码:cw23 Python采集代码下载链接:https://wwgn.lanzoul.com/iKGwb0kye3wj base_url "http…...

RuoYi-Cloud 部署

RuoYi-Cloud部署 1. 下载 点击右侧链接可以进入gitee的源码下载地址: 偌依微服务源码gitee下载地址 2. 数据库部署 依据如下步骤创建系统所需数据环境,脚本执行没有先后次序要求: 在Mysql 中创建 ry-cloud 主数据库,并执行 …...

DockerFile文件详解

一、DockerFile文件说明1、概述 Dockerfile是用来构建Docker镜像的文本文件,文本内容包含了一条条构建镜像所需的指令、参数和说明。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,ENV等指令。即:Dockerfile仅…...

Java程序运行机制

Java语言既具有编译型语言的特征,又具有解释型语言的特征,Java程序要经过先编译后解释两个阶段。高级语言的运行机制📍编译型语言使用专门的编译器,针对特定的平台(移植性差),将高级语言的源代码…...

LeetCode刷题------字符串

目录 LeetCode:344.反转字符串 LeetCode:541. 反转字符串II LeetCode:剑指Offer 05.替换空格 LeetCode:151.翻转字符串里的单词 LeetCode:剑指Offer58-II.左旋转字符串 LeetCode:28. 实现 strStr() …...

区块链技术与应用2——BTC-数据结构

文章目录比特币中的数据结构1. 区块链(block chain)2. 默克尔树(Merkle tree)3.哈希指针的问题比特币中的数据结构 1. 区块链(block chain) 哈希指针: (1)保存数值的位置…...

BiseNet v1论文及其代码详解

来源:投稿 作者:蓬蓬奇 编辑:学姐 BiSeNet v1说明: 文章链接:https://arxiv.org/abs/1808.00897 官方开源代码:https://github.com/CoinCheung/BiSeNet (本文未使用) 文章标题&am…...

(超详细)Navicat的安装和激活,亲测有效

步骤一:准备安装包 下载Navicat,我用的v15最好一致(私信可以发你安装包和注册码)步骤二:关闭杀毒软件,然后需要断掉网络(一定断网) 步骤三:一路next安装,安装…...

JDY-31蓝牙模块使用指南

前言 本来是想买个hc-05,这种非常常用的模块,但是在优信电子买的时候,说有个可以替代的,没注意看,买回来折腾半天。 这个模块是从机模块,蓝牙模块分为主机从机和主从一体的,主机与从机的区别就…...

【2023】华为OD机试真题Java-题目0211-租车骑绿道

租车骑绿道 题目描述 部门组织绿道骑行团建活动。租用公共双人自行车骑行,每辆自行车最多坐两人、最大载重 M M M。 给出部门每个人的体重,请问最多需要租用多少双人自行车。 输入描述 第一行两个数字 m m m、...

leetcode: 3Sum

leetcode: 3Sum1. 题目描述2. 思考3. 解题3. 总结1. 题目描述 Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i ! j, i ! k, and j ! k, and nums[i] nums[j] nums[k] 0. Notice that the solution set must not contain …...

【Python学习笔记】26.Python3 输入和输出(2)

前言 本章节继续介绍Python的输入输出。 文件对象的方法 本节中剩下的例子假设已经创建了一个称为 f 的文件对象。 f.read() 为了读取一个文件的内容,调用 f.read(size), 这将读取一定数目的数据, 然后作为字符串或字节对象返回。 size 是一个可选的数字类型的…...

vue项目第二天

项目中使用element-ui库中文网https://element.eleme.cn/#/zh-CN安装命令npm install element-ui安装按需加载babel插件npm install babel-plugin-component -Dnpm i //可以通过npm i 的指令让配置刷新重新配置一下项目中使用element-ui组件抽离文件中按需使用element ui &…...

Python爬虫零基础到进阶(课程说明)

Python爬虫零基础到进阶 课程介绍总结 学—练—问 跟着学、多做多练、不懂就问、坚持就是胜利! 作业 飞书布置,作业提交放到群里,老师批改。 代码量 python基础: 十一次课,学会python。环境安装(了…...

《C++ Primer Plus》第16章:string类和标准模板库(13)

复习题 考虑下面的声明: class RQ1{ private:char *st; // pointer to C-style string public:RQ1() { st new char [1];strcpy(st, "");}RQ1(const char * s) {st new char [strlen(s)1];strcpy(st, s);}RQ1(const RQ1 & rq) {st new char[strlen…...

材质笔记 - Simluate Solid Surface

光的行为 当光和物体相遇时,光会有三种行为:被物体反射、穿过物体(物体是透明或半透明的)或者被吸收。 高光反射和漫反射 高光反射(Specular Reflection)会在表面光滑且反光的物体上看到,比如镜…...

设计模式-值类型与引用类型、深拷贝与浅拷贝、原型模式详解

一. 值类型和引用类型 1. 前言 (1). 分类 值类型包括:布尔类型、浮点类型(float、double、decimal、byte)、字符类型(char)、整型(int、long、short等)、枚举(entum)、结构体(struct)。 引用类型:数组、字符串(string)、类、接口…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理&#xff1a…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...

【JVM】- 内存结构

引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...