TIM输出比较之PWM驱动LED呼吸灯应用案例

文章目录

  • 前言
  • 一、应用案例演示
  • 二、电路接线图
  • 三、应用案例代码
  • 四、应用案例分析
    • 4.1 基本思路
    • 4.2 相关库函数介绍
    • 4.3 初始化PWM模块
      • 4.3.1 RCC开启时钟
      • 4.3.2 配置时基单元
      • 4.3.3 配置输出比较单元
      • 4.3.4 配置GPIO
      • 4.3.5 运行控制
    • 4.4 PWM输出模块
    • 4.5 主程序


前言

提示:本文主要用作在学习江科大自化协STM32入门教程后做的归纳总结笔记,旨在学习记录,如有侵权请联系作者

本案例利用输出占空比可调的PWM波形来驱动LED灯,实现了一个LED呼吸灯的效果。


一、应用案例演示

TIM输出比较之PWM驱动LED呼吸灯演示

二、电路接线图

在这里插入图片描述

三、应用案例代码

PWD.h文件:

#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);#endif

PWD.c文件:

#include "stm32f10x.h"                  // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 0;		//CCRTIM_OC1Init(TIM2, &TIM_OCInitStructure);TIM_Cmd(TIM2, ENABLE);
}void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);
}

主程序main.c文件:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"uint8_t i;int main(void)
{OLED_Init();PWM_Init();while (1){for (i = 0; i <= 100; i++){PWM_SetCompare1(i);Delay_ms(10);}for (i = 0; i <= 100; i++){PWM_SetCompare1(100 - i);Delay_ms(10);}}
}

完整工程:TIM输出比较之PWM驱动LED呼吸灯应用案例

四、应用案例分析

我们先来看一下PWM的基本结构图,如下所示,我们只需要把下面这些模块打通就可以输出PWM了。

在这里插入图片描述

4.1 基本思路

具体的步骤如下:

  • 第一步,RCC开启时钟。把我们要用的TIM外设和GPIO外设的时钟都打开。
  • 第二步,配置时基单元。包括这前面的时钟源选择。
  • 第三步,配置输出比较单元。包括CCR的值、输出比较模式、极性选择、输出使能这些参数。
  • 第四步,配置GPIO。把PWM对应的GPIO口初始化为复用推挽输出的配置。
  • 第五步,运行控制。启动计数器,这样就能输出PWM了。

以上就是基本思路,老规矩,我们先来看一下都有哪些相关的库函数。

4.2 相关库函数介绍

先来看一下这四个函数

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

这四个函数就是用来配置输出比较模块的,也就是对应PWM的基本结构图中的输出比较单元的位置。输出比较单元有4个,那对应的就是这四个函数。参数TIMx,选择定时器。参数TIM_OCInitStruct,就是输出比较那些参数。

接下来再往下看,该函数是用来给输出比较结构体赋一个默认值的。

void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);

那到这里,输出比较的配置其实就已经可以完成了,接下来就是一些小功能和运行时需要更改参数的函数了。

我们来看一下下面这四个函数,这四个函数是用来配置强制输出模式的,如果你在运行中想要暂停输出波形并且强制输出高或者低电平就可以使用这四个函数。用得不多,了解一下即可。

void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

再看一下下面这四个函数,这四个函数是用来配置CCR寄存器的预装功能的。这个预装功能就是影子寄存器,就是你写入的值不会立即生效,而是在更新事件才会生效,这样可以避免一些小问题。用得不多,了解一下即可。

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

再看一下下面这四个函数,这四个函数是用来配置快速使能的,用得也不多,了解即可。

void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

再看一下下面这四个函数,这四个函数是用于外部事件时清除REF信号,用得也不多,了解即可。

void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

再来看一下下面这些函数,这些函数就是用来单独设置输出比较的极性的,这里带个N的就是高级定时器里互补通道的配置,0C4没有互补通道,所以就没有OC4N的函数。那这里有函数可以设置极性,在结构体初始化的那个函数里也可以设置极性。这两个地方设置极性的作用是一样的。

void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

再看一下下面这两个函数,这两个函数是用来单独修改输出使能参数的。

void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

再下面,这个是用来单独更改输出比较模式的函数。

void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);

再往下看,这四个函数是用来单独更改CCR寄存器值的,这四个函数比较重要。我们在运行的时候更改占空比就需要用到这四个函数。

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

补充一个函数,该函数仅高级定时器使用,在使用高级定时器输出PWM时需要调用这个函数,使能主输出,否则PWM将不能正常输出。

void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

ok,那到这里,有关输出比较的函数就介绍完了,现在开始写代码。

4.3 初始化PWM模块

