定时器详解 -- 定时器中断、PWM输出 --stm32

news2024/10/6 12:24:42

STM32定时器使用

  • STM32定时器
    • 计数模式
    • 定时器工作原理
    • 基本定时器:TIM6、TIM7
      • 示例代码
      • 代码讲解
    • 通用定时器:TIM2、TIM3、TIM4、TIM5
    • 高级定时器:TIM1、TIM8
    • 定时器PWM输出原理
      • 通用定时器3控制通道1输出PWM脉冲
      • 代码
    • 总结
    • 参考资料

STM32定时器

STM32F103系列芯片拥有多种定时器,包括基本定时器、通用定时器和高级定时器,每种定时器都具有一些特定的功能。
在这里插入图片描述

计数模式

向上计数:计数器从0计数到自动重装载值(ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
向下计数:计数器从自动重装载值(ARR)开始向下计数到0,然后重新从自动重装载值(ARR)开始向下计数,并且产生一个计数器溢出事件。
向上向下双向计数(中央对齐模式):计数器从0开始计数到自动重装载值-1,产生一个计数器溢出事件,然后计数器从ARR开始向下计数,计数到1再次产生一个计数器溢出事件,以此往复。

定时器工作原理

STM32F103系统构架知:TIM1、8在APB2上,TIM2、3、4、5、6、7在APB1上,APB1操作速度限于36MHz,APB2操作于全速72MHz。
在这里插入图片描述

基本定时器:TIM6、TIM7

TIM6、TIM7定时器主要功能:16位自动重装载累加计算器,16位可编程预分频器(1~65536),触发DAC的同步电路、产生DMA中断请求。

基本定时器框图在这里插入图片描述
时钟源: STM32F103基本定时器的时钟源,可以使用内部时钟源或外部时钟源。当使用内部时钟源(CN_INT)时,计时器的时钟频率由STM32内部时钟提供。当使用外部时钟源时,计时器的时钟频率由外部时钟信号提供,可以使用外部晶体振荡器、RC振荡器等外部时钟源。

预分频器:PSC预分频寄存器,用于设定定时器时钟的分频系数。

CNT计数器:用于记录定时器的当前值,从0开始计数,当CNT到达ARR时计数器重新从0开始计数(向上计数模式)。

自动重装载寄存器:ARR用于设定计时器的计时时长,当CNT到达该值时自动重新计数。
在这里插入图片描述
如何定时呢?
首先确定TIM6\TIM7时钟源(内部时钟CK_INT)经APB1预分频后分频提供,如果APB1预分频系数是1则频率不变,在库函数中APB1预分频的系数是2,即PCLK1=36MHz,所以定时器的时钟频率TIMxCLK为72Mhz(36*2)

计数器计数的计算方式:

CK_CNT = TIMxCLK/(PSC+1)     //CK_CNT最大65536

PSC是预分频器值

定时时间计算(计数器的中断周期*中断的次数):

Tout = ((ARR+1)*(PSC+1))/TIMxCLK

假设需要计时1s产生一次中断(已知TIMxCLk为72MHz):
先设ARR值为9999(ARR+1就是10000)
1 = (10000(PSC+1))/72000000*
因此PSC=7199

所以CK_CNT计算有什么用?

假设PSC是7199 所以CN_CNK=1000(hz)的时钟  计数一次花费时间1/1000 = 0.0001s = 0.1ms
所以Tout = (ARR+1)*(0.0001) 已知定时1s = Tout  所以ARR = 9999

示例代码

使用定时器TIM6中断方法控制LED灯闪烁,设置定时器1s中断一次,中断服务函数中控制LED实现LED闪烁功能。

定时器头文件定义

#ifndef __TIME_H
#define __TIME_H

#include "stm32f10x.h"

#define TIM         TIM4    
#define TIM_CLK     RCC_APB1Periph_TIM4     //RCC时钟
#define TIM_ARR     10000-1                 //定义ARR值
#define TIM_PSC     7200-1                  //定义PSC值
#define TIM_IRQ     TIM4_IRQn               //定义中断编号
#define TIM_IRQHandler TIM4_IRQHandler      //重定义中断函数

void TIM_Init_Config(void);     

#endif /* __TIME_H */

定时器源文件

#include "bsp_time.h"

//中断优先级配置
void TIM_NVIC_Config(void){
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);             //设置优先级分组
    NVIC_InitStructure.NVIC_IRQChannel = TIM_IRQ;               //指定需要配置的中断信号
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   //先占优先级 1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          //从优先级   1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //使能NVIC
    NVIC_Init(&NVIC_InitStructure);                             //初始化NVIC寄存器
}


