ARM PWM 定时器与实战

news2024/12/23 15:51:38

一、什么是定时器(timer)

1、定时器是 SoC 中常见外设

(1) 定时器与计数器。计数器是用来计数的(每隔一个固定时间会计一个数);因为计数器的计数时间周期是固定的,因此到了一定时间只要用计数值×计数时间周期,就能得到一个时间段,这个时间段就是我们定的时间(这就是定时器了)。
(2) 定时器/计数器作为 SoC 的外设,主要用来实现定时执行代码的功能。定时器相对于 SoC 来说,就好象闹钟相对于人来说意义一样。


2、定时器有什么用

(1) 定时器可以让 SoC 在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断提醒 CPU,CPU 会去处理中断并执行定时器中断的 ISR 。从而去执行预先设定好的事件。
(2) 定时器就好象是 CPU 的一个秘书一样,这个秘书专门管帮 CPU 来计时,并到时间后提醒 CPU 要做某件事情。所以 CPU 有了定时器之后,只需预先把自己 xx 时间之后必须要做的事情绑定到定时器中断 ISR 即可,到了时间之后定时器就会以中断的方式提醒 CPU 来处理这个事情。


3、定时器的原理

(1) 定时器计时其实是通过计数来实现的。定时器内部有一个计数器,这个计数器根据一个时钟(这个时钟源来自于 ARM 的 APB 总线,然后经过时钟模块内部的分频器来分频得到)来工作。每隔一个时钟周期,计数器就计数一次,定时器的时间就是计数器计数值 × 时钟周期。

在这里插入图片描述

(2) 定时器内部有 1 个寄存器 TCNT,计时开始时我们会把一个总的计数值(譬如说 300)放入 TCNT 寄存器中,然后每隔一个时钟周期(假设为 1ms )TCNT 中的值会自动减 1(硬件自动完成,不需要 CPU 软件去干预),直到 TCNT 中减为 0 的时候,TCNT 就会触发定时器中断。
(3) 定时时间是由 2 个东西共同决定的:一个是 TCNT 中的计数值,一个是时钟周期。譬如上例中,定时周期就为 300 × 1 ms = 300 ms。


4、定时器和看门狗、RTC、蜂鸣器的关系

(1) 这几个东西都是和时间有关的部件。
(2) 看门狗其实就是一个定时器,只不过定时时间到了之后不只是中断,还可以复位 CPU。
(3) RTC 是实时时钟,它和定时器的差别就好象闹钟(定时器)和钟表(RTC)的差别一样。
(4) 蜂鸣器是一个发声设备,在 ARM 里面蜂鸣器是用定时器模块来驱动的。


二、 S5PV210 中的定时器

在 S5PV210 内部,一共有 4 类定时器件。这 4 类定时器件的功能、特征是不同的。

在这里插入图片描述

1、PWM 定时器

(1) 这种是最常用的,平时所说的定时器一般指的是这个。像简单的单片机(譬如 51 单片机)中的定时器也是这类。
(2) 为什么叫 PWM 定时器,因为一般 SoC 中产生 PWM 信号都是靠这个定时器模块的。


2、系统定时器

(1) 系统(指的是操作系统)定时器,系统定时器也是用来产生固定时间间隔(TCNT×时钟周期)信号的,称为 systick,这个 systick 用来给操作系统提供 tick 信号。
(2) 产生 systick 作为操作系统的时间片(time slice)的。
(3) 一般做操作系统移植的时候,这里不会由我们自己来做,一般原厂提供的基础移植部分就已经包含了。


3、看门狗定时器

(1) 看门狗定时器本质上也是一个定时器,和上面 2 个没有任何本质区别。
(2) 看门狗定时器可以设置在时间到了的时候产生中断,也可以选择发出复位信号复位 CPU。
(3) 看门狗定时器在实践中应用很多,尤其是工业领域(环境复杂、干扰多)机器容易出问题,而且出问题后后果很严重,此时一般都会用看门狗来进行系统复位。


4、实时时钟 RTC(real time clock)

