STM32滴答定时器SysTick精准延时,兼容HAL库和标准库

news2024/10/7 18:31:54

STM32手册资料下载:STM32资料Github链接;STM32资料Gitee链接;

注意:Github是国外的,要翻墙,Gitee是国内的,无需翻墙。

目录

滴答定时器的功能

模块化思想

什么叫做模块化

如何利用keil实现模块化

第一步,准备工程文件

第二步,建立delay.c和delay.h文件

第三步,将sys加入工程

第四步 ,加入路径

代码

.c文件 

.h文件

HAL库

标准库

今后如何将delay模块加入其他工程

main.c调用

初始化

实现软件PWM

 Delay_us()实验

Delay_ms()实验

代码讲解

Delay_Init()

代码

滴答定时器寄存器介绍

 Delay_Init()函数介绍

 Delay_us()函数介绍

 Delay_ms()函数介绍

最后再次强调!!!


野火和正点原子的滴答定时器部分的延时函数我都看了,感觉对新手都及其不友好。所以我使用海创电子(教的是标准库的内容,但是真的真的讲得棒!)的滴答定时器部分代码作为讲解。

本次实验利用SysTick精准延时,实现软件PWM。需要准备一个LED灯(这个可能不太直观),或者一个示波器(这个精准一些)。

滴答定时器的功能

(1)滴答定时器可用于操作系统产生时基,维持操作系统的心跳。一般操作系统都需要一个时基,进行任务的调度、同步等功能实现。(这个了解即可,不知道没关系)

(2)滴答定时器常用于计数。比如进行微妙、毫秒延时。(这个才是重点)

注意:

(1)这一篇不需要使用到STM32CubeMX,我们是直接对寄存器进行操作!

(2)想了解底层实现的可以看详细说明,只想要延时函数的可以直接复制代码就走。

(3)因为我们都是裸机开发,所以关于操作系统部分的内容没有。需要操作系统部分的延时程序,可自行去野火或者正点原子的官方例程中复制。

(4)标准库和HAL库代码基本一样,就只要那个需要分频的函数部分需要更改,以及头文件需要更改

(5)在裸机开发中,一般都使用滴答定时器作为精准延时函数。所以我就只讲精准延时部分。

模块化思想

什么叫做模块化

因为可能有人是根据我的博客来学习的,没有模块化的思想,甚至不知道什么叫做模块化。

(1)什么是模块化?

比如我们下载一个工程文件,里面会有很多.c文件(这些.c放在对应的文件夹下面了),只有一个main.c文件,如下。像key文件夹,lcd文件夹下面存储的这些.c文件就是模块

(2)这样模块化了有什么用呢? 

我们都是从学习C语言开始的。像我们使用printf打印字符,scanf获取键盘上的字符。printf和scanf函数就是存放在stdio.h这个头文件下。

当我们有了stdio这个模块之后,我们就不需要重新写printf和scanf函数的实现了。直接引用文件,就可以使用了。

现在我们所说的模块化亦是如此。如果我们将延时函数进行模块化了,之后我们需要在其他工程使用延时函数,我们只需要复制delay这个模块化到对应工程下面即可

如何利用keil实现模块化

很多人可能没怎么使用过keil这个编译器,不知道如何利用keil创建一个模块,现在我教学一下。

第一步,准备工程文件

如果是使用HAL库首先利用STM32CubeMX生成一个工程文件。

如果是标准库,你自己准备好一个点灯工程。第一步就不用看了

(1)配置RCC

(2)主频配置为72MHZ

 

(3)配置SYS 

(4)配置GPIO 

(5) 生成文件

 

第二步,建立delay.c和delay.h文件

(1) 在工程目录下建立一个文件夹名为User,然后再在这个文件夹里面建立一个delay文件夹。

(2)在delay文件夹下面建立两个txt文件 

(3)更改两个文件名为delay.c和delay.h。

注意:记得要勾选文件扩展名!!!不会的百度!!!

第三步,将sys加入工程

第四步 ,加入路径

(1)再点击两个OK,现在delay这个模块就加入工程了。

(2)然后双击delay.c就可以打开delay.c这个文件了。

(3)在delay.c中加入#include  "delay.h",编译之后,delay.h也加入了工程。

代码