4.3.1 RCC开启时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

注意:TIM2是APB1总线的外设,要使用APB1的开启时钟函数

4.3.2 配置时基单元

TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

TIM_InternalClockConfig(TIM2);//选择时基单元的时钟源,选择内部时钟。若不调用这个函数,系统上电后默认也是内部时钟。

  • TIM_ClockDivision:指定时钟分频。在这里选择TIM_CKD_DIV1,1分频,也就是不分频。
  • TIM_CounterMode:计数模式。在这里选择TIM_CounterMode_Up向上计数模式。
  • TIM_Period:ARR自动重装器的值。
  • TIM_Prescaler:PSC预分频器的值。
  • TIM_RepetitionCounter:重复计数器的值。这个是高级定时器才有的,我们不需要用,直接给0即可。

计算公式如下:
PWM频率:Freq = CK_PSC / (PSC + 1) / (ARR + 1)
PWM占空比:Duty = CCR / (ARR + 1)
PWM分辨率:Reso = 1 / (ARR + 1)
换算公式:1 MHz = 1,000 KHz = 1,000,000 Hz

假设我要输出一个频率为1KHz,占空比为50%,分辨率为1%的PWM波形,时钟源选择内部时钟,也就是说CK_PSC=72MHz。
代入公式计算可得:
Freq =1000 = 72000000 / 720 / 100
那么可以推算出PSC为719,ARR为99
同样的道理,Duty = 50% = CCR / 100,推算出CCR为50
同样也可以推算出周期 T = 1 / 1000 = 0.001秒,也就是1毫秒。(频率是周期的倒数 f = 1 / T)

4.3.3 配置输出比较单元

TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
TIM_OC1Init(TIM2, &TIM_OCInitStructure);

各个参数解析如下:

  • TIM_OCMode:设置输出比较的模式,这里选择PWM模式1。
  • TIM_OCPolarity:设置输出比较的极性,这里选择高极性,也就是极性不翻转,REF波形直接输出。
  • TIM_OutputState: 设置输出使能,设置使能。
  • TIM_Pulse:设置CCR,这里先暂时设置为0。

设置完成后,在TIM2的OC1通道上就可以输出PWM波形了,但最终这个波形肯定要借用一下GPIO口才能输出对吧?那这个TIM2的OC1通道是借用了哪个GPIO通道呢?

外设引脚和GPIO引脚的复用关系和重映射介绍:

我们可以查看一下引脚定义表,我们来看一下默认复用功能这一列,这一列就是片上外设的端口和GPIO的连接关系。

在这里插入图片描述

在这里可以看到,有TIM2_CH1_ETR,它是在这个PA0这一行的,这就说明TIM2的ETR引脚和通道1的引脚都是借用了PA0这个引脚的位置的。换句话说就是TIM2的引脚复用在了PA0引脚上。所以说如果我们要使用TIM2的OC1也就是CH1通道输出PWM,那它就只能在PA0引脚上输出,而不能任意选择引脚输出。

同样,如果选择TIM2的CH2通道,那就只能在PA1端口上输出。同样的道理,TIM2的CH3就对应PA2,以此类推。这些关系是定死的,不能随意更改。但是如果想要更改的话,还是有办法的,那就是重定义,也叫做重映射。

比如如果你既想用USART2_TX引脚,又要用TIM2的CH3通道,他俩冲突了,没办法同时使用,那我们就可以在这个重映射的列表里找一下,比如我们在引脚号为21的这里找到了TIM2_CH3,那TIM2的CH3就可以从原来的引脚,换到这里的引脚也就是PB10,这样就避免了两个外设引脚的冲突。

在这里插入图片描述
如果这个重映射的列表里找不到,那外设复用的GPIO就不能挪位置,这就是重映射的功能。配置重映射是用AFIO来完成的。

那在了解完外设引脚和GPIO引脚的关系之后,通过查看引脚定义表可知,TIM2的CH1通道复用在了PA0上。或者使用重映射,可以看到TIM2_CH1_ETR可以重映射到PA15上。

在这里插入图片描述

4.3.4 配置GPIO

通过上面的分析可以知道TIM2的CH1通道复用在了PA0上,所以需要初始化一个GPIOA,引脚为pin 0。

要注意的一点就是,这里GPIO的模式要选择GPIO_Mode_AF_PP复用推挽输出模式,为什么要选择这个模式呢?

在这里插入图片描述
对于普通的开漏/推挽输出,引脚的控制权是来自于输出数据寄存器的,那如果想让定时器来控制引脚,那就需要使用复用开漏/推挽输出的模式。在这里输出数据寄存器将被断开,输出控制权将转移给片上外设。那通过刚才看到的引脚定义表我们就知道了这里的片上外设引脚连接的就是TIM2的CH1通道,所以,只有把GPIO设置为复用推挽输出,引脚的控制权才能交给片上外设,PWM波形才能通过引脚输出。