(1) 区分时间段和时间点。时间段是相对的,两个时间点相减就会得到一个时间段;而时间点是绝对的,是绝无仅有的一个时间点。
(2) 定时器关注的是时间段(而不是时间点),定时器计时从开启定时器的那一刻开始,到定的时间段结束为止产生中断;RTC 中工作用的是时间点(xx年x月x日x时x分x秒星期x)。
(3) RTC和定时器的区别,就相当于是钟表和闹钟的区别。


三、S5PV210 的 PWM 定时器1

1、为什么叫 PWM 定时器

(1) 叫定时器说明它本质上的原理是定时器。
(2) 叫 PWM 定时器,是因为这个定时器天然是用来产生 PWM 波形的。


2、PWM 定时器介绍

(1) S5PV210 有 5 个PWM 定时器。其中 0、1、2、3 各自对应一个外部 GPIO,可以通过这些对应的 GPIO 产生 PWM 波形信号并输出;timer4 没有对应的外部 GPIO(因此不是为了生成 PWM 波形而是为了产生内部定时器中断而生的)。
(2) S5PV210 的 5 个 PWM 定时器的时钟源为 PCLK_PSYS,timer0 和 timer1 共同使用一个预分频器,timer2、3、4 共同使用一个预分频器;每个 timer 有一个专用的独立的分频器;预分频器和分频器构成了 2 级分频系统,将 PCLK_PSYS 两级分频后生成的时钟供给 timer 模块作为时钟周期。

Each timer has its own 32-bit down-counter which is driven by the timer clock. The down-
counter is initially loaded from the Timer Count Buffer register (TCNTBn). If the down-
counter reaches zero, the timer interrupt request is  generated to inform the CPU that 
the timer operation is complete. If the timer down-counter reaches zero, the  value 
of corresponding TCNTBn automatically reloads into the down-counter to start a next
cycle. However, if the  timer stops, for example, by clearing the timer enable bit 
of TCONn during the timer running mode, the value of TCNTBn is not reloaded into 
the counter. 

The PWM function uses the value of the TCMPBn register. The timer control logic changes 
the output level if down-counter value matches the value of the compare register in 
timer control logic. Therefore, the compare register determines the turn-on time 
(or turn-off time) of a PWM output. 

The TCNTBn and TCMPBn registers are double buffered to allow the timer parameters to 
be updated in the  middle of a cycle. The new values do not take effect until the 
current timer cycle completes.

在这里插入图片描述

在这里插入图片描述


3、S5PV210 的 PWM 定时器框图简介

(1) 关键点:时钟源、预分频器、分频器、TCMPB & TCNTB、dead zone
在这里插入图片描述


四、S5PV210 的 PWM 定时器 2

1、预分频器与分频器

(1) 两级分频是串联(级联)的,所以两级分频的分频数是相乘的。
(2) 两级分频的分频系数分别在 TCFG0 和 TCFG1 两个寄存器中设置。
(3) 预分频器有 2 个,prescaler0 为 timer0 & timer1 共用;prescaler1 为 timer2、3、4 共用;两个 prescaler 都是 8 bit 位,因此 prescaler value 范围为 0~255;所以预分频器的分频值范围为 1~256(注意实际分频值为 prescaler value + 1)。
(4) 分频器实质上是一个 MUX 开关,多选一开关决定了走哪个分频系数路线。可以选择的有 1/1,1/2,1/4,1/8,1/16 等。
(5) 计算一下,两级分频下来,分频最小为 1/1(也可能是 1/2 ),最大分频为 1/256 × 16(1/4096).
(6) 在 PCLK_PSYS 为 66 MHz的情况下(默认时钟设置就是 66 MHz的),此时两级分频后的时钟周期范围为 0.03us 到 62.061us;再结合 TCNTB 的值的设置(范围为1~2 ^ 32),可知能定出来的时间最长为 266548.27s(折合74小时多,远远够用了)。
在这里插入图片描述


2、TCNT&TCMP、TCNTB&TCMPB、TCNTO