//定时器配置
void TIM_Init_Config(void){
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    RCC_APB1PeriphClockCmd(TIM_CLK, ENABLE);                    //开启TIM4定时器所对应的APB1总线时钟
    TIM_TimeBaseInitStruct.TIM_Prescaler = TIM_PSC;             //设置TIM4的预分频系数
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数模式设置为递增模式
    TIM_TimeBaseInitStruct.TIM_Period = TIM_ARR;                //设置TIM4自动重载寄存器的值,用于设定定时器的定时时长
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    //设置TIM4的时钟分割比,即分割细度
//    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM, &TIM_TimeBaseInitStruct);
    
    TIM_ITConfig(TIM, TIM_IT_Update, ENABLE);//使能TIM4的溢出中断,将TIM_IT_Update设置为ENABLE即可。这一步非常重要,否则定时器无法产生中断信号,不会触发相应的中断服务程序。
    
    TIM_NVIC_Config();
    
    TIM_Cmd(TIM, ENABLE);   //使能定时器 -- 开启定时器
}

中断函数

//"stm32f10x_it.c"源文件
void TIM_IRQHandler(void){
    if(TIM_GetITStatus(TIM, TIM_IT_Update)!= RESET){
        LED_TOGGLE;
        TIM_ClearITPendingBit(TIM, TIM_IT_Update);
    }
}

代码讲解

定时器结构体成员

/**
  * @brief  TIM Time Base Init structure definition
  * @note   This structure is used with all TIMx except for TIM6 and TIM7.    
  */


typedef struct
{
  uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                       This parameter can be a number between 0x0000 and 0xFFFF */


  uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.
                                       This parameter can be a value of @ref TIM_Counter_Mode */


  uint16_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                       Auto-Reload Register at the next update event.
                                       This parameter must be a number between 0x0000 and 0xFFFF.  */


  uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.
                                      This parameter can be a value of @ref TIM_Clock_Division_CKD */


  uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                       reaches zero, an update event is generated and counting restarts
                                       from the RCR value (N).
                                       This means in PWM mode that (N+1) corresponds to:
                                          - the number of PWM periods in edge-aligned mode
                                          - the number of half PWM period in center-aligned mode
                                       This parameter must be a number between 0x00 and 0xFF.
                                       @note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;

TIM_Prescaler:指分配器的预分频值,一般为一定的预定值,大小范围为0到65536
TIM_CounterMode:指定时器的计数模式,一般有递增和递减模式

#define TIM_CounterMode_Up                 ((uint16_t)0x0000)
#define TIM_CounterMode_Down               ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)

TIM_Period:定时器的自动重装载值,大小范围为0到65536
TIM_ClockDivision:TIM的时钟分割比,即分割细度
TIM_RepetitionCounter: 指定TIM1和TIM8定时器的重复计数器值。当重复计数器的值减少到0时,将会产生一个溢出事件,并将TIMx的计数器重新从重复计数器的值开始计数。

定时器初始化函数

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)    //x从1到17

TIMx:定时器选择,可从1到17

使能/失能中断溢出函数

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)    //x从1到17

开启/关闭定时器函数

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)    //x从1到17

定时器中断标志位获取和清除

FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);        //获取定时器中断标志状态,检查x定时器是否发生中断事件

                                                                           //TIM_FLAG是需要检测的中断标志
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);                  //清除定时器中断标志,将x定时器指定的中断标志清零

ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);              //获取定时器中断状态,检查x定时器是否产生中断信号
                                                                           //TIM_IT用于检测需要的中断源

void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);            //清除定时器的中断状态

定时器中断标志状态函数一般先于定时器中断状态函数使用,并且在启用中断之前使用它们以确保不会丢失年中断信号;定时器中断状态函数则用于在ISR(中断服务程序)中检查中断状态。

通用定时器:TIM2、TIM3、TIM4、TIM5

定时器时钟来源:

  • 内部定时器(CK_INT)
  • 外部时钟模式1:外部输入脚(TIx)
  • 外部时钟模式2:外部触发输入(ETR)
  • 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器作为另一个定时器的预分频器。

编程步骤:

  • 配置系统时钟
  • 配置NVIC
  • 配置定时器
  • 配置定时器中断服务函数

高级定时器:TIM1、TIM8

待补写

定时器PWM输出原理

PWM输出就是对外输出脉宽(占空比)可调的方波信号,信号频率由自动重装载寄存器ARR的值决定,占空比由比较寄存器CCR的值决定。