.c文件 

因为我们是直接对寄存器进行操作,所以无论你是使用的HAL库还是标准库,都不影响!!!

直接将下面代码复制到工程里面即可。

#include  "delay.h"

uint8_t fac_us=0;
uint16_t fac_ms=0;

void Delay_Init()
{
	//只可以选择不分频或者8分频,这里选择系统时钟8分频,最后频率为9MHZ
	SysTick->CTRL &= ~(1<<2);
	//SystemCoreClock为72000000,最终fac_us为9,也就是记录震动9次。因为频率为9MHZ所以为1us
	fac_us  = SystemCoreClock  / 8000000;  
	fac_ms  = fac_us*1000;  //1000us=1ms
}

/*
	CTRL     SysTick控制及状态寄存器
	LOAD     SysTick重装载数值寄存器
	VAL      SysTick当前数值寄存器
*/
void Delay_us(uint32_t nus)
{
	uint32_t temp;
	SysTick->LOAD  =nus*fac_us;   //设置加载的值,比如1us就要计数9次。nus传入1,CALIB=1*9=9,最后就是1us
	SysTick->VAL   =0x00;         //清空计数器中的值,LOAD里的值不是写入后就会加载,而是在systick使能且VAL值为0时才加载
	SysTick->CTRL  |=SysTick_CTRL_ENABLE_Msk;  //使能时钟,开始计时
	do
	{
		temp=SysTick->CTRL;   //查询是否计数完成
	}while((temp&0x01)&&!(temp&(1<<16)));   //先判断定时器是否在运行,再判断是否计数完成
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
	SysTick->VAL =0X00;      					 //清空计数器	 
}

void Delay_ms(uint32_t nms)
{
	uint32_t temp;
	SysTick->LOAD  =nms*fac_ms;   //设置加载的值,比如1us就要计数9次。nus传入1,CALIB=1*9=9,最后就是1us
	SysTick->VAL   =0x00;         //清空计数器中的值,LOAD里的值不是写入后就会加载,而是在systick使能且VAL值为0时才加载
	SysTick->CTRL  |=SysTick_CTRL_ENABLE_Msk;  //使能时钟,开始计时
	do
	{
		temp=SysTick->CTRL;   //查询是否计数完成
	}while((temp&0x01)&&!(temp&(1<<16)));   //先判断定时器是否在运行,再判断是否计数完成
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
	SysTick->VAL =0X00;      					 //清空计数器	 
}

.h文件

HAL库

因为HAL库和标准库的头文件名字不一样,所以这里还是有区分的

#ifndef     __delay_H
#define     __delay_H

#include "stm32f1xx.h"  // 相当于51单片机中的  #include <reg51.h>

void Delay_Init(void);
void Delay_us(uint32_t nus);
void Delay_ms(uint32_t nms);
#endif

标准库

#ifndef     __delay_H
#define     __delay_H

#include "stm32f10x.h"   // 相当于51单片机中的  #include <reg51.h>

void Delay_Init(void);
void Delay_us(uint32_t nus);
void Delay_ms(uint32_t nms);
#endif

今后如何将delay模块加入其他工程

我们只需要复制delay这个文件夹,到其他工程中,然后按照第三步,将sys加入工程和第四步 ,加入路径即可。

main.c调用

初始化

(1)首先我们需要在main.c最上面一行写上#include  "delay.h"

(2)然后在main函数里面需要调用Delay_Init();

注意:STM32Cube MX自动生成的  SystemClock_Config();需要放在Delay_Init();之前

 

实现软件PWM

只讲死循环部分,非死循环部分需要调整的如上。

 Delay_us()实验

  while (1)
  {
    /* USER CODE END WHILE */
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
		Delay_us(1000);
    /* USER CODE BEGIN 3 */
  }

最后生成了一个周期为2ms,占空比为50%的PWM

Delay_ms()实验

  while (1)
  {
    /* USER CODE END WHILE */
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
		Delay_ms(10);
    /* USER CODE BEGIN 3 */
  }

 最后生成了一个周期为20ms,占空比为50%的PWM.

代码讲解

这一部分给想跟深刻理解底层的人学习的,如果只是想用延时函数的人不需要看,对后续操作不影响

Delay_Init()

代码