(1) TCNT 和 TCNTB 是相对应的,TCNTB 是有地址的寄存器,供程序员操作TCNT 在内部和TCNTB 相对应,它没有寄存器地址,程序员不能编程访问这个寄存器。
(2) TCNT 寄存器功能就是用来减 1 的 ,它是内部的不能读写;我们向 TCNT 中写,要通过TCNTB 往进写;读取 TCNT 寄存器中的值要通过读取相对应的 TCNTO 寄存器。

在这里插入图片描述

(3) 工作流程就是:我们事先算好 TCNT 寄存器中开始减的那个数(譬如 300),然后将之写入TCNTB 寄存器中,在启动 timer 前,将 TCNTB 中的值刷到 TCNT 寄存器中(有一位寄存器专门用来操作刷数据过去的),刷过去后就可以启动定时器开始计时;在计时过程中如果想知道 TCNT 寄存器中的值减到多少了,可以读取相应的 TCNTO 寄存器来得知。
(4) 定时功能只需要 TCNT、TCNTB 两个即可;TCNTO 寄存器用来做一些捕获计时;TCMPB 用来生成PWM波形。
在这里插入图片描述

在这里插入图片描述


3、自动重载和双缓冲(auto-reload and double buffering)

(1) 定时器工作的时候,一次定时算一个工作循环。定时器默认是单个循环工作的,也就是说定时一次,计时一次,到期中断一次,就完了。下次如果还要再定时中断,需要另外设置。
(2) 但是现实中用定时器来做的时候往往是循环的,最简单最笨的方法就是写代码反复重置定时器寄存器的值(在每次中断处理的 isr 中再次给 TCNTB 中赋值,再次刷到 TCNT 中再次启动定时器),早期的单片机定时器就是这样的;但是现在的高级 SoC 中的定时器已经默认内置了这种循环定时工作模式,就叫自动装载(auto-reload)机制。
(3) 自动装载机制就是当定时器初始化好开始计时后再不用管了,他一个周期到了后会自己从TCNTB 中再次装载值到 TCNT 中,再次启动定时器开始下个循环。
在这里插入图片描述


在这里插入图片描述


4、一个定时器实例

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


五、S5PV210 的PWM 定时器 3

1、什么是 PWM ?

(1) PWM(pulse wide modulation 脉宽调制)。
(2) PWM 波形是一个周期性波形,周期为 T,在每个周期内波形是完全相同的。每个周期内由一个高电平和一个低电平组成。
(3) PWM 波形有 2 个重要参数:一个是周期 T,另一个是占空比 duty(占空比就是一个周期内高电平的时间除以周期时间的商)。
(4) 对于一个 PWM 波形,知道了周期 T 和占空比 duty,就可以算出这个波形的所有细节。譬如高电平时间为 T * duty,低电平时间为 T * (1-duty)
(5) PWM波形有很多用处,譬如通信上用 PWM 来进行脉宽调制对基波进行载波调制;在发光二极管 LED 照明领域可以用 PWM 波形来调制电流进行调光;用来驱动蜂鸣器等设备。


2、PWM 波形的生成原理

(1) PWM 波形其实就是用时间来控制电平高低,所以用定时器来实现 PWM 波形是天经地义的。
(2) 早期的简单单片机里(譬如 51 单片机)是没有专用的 PWM 定时器的,那时候我们需要自己结合 GPIO 和定时器模块来手工生产 PWM 波形(流程是这样:先将 GPIO 引脚电平拉高、同时启动定时器定 T * duty 时间,时间到了在 isr 中将电平拉低,然后定时 T * (1-duty) 后再次启动定时器,然后时间到了后在 isr 中将电平拉高,然后再定时 T * duty 时间再次启动定时器····如此循环即可得到周期为 T,占空比为 duty 的 PWM 波形)。
(3) 后来因为定时器经常和 PWM 产生纠结在一起,所以设计 SoC 的时候就直接把定时器和一个 GPIO 引脚内部绑定起来了,然后在定时器内部给我们设置了 PWM 产生的机制,可以更方便的利用定时器产生 PWM 波形。此时我们利用 PWM 定时器来产生 PWM 波形再不用中断了。 绑定了之后坏处就是 GPIO 引脚是固定的、死板的、不能随便换的;好处是不用进入中断 isr 中,直接可以生成 PWM。
(4) 在 S5PV210 中,PWM 波形产生有 2 个寄存器很关键,一个是 TCNTB、一个是 TCMPB。其中,TCNTB 决定了 PWM 波形的周期,TCMPB 决定了 PWM 波形的占空比。

