[标准库]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)、类、接口…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
VSCode 没有添加Windows右键菜单
关键字:VSCode;Windows右键菜单;注册表。 文章目录 前言一、工程环境二、配置流程1.右键文件打开2.右键文件夹打开3.右键空白处打开文件夹 三、测试总结 前言 安装 VSCode 时没有注意,实际使用的时候发现 VSCode 在 Windows 菜单栏…...