这个函数就是对滴答定时器进行一个8分频。然后设置两个变量。

uint8_t fac_us=0;
uint16_t fac_ms=0;

void Delay_Init()
{
	//只可以选择不分频或者8分频,这里选择系统时钟8分频,最后频率为9MHZ
	SysTick->CTRL &= ~(1<<2);
	//SystemCoreClock为72000000,最终fac_us为9,也就是记录震动9次。因为频率为9MHZ所以为1us
	fac_us  = SystemCoreClock  / 8000000;  
	fac_ms  = fac_us*1000;  //1000us=1ms
}

滴答定时器寄存器介绍

因为滴答定时器属于CM3内核相关的内容,所以我们需要查看CM3的手册。在我上面的链接里面,有很多STM32F103的资料,可以看野火,正点原子的SysTick部分的资料,或者直接看CM3权威指南。

首先解释Sys Tick定时器相关的寄存器

(1)CTRL控制及状态寄存器

CTRL只有0,1,2,16这四个位有用,其他的都没有使用。

 (2)LOAD重装载数值寄存器

1,我们知道,Sys Tick滴答定时器是一个24位定时器,所以他的重装载数值寄存器是一个24bit的寄存器。

2,重装载可能有些人无法理解。因为Sys Tick滴答定时器是一个向下计数的寄存器。比如滴答定时器现在的值为100,那么他从100一直自减到0的时候,LOAD会自动将100存入滴答定时器。

(3)VAL 当前数值寄存器

这个负责记录当前滴答定时器的值。加入这个值为0了,那么重装载寄存器里面的值将会自动存入VAL。(注意,重装载寄存器中的值并没有减少!相当于将重装载寄存器中的值复制,然后粘贴给VAL )

 (4)CALIB 校准数值寄存器

这个不知道什么用,正点原子手册里面没讲解,野火的手册里面说他们也是懵逼的。所以我也不明白,但是我猜测是进行校准滴答定时器的值,如果里面的值出问题了会又一些操作进行校正。用不到,不用纠结

 

 Delay_Init()函数介绍

下面为Delay_Init()这个函数的全部部分。uint8_t fac_us=0;和uint16_t fac_ms=0;也要包含!

uint8_t fac_us=0;
uint16_t fac_ms=0;

void Delay_Init()
{
	//只可以选择不分频或者8分频,这里选择系统时钟8分频,最后频率为9MHZ
	SysTick->CTRL &= ~(1<<2);
	//SystemCoreClock为72000000,最终fac_us为9,也就是记录震动9次。因为频率为9MHZ所以为1us
	fac_us  = SystemCoreClock  / 8000000;  
	fac_ms  = fac_us*1000;  //1000us=1ms
}

(1)我们看第一行代码,很简单,就是对滴答定时器进行一次八分频。CTRL是控制状态寄存器,当我们对他的bit2进行操作的时候,就是在选择SysTick的时钟源。这也是为什么我上面强调SystemClock_Config();需要放在Delay_Init();之前的原因了。

(2)因为我们CubeMX生成的滴答定时器是72MHZ,没有进行8分频。(不过你可以在CubeMX设置让他8分频)如果SystemClock_Config()放在Delay_Init()前面,那么滴答定时器本来在Delay_Init()进行了八分频,现在你又用SystemClock_Config()把滴答定时器变成没有分频。会导致延时出现问题。

(3)这个时候有人会问了,为什么滴答定时器要进行八分频呢?可以不八分频吗?

(4)答案显然是可以的,但是如果看过我之前的博客就知道,如果频率越高,功耗越大,响应速度也快。上面说了,滴答定时器就延时给操作系统提供时基的,我们不用操作系统,那么不需要考虑响应速度的问题。

(5)那么现在就考虑延时的问题,先说结论,如果频率越高,滴答定时器最大延时越短。什么意思呢?

(6)我们先又一个概念,1MHZ表示1S跳变1,000,000次。跳变一次,滴答定时器的VAL( 当前数值寄存器)中的数据就会减1。滴答定时器是24位定时器,2^24=16,777,215。可以跳变16,777,215次

(7)假设不分频,72MHZ,那么现在可以计数1/(72,000,000)*16,777,215\approx 0.233,也就是最大延时0.233S