在这里插入图片描述

(5) 最终生成的 PWM 波形的周期是:TCNTB × 时钟周期(PCLK_PSYS 经过两极分频后得到的时钟周期)。注意这个周期是 PWM 中高电平+低电平的总时间,不是其中之一。
(6) 最终生成的 PWM 波形的占空比是:TCMPB / TCNTB.

在这里插入图片描述


在这里插入图片描述


3、输出电平翻转器

(1) PWM 定时器可以规定:当 TCNT > TCMPB 时为高电平,当 TCNT < TCMPB 时为低电平。也可以规定:当 TCNT > TCMPB 时为低电平,当 TCNT < TCMPB 时为高电平。在这两种规定下,计算时 TCMP 寄存器的值会变化。
(2) 基于上面讲的,当 duty 从 30% 变到 70% 时,我们 TCMPB 寄存器中的值就要改(譬如 TCNTB 中是 300 时,TCMPB 就要从 210 变化到 90 )。这样的改变可以满足需要,但是计算有点麻烦。于是乎 210 的 PWM 定时器帮我们提供了一个友好的工具叫做电平翻转器。
(3) 电平翻转器在电路上的实质就是一个电平取反的部件,在编程上反映为一个寄存器位。写 0 就关闭输出电平反转,写 1 就开启输出电平反转。开启后和开启前输出电平刚好高低反转。(输出电平一反转 30% 的 duty 就变成 70% 了)
(4) 实战中到底是 TCNT 和 TCMPB 谁大谁小时高电平还是低电平,一般不用理论分析,只要写个代码然后用示波器实际看一下出来的波形就知道了;如果反了就直接开启电平翻转器即可。


4、死区生成器

(1) PWM 有一个应用就是用在功率电路中用来对交流电压进行整流。整流时 2 路整流分别在正电平和负电平时导通工作,不能同时导通(同时导通会直接短路,瞬间的同时导通都会导致电路烧毁)。大功率的开关电源、逆变器等设备广泛使用了整流技术。特别是逆变器,用 SoC 的 GPIO 输出的 PWM 波形来分别驱动 2 路整流的IGBT。
(2) PWM 波形用来做整流时要求不能同时高或低,因为会短路。但是实际电路是不理想的,不可能同时上升/下降沿,所以比较安全的做法是留死区。
(3) 死区这东西离不了也多不了。死区少了容易短路,死区多了控制精度低了不利于产品性能的提升。
(4) S5PV210 给大家提供了自带的死区生成器,只要开启死区生成器,生产出来的 PWM 波形就自带了死区控制功能,用户不用再自己去操心死区问题。
(5) 大部分人工作是用不到这个的,直接关掉死区生成器即可。


六、蜂鸣器和 PWM 定时器编程实践1

1、蜂鸣器的工作原理

(1) 蜂鸣器里面有 2 个金属片,离的很紧但没挨着;没电的时候两个片在弹簧本身张力作用下分开彼此平行;有电的时候两边分别充电,在异性电荷的吸力作用下两个片挨着;
(2) 我们只要以快速的频率给蜂鸣器的正负极:供电、断电。进行这样的循环,蜂鸣器的两个弹簧片就会挨着分开挨着分开···形成敲击,发出声音。
(3) 因为人的耳朵能听见的声音频率有限制(20Hz-20000Hz),我们做实验时一般给个 2KHz 的频率,大部分人都能听到。
(4) 频率高低会影响声音的音频,一般是音频越低声音听起来越低沉、音频越高听起来越尖锐。
(5) 根据以上的分析,可以看出,只要用 PWM 波形的电压信号来驱动蜂鸣器,把 PWM 波形的周期 T 设置为要发出的声音信号的 1/频率 即可;PWM 的占空比只要确保能驱动蜂鸣器即可(驱动能力问题,一般引脚驱动能力都不够,所以蜂鸣器会额外用三极管来放大流来供电)。