通用定时器3控制通道1输出PWM脉冲

在这里插入图片描述
从上图通用定时器框图可以看出一个定时器只有一个计数器,所以同一个定时器输出的PWM频率是一样的,可以改变的是占空比大小(可以通过改变比较寄存器改变占空比大小)。

查看定时器TIM3复用的引脚图,如下所示
在这里插入图片描述

代码

PWM头文件定义

#ifndef __PWM_H
#define __PWM_H
#include "stm32f10x.h"

#define PWM_TIM     TIM3
#define PWM_TIM_CLK RCC_APB1Periph_TIM3

#define PWM_TIM_GPIP_PORT   GPIOA
#define PWM_TIM_GPIO_CLK    RCC_APB2Periph_GPIOA
#define PWM_TIM_GPIO_Pin    GPIO_Pin_6

void PWM_TIM_Mode_Init(uint16_t freq, uint16_t duty);

#endif /* __PWM_H */

PWM源文件

#include "bsp_pwm.h"

/**
* @brief 初始化PWM的GPIO为复用模式
*
* @retval None
*/
void PWM_TIM_GPIO_Init(void){
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(PWM_TIM_GPIO_CLK, ENABLE);   //开启GPIOA时钟
    GPIO_InitStruct.GPIO_Pin = PWM_TIM_GPIO_Pin;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;        //设置引脚为复用推挽输出模式
    GPIO_Init(PWM_TIM_GPIP_PORT, &GPIO_InitStruct);     //初始化函数
}

/**
* @brief 初始化TIM为PWM输出模式
*
* @param freq PWM的频率(kHz)
* @param duty PWM的占空比(0~100)
* @retval None
*/
void PWM_TIM_Mode_Init(uint16_t freq, uint16_t duty){
    uint16_t arr = 36000/freq;      //freq是频率,单位是khz   //将频率
    PWM_TIM_GPIO_Init();
    //配置定时器
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_OCInitTypeDef TIM_OCInitStruct;
    //开启定时器时钟
    RCC_APB1PeriphClockCmd(PWM_TIM_CLK, ENABLE);
    
    TIM_TimeBaseInitStruct.TIM_Period = arr-1;
    TIM_TimeBaseInitStruct.TIM_Prescaler =1; //时钟预分频数  设置频率f = 36mhz  因为 t = TIMx_CLK/(PSC+1) --> t = 1/(36Mhz) --> f = 1/t  --> f = 1/t = 36mhz
    TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;   //采样分频
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;    //计数模式
    TIM_TimeBaseInit(PWM_TIM, &TIM_TimeBaseInitStruct);
    
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;      //设置为PWM1模式
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  //输出使能
    TIM_OCInitStruct.TIM_Pulse = (arr+1)*duty/100-1;    //设置占空比
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;      //输出极性
    //初始化PWM_TIM输出比较通道1
    TIM_OC1Init(PWM_TIM, &TIM_OCInitStruct);
    //使能OC1输出比较多预装载以及TIMx的配置寄存器
    TIM_OC1PreloadConfig(PWM_TIM, TIM_OCPreload_Enable);
    //开启定时器
    TIM_Cmd(PWM_TIM,ENABLE);
}

主程序

PWM_TIM_Mode_Init(20, 80);    //初始化时调用一次即可

TIM_OCInitTypeDef结构体讲解

typedef struct
{
  uint16_t TIM_OCMode;        /*!< 指定TIM输出比较的模式 */


  uint16_t TIM_OutputState;   /*!< 指定TIM输出比较通道的输出状态(开启或关闭) */


  uint16_t TIM_OutputNState;  /*!< 指定TIM互补输出比较通道的输出状态(开启或者关闭),只对定时器TIM1、TIM8有效 */


  uint16_t TIM_Pulse;         /*!< 指定TIM输出比较通道的占空比 */


  uint16_t TIM_OCPolarity;    /*!< 指定TIM输出比较通道的极性 */


  uint16_t TIM_OCNPolarity;   /*!< 指定TIM互补输出比较通道的极性 */


  uint16_t TIM_OCIdleState;   /*!< 指定TIM输出比较通道在闲置或者空档时的输出电平状态 */


  uint16_t TIM_OCNIdleState;  /*!< 指定TIM互补输出比较通道在空档状态下输出的电平状态 */
} TIM_OCInitTypeDef;

ARR决定PWM周期
CCRx决定PWM占空比大小
ARR计算:

由Tout = ((ARR+1)*(PSC+1))/TIMxCLK           --   已知TIMxCLK = 72Mhz且PSC设置为1
因此T=(arr+1)/36            -- 已知 t = 1/f
所以1/f = (arr+1)/36  
得 arr = 36000/f