(8)但是假如是进行了八分频,1/(72,000,000/8)*16,777,215\approx 1.864最大延时1.864S所以,为了更长的延时时间,我们选择了八分频

(9)fac_us 与fac_ms 作用又是什么呢?

现在我们的滴答定时器是9MHZ(72MHZ/8=9MHZ),所以说,当VAL( 当前数值寄存器)每减一,那么就表示过了1/9,000,000S。那么1us(1us=1/1,000,000S)就是VAL的值减9次。1ms就是VAL减9,000次。

(10)如果我们硬是要72MHZ的滴答定时器怎么办呢?

fac_us  = SystemCoreClock  / 8000000;  ——>fac_us  = SystemCoreClock  / 1000000;即可。  

 Delay_us()函数介绍

void Delay_us(uint32_t nus)
{
	uint32_t temp;
	SysTick->LOAD  =nus*fac_us;   //设置加载的值,比如1us就要计数9次。nus传入1,CALIB=1*9=9,最后就是1us
	SysTick->VAL   =0x00;         //清空计数器中的值,LOAD里的值不是写入后就会加载,而是在systick使能且VAL值为0时才加载
	SysTick->CTRL  |=SysTick_CTRL_ENABLE_Msk;  //使能时钟,开始计时
	do
	{
		temp=SysTick->CTRL;   //查询是否计数完成
	}while((temp&0x01)&&!(temp&(1<<16)));   //先判断定时器是否在运行,再判断是否计数完成
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
	SysTick->VAL =0X00;      					 //清空计数器	 
}

(1)我们知道了fac_us可以表示1us,那么我们传入参数nus*fac_us就可以表示为延时了多少us。现在将要延时的时间存入LOAD(自动重装载寄存器),然后清空VAL( 当前数值寄存器)的值,在我们开启滴答定时器的瞬间,LOAD会将数据存入VAL。因为当VAL寄存器为0的时候,LOAD会将值传给VAL。

(2)现在我们进行轮询法,不断查询CTRL(控制及状态寄存器)的bit16,因为CTRL的bit16在VAL为0的时候会为1。

(3)这个时候有人会问了呀,我们一开始就置零了VAL,那么现在CTRL的bit16不就已经是1了吗?所以我们要实现清空CTRL的bit16位。

(4)这个时候我们就需要自行看手册说明了。如果在上次读取本寄存器(也就是CTRL)后,SysTick 已经计到了 0,则该位为 1。

所以流程是,读取CTRL寄存器——>LOAD为0——>CTRL的bit16置1。我们在上面清零LOAD的时候,并没有读取CTRL,当我们在进行轮询的时候,LOAD的值已经被重装载了

(5)一直轮询,直到VAL为0,那么现在延时结束。关闭滴答定时器,清空VAL的值即可。

(6)能够看到这里,说明你有一定基础。但是可能还是有一些新手像了解底层,坚持到了这里,看到SysTick_CTRL_ENABLE_Msk这个东西很奇怪,不知道这个是啥。这个时候我们需要将鼠标点击到SysTick_CTRL_ENABLE_Msk,按F12可以跳转到他的定义。

我们看发现SysTick_CTRL_ENABLE_Msk其实就是无符号的数字1。开关Sys Tick依靠CTRL的bit0。

#define SysTick_CTRL_ENABLE_Msk            (1UL /*<< SysTick_CTRL_ENABLE_Pos*/)           /*!< SysTick CTRL: ENABLE Mask */

 Delay_ms()函数介绍

void Delay_ms(uint32_t nms)
{
	uint32_t temp;
	SysTick->LOAD  =nms*fac_ms;   //设置加载的值,比如1us就要计数9次。nus传入1,CALIB=1*9=9,最后就是1us
	SysTick->VAL   =0x00;         //清空计数器中的值,LOAD里的值不是写入后就会加载,而是在systick使能且VAL值为0时才加载
	SysTick->CTRL  |=SysTick_CTRL_ENABLE_Msk;  //使能时钟,开始计时
	do
	{
		temp=SysTick->CTRL;   //查询是否计数完成
	}while((temp&0x01)&&!(temp&(1<<16)));   //先判断定时器是否在运行,再判断是否计数完成
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
	SysTick->VAL =0X00;      					 //清空计数器	 
}