2、原理图和硬件信息

(1) 查阅原理图可知,开发板底板上的蜂鸣器通过 GPD0_2(XpwmTOUT2) 引脚连接在 SoC 上。
在这里插入图片描述


在这里插入图片描述

(2) GPD0_2 引脚通过限流电阻接在三极管基极上,引脚有电,蜂鸣器就会有电(三极管导通);引脚没电,蜂鸣器就会没电(三极管关闭)。这些都是硬件问题,软件工程师不用管,软件工程师只要写程序控制 GPD0_2 引脚的电平产生 PWM 波形即可。
(3) GPD0CON (0xE02000A0),要把 bit8~bit11 设置为 0b0010(功能选择为TOUT_2,就是把这个引脚设置为 PWM 输出功能)。
在这里插入图片描述

(4) 从 GPD0_2 引脚可以反推出使用的是 timer2 这个PWM定时器。


3、PWM定时器的主要寄存器详解

(1) 相关的寄存器有 TCFG0、TCFG1、CON、TCNTB2、TCMPB2、TCNTO2。

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


七 、蜂鸣器和 PWM 定时器编程实践2

注意:PWM 定时器来产生 PWM 波形时是不需要中断干预的。

#define 	GPD0CON		(0xE02000A0)
#define 	TCFG0		(0xE2500000)
#define 	TCFG1		(0xE2500004)
#define 	CON		(0xE2500008)
#define 	TCNTB2		(0xE2500024)
#define 	TCMPB2		(0xE2500028)

#define 	rGPD0CON	(*(volatile unsigned int *)GPD0CON)
#define 	rTCFG0		(*(volatile unsigned int *)TCFG0)
#define 	rTCFG1		(*(volatile unsigned int *)TCFG1)
#define 	rCON		(*(volatile unsigned int *)CON)
#define 	rTCNTB2		(*(volatile unsigned int *)TCNTB2)
#define 	rTCMPB2		(*(volatile unsigned int *)TCMPB2)

/******************************************************************************/

#define         BIT_WIDTH_GPD0_CON                (4)
#define         BIT_LOCATION_GPD0_2_FUNC          (0xf    << (2 * BIT_WIDTH_GPD0_CON))
#define         GPD0_2_FUNC_INPUT                 (0b0000 << (2 * BIT_WIDTH_GPD0_CON))
#define         GPD0_2_FUNC_OUTPUT                (0b0001 << (2 * BIT_WIDTH_GPD0_CON))
#define         GPD0_2_FUNC_TOUT2                 (0b0010 << (2 * BIT_WIDTH_GPD0_CON))
#define         GPD0_2_FUNC_INT2                  (0b1111 << (2 * BIT_WIDTH_GPD0_CON))

/******************************************************************************/

#define         BIT_LOCATION_TCFG0_PRESCALER0     (0xff)   // 1~255
#define         BIT_LOCATION_TCFG0_PRESCALER1     (0xff << 8) // 1~255

/******************************************************************************/

#define         BIT_WIDTH_TCFG1_DIVIDER            (4)
#define         BIT_LOCATION_TCFG1_DIVIDER_MUX2    (0xf    << (2 * BIT_WIDTH_TCFG1_DIVIDER))
#define         TCFG1_DIVIDER_MUX2_DIVID_1         (0b0000 << (2 * BIT_WIDTH_TCFG1_DIVIDER))
#define         TCFG1_DIVIDER_MUX2_DIVID_2         (0b0001 << (2 * BIT_WIDTH_TCFG1_DIVIDER))
#define         TCFG1_DIVIDER_MUX2_DIVID_4         (0b0010 << (2 * BIT_WIDTH_TCFG1_DIVIDER))
#define         TCFG1_DIVIDER_MUX2_DIVID_8         (0b0011 << (2 * BIT_WIDTH_TCFG1_DIVIDER))
#define         TCFG1_DIVIDER_MUX2_DIVID_16        (0b0100 << (2 * BIT_WIDTH_TCFG1_DIVIDER))
#define         TCFG1_DIVIDER_MUX2_DIVID_SCLK_PWM  (0b0101 << (2 * BIT_WIDTH_TCFG1_DIVIDER))