总结

要多用,要多用!

参考资料

https://www.bilibili.com/video/BV1b54y1m71K/?spm_id_from=333.337.search-card.all.click&vd_source=101ae2594bcc6dbee11cc6670869bc2e

https://blog.csdn.net/qq_44016222/article/details/123507270?spm=1001.2100.3001.7377&utm_medium=distribute.pc_feed_blog_category.none-task-blog-classify_tag-20-123507270-null-null.nonecase&depth_1-utm_source=distribute.pc_feed_blog_category.none-task-blog-classify_tag-20-123507270-null-null.nonecase

https://www.guyuehome.com/39703#%E4%B8%89%E3%80%81%E5%AE%9A%E6%97%B6%E5%99%A8%E8%BE%93%E5%87%BAPWM

https://blog.csdn.net/qq_38410730/article/details/79996222

在这里插入图片描述

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

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

相关文章

加密与解密 调试篇 动态调试技术 (三)-OllyDbg 插件 Run/Hit 符号调试 加载程序

目录 插件 这里给出一个命令行插件 Run Trace 运行 Hit Trace 符号调试 符号格式 1.SYM格式 2.COFF格式 3.CodeView格式 4.PDB格式 5.DBG格式 6.MAP文件 创建调试文件 加载程序 1.CreateProcess 2.将OllyDbg附加到一个正在运行的程序上 插件 OllyDbg允许插件 …

1计算机网络体系结构_1.1计算机网络概述

1.1.1计网_概念 概念&#xff1a; 计网是一个 将【分散的、具有独立功能的】计算机系统&#xff0c;通过【通信设备与线路】连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。简言之&#xff0c;计算机网络就是一些 互连的、自治的 计算机系统 的 集合。 …

excel函数采集,截取特殊符号前面/后面数据

截取前面 LEFT(I2,FIND("-",I2)-1) 截取后面 MID(I2,FIND("-",I2)1,99) 房贷利率计算公司&#xff0c;等额本金 (B2-G2*A2)*F2*0.01 Excel常用电子表格公式大全  一、Excel基本公式   1、查找重复内容公式&#xff1a;IF(COUNTIF(A:A,A2)>1,&qu…

国密算法解析

国密算法即国家密码局认定的国产密码算法。 国密算法是商用密码&#xff0c;仅能用于商业用途。国密算法是一套标准&#xff0c;由国家密码局制定的规范&#xff0c;凡是符合的&#xff0c;都可以称之为国密算法。国密算法暂无官方的代码实现&#xff0c;企业可以自己编码实现…

2022年五一杯数学建模A题血管机器人的订购与生物学习解题全过程及论文和程序

2022年五一杯数学建模A题 血管机器人的订购与生物学习 原题再现&#xff1a; 随着微机电系统的发展&#xff0c;人类已经可以加工越来越小的机器。这些机器小到一定程度就可以放进血管开展疾病治疗&#xff0c;这就是血管机器人。血管机器人可以携带药物放入血管里定点治疗与…

信号调制的工作原理

要理解如何进行无线数据传输&#xff0c;我们需要了解&#xff1a; 什么是频率&#xff1f; 信息/数据信号 时间表示 频率表示&#xff0c;为什么它很重要&#xff1f; 滤波器如何工作&#xff1f; FCC通信频段 调制和解调 这些主题可能您在大学专业课上学过&#xff0c…

uboot下的mw写内存和md显示内存命令以及nand命令