Delay_ms()与Delay_us()操作步骤一样的,就只是把    SysTick->LOAD  =nus*fac_us; 改为    SysTick->LOAD  =nms*fac_ms; 。

最后再次强调!!!

为了更长的延时时间,我们选择了八分频。但是八分频之后,依旧只能最大延时1.864S!

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

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

相关文章

用 Wireshark 让你看见 TCP 到底是什么样!

本文为掘金社区首发签约文章&#xff0c;14天内禁止转载&#xff0c;14天后未获授权禁止转载&#xff0c;侵权必究&#xff01; 莫听穿林打叶声&#xff0c;何妨吟啸且徐行。 前言 当你看到这篇文章时&#xff0c;你只能看到已经渲染好的文字和图像&#xff0c;而网络数据的交…

rk3588硬件构成-rock5b

前言 rk3588是瑞芯微的一套新的arm64的板子&#xff0c;上一代用的比较多的是rk3399&#xff0c;新的硬件设备比之前更强大&#xff0c;接口更多&#xff0c;本系列就是介绍相关的硬件软件的一些资料&#xff0c;后面会根据不同的使用进行分篇的介绍 很多资料官网有提供&…

深度学习与总结JVM专辑(四):类文件结构(图文+代码)

类文件结构概述无关性的基石Class类文件结构前言字节码文件结构属性魔数与Class文件的版本号魔数版本号常量池反编译软件访问标志类索引&#xff0c;父类索引与接口索引集合字段表集合方法表集合属性表集合Code属性attribute_name_indexmax_stackmax_localscode_length和codeja…

视频卡顿率测试方法

一、背景介绍 视频流畅性测试是视频质量评估一个重要的指标。一般的获取方法是在渲染前增加统计信息。不过这种方法需要增加额外工作量&#xff0c;并且也不是用户直接的体验数据。 这里介绍一种基于时域运动指标/平均相关位置像素差&#xff08;TI&#xff1a;temporal info…

Android Camera性能分析 第24讲 录像Buffer Path帧率统计

​ 本讲是Android Camera性能分析专题的第24讲&#xff0c;我们介绍录像Buffer Path帧率统计&#xff0c;包括如下内容&#xff1a; 从GraphicBufferSource统计录像Buffer Path帧率Video Codec角度统计视频帧率Video Codec2角度统计视频帧率 视频在线观看&#xff1a; 极客笔…

Nacos Discovery--服务治理

目录 一&#xff0c;服务治理介绍 二&#xff0c;nacos简介 nacos实战入门 搭建nacos环境 第1步: 安装nacos 第2步: 启动nacos 第3步: 访问nacos 将商品微服务注册到nacos 1 在shop-common模块的pom.xml中添加nacos的依赖 注意在父模块中是否导入了alibaba 2 在主类上添加E…

Altium Designer智能粘贴命令的使用教程

怎么样等间距的复制很多过孔&#xff1f;怎么带网络的复制走线&#xff1f;又或者是怎么样把元件的位号及网络从当前的这个PCB调用到另一个PCB板中呢&#xff1f;PCB设计当中经常会遇到这些问题&#xff0c;可以使用特殊粘贴也可以称为智能粘贴法来实现。 1、选中需要复制的元素…

微信小程序 视频列表滑动无限循环(仿抖音)

一、写在前面&#xff1a; 1:安卓ios表现基本一致&#xff0c;不是swiper组件实现&#xff0c;滑动效果流畅不卡顿&#xff0c;实现了列表无限循环。不是使用官方的腾讯视频播放组件&#xff0c;完整代码在下面 2:实现功能&#xff1a;支持位置导航、拨打电话、复制微信号、分…

如何实现fastdds的topic调试工具

在使用fastdds进行实际的开发调试中发现&#xff0c;常常需要对已经发布的话题进行进一步的调试&#xff0c;比如话题存在&#xff0c;话题内容&#xff0c;话题频率等等信息都需要确认&#xff0c;尤其是话题内容。这时候就需要一个能进行这项操作的调试工具。可能对于用过ros…

hit_os_lab2 操作系统启动