/******************************************************************************/

#define         BIT_LOCATION_TCON_TIMER2_START_STOP         (0b1 << 12)
#define         TCON_TIMER2_FUNC_STOP                       (0b0 << 12)
#define         TCON_TIMER2_FUNC_START                      (0b1 << 12)

#define         BIT_LOCATION_TCON_TIMER2_MANUAL_UPDATE      (0b1 << 13)
#define         TCON_TIMER2_FUNC_NO_UPDATE                  (0b0 << 13)
#define         TCON_TIMER2_FUNC_MANUAL_UPDATE              (0b1 << 13)

#define         BIT_LOCATION_TCON_TIMER2_OUTPUT_INVERTER    (0b1 << 14)
#define         TCON_TIMER2_FUNC_TOUT2_INVERTER_OFF         (0b0 << 14)
#define         TCON_TIMER2_FUNC_TOUT2_INVERTER_ON          (0b1 << 14)

#define         BIT_LOCATION_TCON_TIMER2_AUTO_RELOAD        (0b1 << 15)
#define         TCON_TIMER2_FUNC_AUTO_RELOAD_OFF            (0b0 << 15)
#define         TCON_TIMER2_FUNC_AUTO_RELOAD_ON             (0b1 << 15)


//初始化 PWM Timer2,使其输出 PWM 波形: 频率是 2KHZ, duty 为 50%
void timer2_pwm_init()
{
    //设置 GPD0_2 引脚,将其配置为 XpwmTOUT_2
    rGPD0CON &= ~(BIT_LOCATION_GPD0_2_FUNC);
    rGPD0CON |= (GPD0_2_FUNC_TOUT2);


    //Timer Input Clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value}
    //设置 PWM 定时器的若干寄存器, 使其工作
    rTCFG0 &= ~(BIT_LOCATION_TCFG0_PRESCALER1);
    rTCFG0 |= (65 << 8);  // 66 分频

    rTCFG1 &= ~(BIT_LOCATION_TCFG1_DIVIDER_MUX2);
    rTCFG1 |= TCFG1_DIVIDER_MUX2_DIVID_2; //MUX2 设置为 1/2,分频后时钟周期为 500KHZ
    //时钟设置好,我们的时钟频率是 500KHZ, 对应的时钟周期是 2us.也就是说每隔 2us
    //计一次数. 如果要定的时间是 x,则 TCNTB 中应该写入 x/2us
    
    
    rCON |= (TCON_TIMER2_FUNC_AUTO_RELOAD_ON);  //使能 auto-reload,反复定时才能发出 PWM 波形
    
    //设置 PWM 波形为 2KHZ, 即周期是 0.5ms; 500us/2us = 250,即计数 250,就可以定时 0.5ms.
    rTCNTB2 = 250;
    rTCMPB2 = 125;

    //设置 PWM 波形为 10KHZ, 即周期是 0.1ms; 100us/2us = 50,即计数 50,就可以定时 0.1ms.
    rTCNTB2 = 50;
    rTCMPB2 = 25;

    //设置 PWM 波形为 100HZ, 即周期是 10ms; 10,000us/2us = 5000, 即计数 5000,就可以定时 10ms.
    rTCNTB2 = 5000;
    rTCMPB2 = 2500;

    //第一次需要手工将 TCNTB 中的值刷新到 TCNT 中, 以后就可以 auto-reload 了
    rCON |= TCON_TIMER2_FUNC_MANUAL_UPDATE;            //打开自动刷新功能
    rCON &= ~(BIT_LOCATION_TCON_TIMER2_MANUAL_UPDATE); //关闭自动刷新功能

    rCON |= (TCON_TIMER2_FUNC_START);   //开 timer2 定时器,要先把其他设置好才能开定时器




}