在这里插入图片描述

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

这样,输出PWM的GPIO就配置好了。

4.3.5 运行控制

TIM_Cmd(TIM2, ENABLE);

最后一步,启动定时器。这样,PWM的波形就能通过PA0输出了。

4.4 PWM输出模块

我们想让LED呈现呼吸灯的效果,那就不断更改CCR的值就行了。

void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);
}

4.5 主程序

我们只需要在while(1)主循环里不断调用PWM_SetCompare1函数更改CCR的值(占空比从0到100,再从100到0),这样就能完成LED呼吸灯的效果了。

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"uint8_t i;int main(void)
{OLED_Init();PWM_Init();while (1){for (i = 0; i <= 100; i++){PWM_SetCompare1(i);Delay_ms(10);}for (i = 0; i <= 100; i++){PWM_SetCompare1(100 - i);Delay_ms(10);}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[数据集][目标检测]竹子甘蔗发芽缺陷检测数据集VOC+YOLO格式2953张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2953 标注数量(xml文件个数)&#xff1a;2953 标注数量(txt文件个数)&#xff1a;2953 标注…

电脑录屏高清视频制作:如何选择适合的分辨率和参数

在当今数字化时代&#xff0c;无论是教学、演示还是游戏直播&#xff0c;电脑录屏已经成为了一个不可或缺的工具。然而画质往往是录屏质量的关键因素&#xff0c;许多用户在追求高清录屏体验时&#xff0c;常常面临选择1080p还是4K分辨率的困惑。本文将深入探讨如何优化电脑录屏…

SpringBoot自动配置

一、Condition条件判断功能 Condition 是在Spring 4.0 增加的条件判断功能&#xff0c;其主要作用是判断条件是否满足&#xff0c;从而决定是否初始化并向容器注入Bean对象。通过Conditional注解及其一系列的其他相关注解实现。 在Spring Boot中&#xff0c;条件匹配&#xf…

性能优化理论篇 | swap area是个什么东西

我们知道每台计算机的内存&#xff08;RAM&#xff09;都是有限的&#xff0c;而我们的应用程序需要加载到内存才能被运行&#xff0c;如果一台机器运行多个应用程序时&#xff0c;内存可能会耗尽。Linux 系统中的“交换空间&#xff08;也称为交换分区&#xff09;”可以帮助缓…

使用AWS Lambda轻松开启Amazon Rekognition之旅

这是本系列文章的第一篇&#xff0c;旨在通过动手实践&#xff0c;帮助大家学习亚马逊云科技的生成式AI相关技能。通过这些文章&#xff0c;大家将掌握如何利用亚马逊云科技的各类服务来应用AI技术。 那么让我们开始今天的内容吧&#xff01; 介绍 什么是Amazon Rekognition&…

微软的免费“后悔药“-Windows File Recovery (WinFR)

微软的免费"后悔药"-Windows File Recovery (WinFR) 当你不小心误删除了文件或因各种意外情况导致数据丢失&#xff0c;可以使用 EasyRecovery、Disk Drill、DiskGenius、Recuva 等“上古”软件&#xff0c;也可以交由专业机构进行恢复。微软&#xff08;Microsoft&…

揭秘!移动安全管理系统是什么?有什么功能?(从小白到精通一文揭晓!)

在2024年&#xff0c;移动终端管控软件在企业和组织中的应用日益广泛。 移动安全管理系统不仅提高了管理效率&#xff0c;还增强了数据安全性和移动办公的便捷性。 以下是六款值得推荐的移动终端管控软件&#xff1a; 1. 安企神 特点&#xff1a;作为行业领头羊&#xff0c;…

框架漏洞大全【万字总结】

文章目录 常见语言开发框架&#xff1a;Thinkphp远程代码执行5.0.23 rce介绍影响版本复现 CNVD-2018-24942介绍影响版本复现 任意文件包含包含日志-3.2x介绍影响版本复现 包含语言&#xff08;QVD-2022-46174&#xff09;介绍影响版本复现 sql注入漏洞(5.0.x)介绍影响版本复现 …

(26)微信检查联系人和清粉(针对删除和拉黑)-微信UI自动化(.Net+C#)

整理 | 小耕家的喵大仙 出品 | CSDN&#xff08;ID&#xff1a;lichao19897314&#xff09; Q Q | 978124155 往期知识回顾 (1)开启探索微信自动化之路-微信UI自动化(.NetC#) (2)初始化微信窗体UI自动化实例-微信UI自动化(.NetC#) (3)采用热键终止微信采集任务-微信UI自动…

UI自动化测试:遍历页面元素并获取文本的实践分享!

遍历读取元素的文本 在写UI自动化过程中还会遇到需要遍历读取元素的情况。下面分享以「稿定设计」网站为例&#xff0c;想要通过UI自动化读取素材内容的操作菜单列表&#xff0c;如下图&#xff1a; 代码片段和解释 # 获取菜单列表元素的文本信息&#xff0c;例如&#xff1a…

算法基础及例题

1、双指针 维护区间信息、子序列匹配、利用序列有序性、单项链表找环双指针 - OI Wiki (oi-wiki.org) 盛最多水的容器https://leetcode.cn/problems/container-with-most-water/ public class Solution {public int maxArea(int[] height) {int l 0, r height.length - 1;int…

泡泡玛特2024半年报发布:首度划分四大品类 手办收入占比首次低于60%

8月20日&#xff0c;泡泡玛特发布2024上半年业绩报告。报告显示&#xff0c;2024年上半年泡泡玛特国际集团实现营收45.6亿元&#xff08;人民币&#xff0c;下同&#xff09;&#xff0c;同比增长62.0%&#xff0c;经调整后净利10.2亿元&#xff0c;同比增长90.1%。 上半年泡泡…

MacOS升级ruby版本

​ ​ 您好&#xff0c;我是程序员小羊&#xff01; 前言 升级Ruby版本在MacOS上相对简单&#xff0c;但需要一些基础的命令行知识。本文将详细介绍如何在MacOS上升级Ruby版本&#xff0c;包括使用常见的版本管理工具、解决可能遇到的问题、以及确保你的环境配置不会受到影响。…

第二百零九节 Java格式 - Java数字格式类

Java格式 - Java数字格式类 以下两个类可用于格式化和解析数字: java.text.NumberFormatjava.text.DecimalFormat NumberFormat 类可以格式化一个数字特定地区的预定义格式。 DecimalFormat 类可以格式化数字以特定区域设置的自定义格式。 NumberFormat类的 getXXXInstance…

宠物空气净化器怎么选?新手必看猫用除毛空气净化器热门品牌推荐

作为资深铲屎官来说&#xff0c;一到换毛季节&#xff0c;家里的猪咪经常会出现掉毛的情况&#xff0c;而且如果不勤打扫的话&#xff0c;粑粑的臭味也挺重的。如果长期不清理家里的浮毛&#xff0c;很容易就会得鼻炎。 看了身边好几个铲屎官都在用宠物空气净化器&#xff0c;…

什么牌子的开放式耳机性价比高?五款高口碑精品推荐!

由于传统入耳式耳机可能对耳道健康造成长期影响&#xff0c;许多人开始偏好选择开放式耳机的非侵入式设计。这种耳机有助于减少耳内湿润、细菌增长&#xff0c;以及耳道闷热的不适感。为了帮助大家在众多产品中挑选合适的开放式耳机&#xff0c;我将列举一些市场反馈良好的款式…

Android10.0 人脸解锁流程分析

人脸解锁概述 人脸解锁即用户通过注视设备的正面方便地解锁手机或平板。Android 10 为支持人脸解锁的设备在人脸认证期间添加了一个新的可以安全处理相机帧、保持隐私与安全的人脸认证栈的支持&#xff0c;也为安全合规地启用集成交易的应用&#xff08;网上银行或其他服务&am…

TikTok本土店海外仓发货总超时?EasyBoss ERP支持提前申请面单助力解决

近期有部分通过海外仓自发货的TikTok本土卖家表示&#xff1a;通过ERP推送订单至海外仓却无法立即出库&#xff0c;导致超出平台规定发货时间被平台处罚。 而出现这样的原因在于&#xff1a;通过ERP处理的TikTok订单&#xff0c;在使用认证的海外仓发货时&#xff0c;订单会先…

【C++ Primer Plus习题】2.2

问题: 解答: #include <iostream> using namespace std;#define LONG_TO_MA 220int main() {double distance 0;cout << "请输入距离(单位为long):";while (true){cin >> distance;if (cin.fail()){cout << "输入有误!请输入数字:&qu…

Redis 集群三主三从配置

1&#xff1a;安装 Redis安装Linux ubuntu_ubuntu离线安装redis7.2.5-CSDN博客 2&#xff1a;主从复制配置 参考 Redis主从同步配置-CSDN博客 3&#xff1a;哨兵配置 参考 Redis 哨兵模式配置-CSDN博客 4&#xff1a;集群配置 Redis 集群三主三从配置-CSDN博客 5&…