前置知识 1.1 基础概念 入理论课程的学习。 如果网易云上的课程无法查看&#xff0c;也可以看 Bilibili 上的 操作系统哈尔滨工业大学李治军老师。 L2 开始揭开钢琴的盖子L3 操作系统启动 同济大学赵炯博士的《Linux 内核 0.11 完全注释&#xff08;修正版 V3.0&#xff09…

防火墙练习实验

♥️作者&#xff1a;小刘在C站 ♥️每天分享云计算网络运维课堂笔记&#xff0c;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放。 目录 二. 实验命令 一.实验图纸 二. 实验命令 ciscoasa> en Password: ciscoasa# co…

DJ12-2-4 串操作指令

目录 1. REP 重复前缀 2. 串操作指令的基本概念 3. 串操作指令的指令类型 &#xff08;1&#xff09;串传送指令 MOVS &#xff08;2&#xff09;串传送指令 CMPS &#xff08;3&#xff09;串扫描指令 SCAS &#xff08;4&#xff09;串装入指令 LODS &#xff08;5&a…

如果把网络原理倒过来看,从无到有,一切如此清晰(下)

人生若只如初见。 前言 当我在台灯下&#xff0c;听着远隔17年前五月天的歌&#xff0c;而在数日后&#xff0c;我的文字也会纵使相隔万里远的来到你的屏幕前&#xff0c;就觉得这一切妙不可言。 OSI 网络七层模型 《如果把网络原理倒过来看&#xff0c;从无到有&#xff0c…

Metabase学习教程:仪表盘-5

如何进行时间段比较 我们通过不同的方法来比较一个指标在不同日期范围内的表现。 我们将研究不同的策略来比较两个不同时期的指标&#xff0c;比如将本周与上周、去年同期与上一周进行比较。我们将使用Metabase附带的示例数据库&#xff0c;这样您就可以继续学习了。这个示例…

【Android App】Vulkan实现宇宙中旋转雷达动画效果(附源码和原始视频 超详细必看)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、Vulkan简介 Vulkan是一个跨平台的图形绘制接口&#xff0c;被称为下一代OpenGL&#xff0c;因为尽管OpenGL提供了丰富的图形API&#xff0c;但他在底层实现的C代码早已封装起来&#xff0c;由于开发者修改不了底层代码&#xf…

社区系统项目复盘-5

文章目录Kafka消息队列实现系统通知功能什么是Kafka&#xff1f;Spring是怎么整合Kafka的&#xff1f;发送系统通知显示系统通知Kafka消息队列实现系统通知功能 阻塞队列 可以用阻塞队列来实现消息队列&#xff0c;阻塞队列是一个接口&#xff1a;BlockingQueue&#xff0c;可以…

易云维医院后勤综合管理平台为医院智慧后勤的建设与发展做出贡献

近年来&#xff0c;随着国家医疗卫生改革进程的不断推进&#xff0c;越来越多的医院开始关注运营成本控制问题&#xff0c;医院后勤管理服务模式的创新和优化变得越来越重要。利用医院后勤综合管理平台将医院后勤管理信息化将极大地提高医院智慧后勤建设与发展。在这种形势下&a…

Mac下安装Hadoop

1、引言 如果想在Mac下安装Hadoop而且让Hadoop能正常运行&#xff0c;那安装之前需要先安装java&#xff0c;在Mac环境下安装Hadoop。 2、配置ssh环境 在Mac下如果想使用Hadoop&#xff0c;必须要配置ssh环境&#xff0c; 如果不执行这一步&#xff0c;后面启动hadoop时会出现…

Spring MVC应该怎么学?这份教程带你快速入门,深入剖析源码!

前言: 什么是MVC&#xff1f; MVC&#xff08;Model-View-Controller&#xff09;&#xff1a;它是一种软件架构设计模式&#xff0c;分为三个部分&#xff1a; Model&#xff08;模型&#xff09;&#xff1a;业务的数据模型&#xff1b; View&#xff08;视图&#xff09;&…

xss-labs/level5

输入 <script>alert(xss)</script> 查看回显 如下所示 能够发现script被恶意替换为scr_ipt 查看源代码 第一个输出点被转义了 所以没有利用价值了 第二个输出点如同刚才所言被进行了关键字的恶意替换操作 那没办法 我们只能继续尝试一下在标签内部构造一个新…