示例代码可以参照下图所示的图解。
在这里插入图片描述


源自朱有鹏老师.

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

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

相关文章

contex-m基于IAR工程从boot阶段引导app

目录 1.修改工程 2.修改代码 Boot代码 App代码 3.修改FM33LG04x.icf 4.修改IAR工程icf配置路径 5.修改FM33LG04X.icf链接文件 6.编译工程 7.查看map文件 8.调试程序 1.修改工程 本次调试的demo为《UART0 DMA发送_串口中断示例》&#xff0c;以下修改都是基于该工程&…

初始C语言 - 函数

C语言中函数的分类&#xff1a; 1.库函数:C语言自带的函数&#xff0c;包含大量频繁使用的功能 2.自定义函数:有些库函数没有的&#xff0c;需要程序员自己设计一、库函数通过MSDN、cplusplus.com、cppreference.com这些网站&#xff0c;查看学习函数的作用和用法在使用库函数时…

portswigger靶场中目录遍历

portswigger靶场中目录遍历1.Bp靶场介绍1.1.访问靶场1.2.注意事项2.目录变量漏洞2.1.文件路径遍历2.1.1.开启靶场2.1.2.点击详情2.1.3.抓包2.1.4.修改参数2.1.5.过关2.2.用绝对路径旁路阻止遍历序列2.2.1.开启靶场2.2.2.修改参数2.2.3.过关2.3.非递归地剥离遍历序列2.3.1.开启靶…

Windows下让Qt5 QCamera响应UVC摄像头硬件按钮拍图

QCamera相机类提供了一些基本的功能&#xff0c;包括拍照和录制功能&#xff08;Windows不支持录制视频&#xff09;&#xff0c;但也有很多接口是没有封装的&#xff0c;比如有些UVC摄像头有物理按键&#xff0c;可以进行拍图等操作&#xff0c;但是QCamera没法响应硬件按钮的…

通信原理与MATLAB(十五):码间干扰和无码间干扰条件

目录1.码间干扰2.无码间干扰条件2.1 时域条件2.2 频域条件3.满足无码间干扰条件的滤波器3.1 理想低通滤波器3.2 余弦滚降滤波器4.不同滚降系数的余弦滚降滤波器时频域图4.1 代码4.2 结果图5.理想低通滤波器和升余弦滚降滤波器(α1)对比1.码间干扰 如下图所示&#xff0c;码间干…

Vue 基础之侦听器

Vue 基础之侦听器描述侦听器侦听器的创建侦听器的应用选项immediate 选项deep 选项未使用 deep 选项使用 deep 选项侦听目标对象中的单个属性描述 项目描述IDEVScode操作系统Windows 10 专业版Vue.js2.6.12 侦听器 侦听器允许开发者对数据进行监视&#xff0c;并指定数据发生…

数据分析-深度学习 Pytorch Day4

一&#xff1a;概述当你想训练好一个神经网络时&#xff0c;你需要做好三件事情&#xff1a;一个合适的网络结构&#xff0c;一个合适的训练算法&#xff0c;一个合适的训练技巧&#xff1a;合适的网络结构&#xff1a;包括网络结构和激活函数&#xff0c;你可以选择更深的卷积…

打工人必学的法律知识(四)——《中华人民共和国劳动法》

中华人民共和国劳动法http://www.npc.gov.cn/npc/c30834/201901/ffad2d4ae4da4585a041abf66e74753c.shtml 目录 第一章 总  则 第二章 促进就业 第三章 劳动合同和集体合同 第四章 工作时间和休息休假 第五章 工  资 第六章 劳动安全卫生 第七章 女职工和未…

大数据技术之Hadoop(HDFS)——超详细

第1章 HDFS概述 1.1 HDFS产出背景及定义 1&#xff09;HDFS产生背景 随着数据量越来越大&#xff0c;在一个操作系统存不下所有的数据&#xff0c;那么就分配到更多的操作系统管理的磁盘中&#xff0c;但是不方便管理和维护&#xff0c;迫切需要一种系统来管理多台机器上的文…