配置uboot参数 setenv ipaddr 192.168.0.10;setenv serverip 192.168.0.40;setenv gatewayip 192.168.0.1;setenv netmask 255.255.255.0 setenv bootargs mem512M consolettyAMA0,115200 root/dev/mtdblock2 rootfstypeyaffs2 rw init/init mtdpartshinand:1M(boot),4M(kern…

面试offer收割机,爆肝整理高频软件测试面试题(带答案)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 软件测试面试题&am…

excel 给合并的单元格进行序号填充

一、问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 在使用excel 的时候&#xff0c;是否遇到过要给合并单元格排序的情况&#xff0c;下拉会显示需要相同的单元格才行&#xff0c;如图&#xff1a; 二、解决方案 目的是给单元格计数&#xff0c;所以使用…

Module not found: Error: Can‘t resolve ‘fs‘ in ‘/root/workspace/

项目发版时 因为webpack5 不会自动引入polyfills 导致报了一系列错&#xff0c; 按照提示做如下配置 externals 官网文档解释的很清楚&#xff0c;就是webpack可以不处理应用的某些依赖库&#xff0c;使用externals配置后&#xff0c;依旧可以在代码中通过CMD、AMD或者wi…

打车/代驾/跑腿小程序源码司机入住uniapp/thinkphp

开发代驾顺风车货运 客户端&#xff1a;Uniapp 开发 司机端&#xff1a;Uniapp 开发 后台&#xff1a;thinkphp5 框架 数据库&#xff1a;MySQL 打车/代驾/跑腿小程序源码司机入住uniapp/thinkphp 为什么用UNIAPP开发&#xff1f; UNIAPP框架简单&#xff0c;学习成本低…

Spring(IOC,DI,事务)属性

Spring&#xff08;IOC&#xff0c;DI&#xff0c;事务&#xff09;属性 IOC 概念 Inverse Of Controll&#xff1a;控制反转&#xff1b;反转了依赖关系的满足方式&#xff0c;由之前的自己创建依赖对象&#xff0c;变为由工厂推送。(变主动为被动&#xff0c;即反转)解决了…

1_5 optical_flow

采用特征点法做VO存在耗时较大的问题&#xff0c;一般耗时情况&#xff1a;如下 (1) 在图像中提取特征点并计算特征描述&#xff0c; 非常耗时 ~10ms ORB&#xff0c;shift耗时更多&#xff1b; (2) 在不同图像中寻找特征匹配&#xff0c; 非常耗时 …

day43|动态规划5-不同0-1背包的问题形态

关键点&#xff1a; 找到前后两种状态的依赖关系 经典0-1背包&#xff1a; 给定一个背包&#xff0c;问装满该背包的最大价值。分割等和子集&#xff1a; 给定一个背包&#xff0c;能不能装满该背包&#xff08;将重量抽象成价值&#xff09;最后一块石头重量&#xff1a; 给一…

如何快速图片压缩指定大小?图片压缩到200k以内的方法

图片压缩到200k以内的介绍 在现代社交媒体和网页设计中&#xff0c;高质量的图片是必不可少的。但是&#xff0c;大型图像文件可能会导致页面加载时间过长&#xff0c;从而影响用户体验。这时就需要使用图片压缩技术来将图片文件大小减小到合理的范围内。其中&#xff0c;将图…

稳健地对时间序列光学卫星图像进行配准教程

一、引言 几何误差会导致连续卫星图像采集之间的错位&#xff0c;进而影响土地监测和变化检测分析。在这篇博客文章中&#xff0c;我们研究了如何稳健地对时间序列光学卫星图像进行配准&#xff0c;以减少这种错位的影响。 在本篇博客的末尾&#xff0c;给出用Python配准大区域…

【TES710D-EXT】基于复旦微的FMQL10S400全国产化ARM核心模块之扩展板

板卡概述 TES710D-EXT是专门针对我司TES710D&#xff08;基于复旦微FMQL10S400的全国产化ARM核心板&#xff09;的测试扩展板。 FMQL10S400是复旦微电子研制的全可编程融合芯片&#xff0c;在单芯片内集成了具有丰富特点的四核处理器&#xff08;PS&#xff09;和可编程逻辑&am…

B/S架构与C/S架构的区别

B/S与C/S区别&#xff1a; 1、c/s架构主要应用于局域网内&#xff0c;而b/s架构主要应用于广域网中&#xff1b; 2、c/s架构一般面向相对固定的用户群&#xff0c;对信息安全的控制能力很强&#xff0c;而b/s架构对安全的控制能力相对弱&#xff1b; 3、B/S架构维护升级比较简单…

考研算法复试刷题第20天:Dijkstra求最短路 【有向图的最短路径问题】

Dijkstra求最短路 我们先来说说这道算法的过程&#xff1a; 和上道题不同的是我们这次是求一个有向图到最终节点的最短距离&#xff0c;所以其策略也有所不同。我们先手动模拟一下过程吧假如有4个点&#xff0c;有他们之间有五条边&#xff0c;那么我们如何来求其1到4的最短路…

【Daily Share】觉得浏览器low?手写一个浏览器扩展程序,让自己的浏览器变得与众不同!!!!

浏览器扩展 概念 扩展为浏览器添加了特性与功能。它通过我们所熟悉的 Web 技术-HTML&#xff0c;CSS 还有 JavaScript 来创建。扩展可以利用与 JavaScript 相同的网页 API&#xff0c;但是扩展也可以访问它自己专有的 JavaScript API。这意味着&#xff0c;和在网页里编码相比…