误删照片音视频文件不要担心 几种方法解救慌乱的你 别再病急乱投医啦 [附软件]

误删照片音视频文件不要担心 几种方法解救慌乱的你 方法1&#xff1a;从手机相册中恢复手机删除的照片 这里以vivo手机为例,其他手机也是差不多的 相册->右上角三个点->设置->云空间 进入云存储空间 点击云盘->我的备份->就能看到你自动上传的照片 相册-&…

【Linux】共享内存

目录 一、共享内存 1.1 申请共享内存块 1.2 释放共享内存块 1.3 挂接共享内存 二、共享内存的使用 2.1 Server端与Client端 2.2 挂接与运行 三、共享内存总结 3.1 共享内存的特点 3.2 共享内存实现访问控制 一、共享内存 共享内存是最快的IPC形式。一旦这样的内存映…

xxl-job原理(版本2.3.1)

一、xxl-job架构图 1、调度中心 ​ 负责管理调度信息&#xff0c;按照调度配置发出调度请求&#xff0c;自身不承担业务代码。调度系统与任务解耦&#xff0c;提高了系统可用性和稳定性&#xff0c;同时调度系统性能不再受限于任务模块。 2、执行器 负责接收调度请求并执行任…

CSS注入 2.0

看过CSS注入1.0的朋友&#xff0c;不相信对CSS注入有了一个概念性的理解&#xff0c;在上一篇文章中我只是简单复现了一下波兰老哥的CSS注入过程&#xff0c;阐述了其大致原理。对于其中很大一部分技术细节&#xff0c;代码细节并未做深入的理解(当时我也看不懂&#xff0c;哈哈…

什么是分布式事务

上一篇文章已经讲完分布式了&#xff0c;那暖男说要讲分布式事务那就一定会讲&#xff0c;只是我估计大家没料到暖男这么快就肝好了吧&#xff1f; 事务想必大家并不陌生&#xff0c;至于什么是 ACID&#xff0c;也是老生常谈了。不过暖男为了保证文章的完整性确保所有人都听得…

uniapp-微信小程序分包操作步骤详解

1、在原来的pages的同级下新建一个目录&#xff1a;package1 &#xff08;名字自己随便起。想分几个包就建几个新目录。比如package2、package3……&#xff09; 结构是并列的&#xff1a; 2、把想要放进分包里去的模块都剪切在新目录里面去。 &#xff08;就是以前全都放在…

移动端 - 搜索组件(suggest篇)

这一篇博客是和 search-input篇 衔接的, 需要的可以看上文 移动端 - 搜索组件(search-list篇) 这里我们需要去封装这么一个组件 先说一下大致的方向: 1. 根据父组件传入的关键字数据发送请求获取后端数据, 进行模板渲染 2. 处理一些边界情况(后端返回数据为空, 初次加载数据…

《小猫猫大课堂》三轮3——字符函数和字符串函数及其模拟实现

宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的很重…

C语言——自定义类型详解(结构体,联合体,枚举,位段)

专栏&#xff1a;C语言 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;本专栏主要更新一些C语言的基础知识&#xff0c;也会实现一些小游戏和通讯录&#xff0c;学时管理系统之类的&#xff0c;有兴趣的朋友可以关注一下。 结构体前言一、结构体1.结构体类型的声明2.结构体…

黑马学ElasticSearch(十)

目录&#xff1a; &#xff08;1&#xff09;自动补全-安装品分词器 &#xff08;2&#xff09;自动补全-自定义分词器 &#xff08;3&#xff09;自动补全-DSL实现自动补全查询 &#xff08;4&#xff09; 自动补全-修改酒店索引库结构 &#xff08;5&#xff09;自动补全…

测试开发——用例篇(如何设计一个测试用例,设计测试用例的一些具体方法)

目录 一、测试用例的基本要素 二、设计测试用例的万能公式 (在没有需求文档的情况下&#xff09; 1、水杯的测试用例 2、一个网站的登录测试用例 三、基于需求进行测试用例的设计 四、测试用例的具体设计方法 1、等价类 2、边界问题 3、判定表&#xff08;因果图&#…