STM32-SysTick定时器
1 SysTick定时器简介
什么是SysTick?
SysTick定时器也叫SysTick滴答定时器,它是Cortex-M3内核的一个外设,被嵌入在NVIC 中,用于产生SYSTICK异常(异常号:15)。SysTick是一个24位的倒计数系统节拍计时器System Tick timer,每计数一次所需时间为1/SYSTICK,SYSTICK是系统定时器时钟,它可以直接取系统时钟,还可以通过系统时钟8分频后获取。当计数到0时,它就会从Load寄存器中自动重装定时初值,重新向下递减计数,如此循环往复。如果开启SysTick中断的话,当定时器计数到0,将产生一个中断信号。因此只要知道计数的次数就可以准确得到它的延时时间。只要不把CTRL寄存器中的ENABLE清0,它就永不停止。
SysTick作用?
在单任务引用程序中,因为其架构就决定了它执行任务的串行性,这就引出一个问题:当某个任务出现问题时,就会牵连到后续的任务,进而导致整个系统崩溃。要解决这个问题,可以使用实时操作系统(RTOS)。因为RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。微控制器的定时器资源一般比较丰富,比如STM32存在8个定时器,为啥还要再提供一个SYSTICK?原因就是所有基于ARM Cortex_M3内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。而使用RTOS的第一项工作往往就是将其移植到开发人员的硬件平台上,由于SYSTICK的存在无疑降低了移植的难度。SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。
2 SysTick时钟的选择
SysTick寄存器说明在《Cortex-M3权威指南》(SysTick定时器章节)有说明:
SysTick->CTRL:控制和状态寄存器
SysTick->LOAD:重装载寄存器
SysTick->VAL:当前值寄存器
SysTick->CALIB:校准值寄存器
用户可以在位于Cortex_M3处理器系统控制单元中的系统节拍定时器控制和状态寄存器(SysTick control and status register ,SCSR)选择SysTick 时钟源。如将SCSR中的CLKSOURCE位置位,SysTick会在CPU频率下运行;而将CLKSOUCE位清除则SysTick会以CPU主频的1/8频率运行。
在3.5版本的库函数中与SysTick相关的函数有两个:第一个,SysTick_Config(uint32_t ticks),在core_cm3.h头文件中进行定义的。第二个,void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),在misc.c文件中定义的。
在core_cm3.h头文件中进行定义的SysTick_Config(uint32_t ticks)函数主要的作用有一下方面:
1、初始化systick
2、打开systick
3、打开systick的中断并设置优先级
4、返回一个0代表成功或1代表失败
Uint32_t ticks 即为重装值,这个函数默认使用的时钟源是AHB,即不分频。要想分频,调用void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),但是要注意函数调用的次序,先调用SysTick_Config(uint32_t ticks),后调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)。
在misc.c头文件中进行定义的void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)函数主要的作用有一下方面:
1、选择systick的时钟源,AHB时钟或AHB的8分频
2、库函数中默认使用的是AHB时钟(在SysTick_Config()函数中设置),即72MHz
1)在core_cm3.h头文件中uint32_t SysTick_Config(uint32_t ticks)函数说明:
/*** @摘要 初始化并启动SysTick计数器及其中断。** @参数 ticks 两个中断之间的滴答数* @返回值 1 = failed, 0 = successful** 初始化系统滴答计时器及其中断,并在自由运行模式下启动系统滴答计时器/计数器,以产生定时中断。*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* 不可能的重新加载值,重装载值必须小于0XFF FFFF,因为这是一个24位的递减计数器 */SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* 设置重装载值寄存器,SysTick_LOAD_RELOAD_Msk定义见后面*/NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* 设置Cortex-M3系统中断优先级 */SysTick->VAL = 0; /* 加载SysTick计数器值 */SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | //配置CTRL寄存器,选择内核时钟FCLK为时钟源(STM32 的FCLK为72M)SysTick_CTRL_TICKINT_Msk | //开启SysTick中断SysTick_CTRL_ENABLE_Msk; //SysTick使能 return (0); /* 初始化成功 */
}
在core_cm3.h头文件SysTick相关的寄存器定义:
typedef struct
{__IO uint32_t CTRL; /* Offset: 0x00 SysTick控制和状态寄存器 */__IO uint32_t LOAD; /* Offset: 0x04 SysTick重新加载值寄存器 */__IO uint32_t VAL; /* Offset: 0x08 SysTick当前值寄存器 */__I uint32_t CALIB; /* Offset: 0x0C SysTick校准寄存器 */
} SysTick_Type;
在core_cm3.h头文件SysTick寄存器相关的位的宏定义:
/* SysTick控制/状态寄存器定义 */
#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1ul << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1ul << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1ul << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1ul << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask *//* SysTick重新加载寄存器定义 */
#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask *//* SysTick当前寄存器定义 */
#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFul << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask *//* SysTick校准寄存器定义 */
#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk (1ul << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk (1ul << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFul << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */
2)在core_cm3.h头文件中void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)函数说明:
/*** @摘要 配置SysTick时钟源* @参数 SysTick_CLKSource: SysTick时钟源。* 该参数可以是以下值之一:* @arg SysTick_CLKSource_HCLK_Div8: SysTick时钟源为AHB时钟除以8。* @arg SysTick_CLKSource_HCLK: 选择AHB时钟作为SysTick时钟源。* @返回值 无*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{/* 检查参数 */assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));if (SysTick_CLKSource == SysTick_CLKSource_HCLK){SysTick->CTRL |= SysTick_CLKSource_HCLK;}else{SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;}
}
SysTick时钟源的定义:
#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) //将控制状态寄存器的第二位置0,即用外部时钟源
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) //将控制状态寄存器的第二位置1,即用内核时钟
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \((SOURCE) == SysTick_CLKSource_HCLK_Div8))
3 Systick使用实践
Systick定时时间的设定:
重装载值=systick 时钟频率(Hz) X 想要的定时时间(S)
如果时钟频率为:AHB的8分频;AHB=72MHz那么systick的时钟频率为72/8MHz=9MHz。若要定时1秒,则重装载值=9000000X1=9000000,调用函数:SysTick_Config(9000000X1)。若要定时1毫秒,重状态值=9000000X0.001=9000,调用函数:SysTick_Config(9000000/1000);
Systick的中断处理函数:
在startup_stm32f10x_hd.s启动文件中有定义:DCD SysTick_Handler ; SysTick Handler
根据需要直接编写中断处理函数即可:Void SysTick_Handler (void)
注意:如果在工程中,加入了stm32f10x_it.c,而又在主函数中编写中断函数,则会报错。因为在stm32f10x_it.c文件中,也有这个中断函数的声明,只是内容是空的。
/*** @摘要 这个函数处理SysTick Handler。* @参数 无* @返回值 无*/
void SysTick_Handler(void)
{
}
中断优先级的修改:
在调用SysTick_Config(uint32_t ticks)之后,调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)。这个函数在core_cm3.h头文件中。具体内容如下:
/**
* @摘要 设置中断的优先级
* @参数 IRQn 用于设置优先级的中断数
* @参数 priority 设定的优先级
*为指定的中断设置优先级。中断号可以是正数来指定外部(设备特定的)中断,也可以是负数来指定内部(核心)中断。
* 注释: 不能为每个核心中断设置优先级。
*/
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{if(IRQn < 0) {SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* 设置Cortex-M3系统中断优先级 */else {NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* 设置Cortex-M3系统中断优先级 */
}
下面以一个实例来说明:利用systick来实现以1秒的时间间隔,闪亮一个LED指示灯,指示灯接在GPIOA.8,低电平点亮。
#include "stm32f10x.h"
//函数声明
void GPIO_Configuration(void); //设置GPIOA.8端口
u32 t; //定义一个全局变量
int main(void)
{// SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);SysTick_Config(9000000);SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);GPIO_Configuration();while(1);
}//GPIOA.8设置函数
void GPIO_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStruct; //定义一个端口初始化结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打开GPIOA口时钟GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //设置为推挽输出GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //设置输出频率50MGPIO_InitStruct.GPIO_Pin=GPIO_Pin_8; //指定第8脚GPIO_Init(GPIOA,&GPIO_InitStruct); //初始化GPIOA.8 GPIO_SetBits( GPIOA, GPIO_Pin_8); //置高GPIOA.8,关闭LED
}
//systick中断函数
void SysTick_Handler(void)
{
t++;if(t>=1){if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==1){GPIO_ResetBits( GPIOA, GPIO_Pin_8);} }if(t>=2){if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==0){GPIO_SetBits( GPIOA, GPIO_Pin_8);}t=0;}
}
以上基本讲完了,下面是我在网上看到的一些其他理解。
基于STM32F10x V3.5.0库如何操作Systick定时器呢?首先:STM32 的内核库已经提供了这个功能。只要配置SysTick_Config()即可实现。看下面的程序段:
/*
* 函数名:SysTick_Init
* 描述 :启动系统滴答定时器 SysTick
* 输入 : 无
* 输出 :无
* 调用 : 外部调用
*/
void SysTick_Init(void)
{if(SysTick_Config(SystemCoreClock/1000)) //1ms定时器{while(1);}//SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //若无法启动则关闭
}
SysTick_Config()的参数,其实就是一个时钟次数,叫SysTick重装定时器的值。意思就是我要多少个1/fosc 时间后中断一下。
根据学过的物理中的时间与频率的公式:fosc=1/T T=1/fosc ,fosc为系统的频率。如果STM32时钟频率为:72MHz,每次的时间为:T=1/72MHz。1秒钟为:1/(每次的时间)=1/(1/72MHz)=72 000 000次。1MHz是:1000 000。反过来讲。SysTick_Config(72000)代表:72000*(1/72MHz)=1/1000=1(ms)。即定时为1ms。如果需要1S,可以通过设置一个全局变量,然后定初值得为1000,这样,每个systick中断一次,这个全局变量减1,减到0,即systick中断1000次,时间为:1ms*1000=1S。从而实现1S的定时。因为SysTick定时器是:24位的,最大定时时间为:2的24次方*(1/72MHz)的时间,这里系统频率为:72MHz的情况下。
如何使用这个Systick用于程序设计上的延时或是定时作用呢?如下:__IO uint32_t TimingDelay; 定义一个全局变量,注意类型为 volatile的。volatile的作用: 作为指令关键字,确保本条指令不会因为编译器的优化而省略,且要求每次直接读值,然后定义一个延时或是定时函数:
/*
* 函数名:Delay_ms
* 描述 :ms延时程序,1ms为一个单位
* 输入 : - nTime
* 输出 :无
* 示例 : Delay_ms(1) 实现的延时为:1*ms=1ms
* 调用 :外部调用
*/
void Delay_ms(uint16_t nTime)
{TimingDelay = nTime;//使能系统滴答定时器while(TimingDelay !=0);
}
还要在系统的中断函数文件:stm32f10x_it.c/h 里面,修改系统自带的 SysTick 函数。这个函数要么没有声明或是为空操作。这里加入定时延时里的处理。即中断后,全局变量做个延时处理即可。在stm32f10x_it.c里修改如下:添加外部的声明:extern __IO uint32_t TimingDelay; 修改这个函数:SysTick_Handler ,这是系统的关于SysTick_Handler的中断服务程序名,在启动文件里如:startup_stm32f10x_hd.s 有它的定义的名字。不要弄错了。否则无法中断处理。
/*** @摘要 这个函数处理SysTick Handler。* @参数 无* @返回值 无*/
void SysTick_Handler(void)
{
if (TimingDelay != 0x00){ TimingDelay--; }
}
以上,即定义配置好了Systick定时器。如何使用呢?很简单。Delay_ms(500); 即为延时500ms。当然,使用前,请先初始化:SysTick_Init();否则无法使用并影响后续的程序运行,这个很重要,就像打开了串口中断,你不清标志位,也同样在接收字符后,CPU中断在那里,而不能继续执行!。使用外设功能,需要初始化!
4 配置延时函数(systick定时器)
4.1 delay_init函数
该函数初始化了两个重要参数:fac_us和fac_ms,同时将SysTick是时钟源配置为外部时钟,具体代码如下:
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init()
{//选择外部时钟 HCLK/8SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);fac_us = SystemCoreClock/8000000; //为系统时钟的1/8fac_ms = fac_us * 1000; //1ms = 1us * 1000
}
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 这里把SysTick的时钟配置为外部时钟,要注意的是SysTick 的时钟源自与HCLK的8分频,如果外部晶振为8MHz,然后倍频到72MHz,那么SysTick的时钟就是72/8 = 9MHz,即是SysTick的计数器每减1,时间就过去了1/9us。所以fac_us = SystemCoreClock/8000000; 表示过了1us,可能有部分人对这句话不太理解,下面做个大概解释,上面说到systick为系统时钟的8分频,假设系统时钟倍频到72MHz,8分频即为9MHz,所以每一个systick时钟周期的时间为1/9us,SystemCoreClock/8000000 的意思是算出 1us 需要几个 systick 周期,即72000000/8000000 = 9个systick时钟周期,fac_us = 9 * 1/9us = 1us 没毛病,还没看懂的多看几遍就理解了,接下来的fac_ms = fac_us * 1000,1ms等于1000 us 这个不用怎么解释了。
该注意的是delay_init函数需要在main函数的开头调用作为对systick定时器的配置,fac_us和fac_ms变量需要在定义为全局变量,因为接下来的两个函数还将用到。
static uint8_t fac_us; //us延时倍乘数
static uint16_t fac_ms; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
4.2 delay_us函数
该函数用来延时指定的us,其参数nus为要延时的毫秒数,代码如下:
//功能: delay_us
//参数: nus
void delay_us(uint32_t nus)
{uint32_t temp;SysTick->LOAD = nus * fac_us; //时间加载 SysTick->VAL = 0x00; //清空计数器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; //清空计数器
}
以上是配置SysTick的寄存器实现的延时,有兴趣的可以参阅core_cm3.h头文件CTRL、LOAD、VAL、CALIB
这4个寄存器。
4.3 delay_ms函数
该函数用来延时指定的ms,其参数nms为要延时的毫秒数,代码如下:
//功能: delay_ms
//参数: nms 注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms,对72M条件下,nms<=1864
void delay_ms(uint16_t nms)
{uint32_t temp;SysTick->LOAD = nms * fac_ms; //时间加载(SysTick->LOAD为24bit)SysTick->VAL = 0x00; //清空计数器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.h
加入上面3个函数的声明,然后在main函数或者其他函数中直接调用 delay_us()
函数和 delay_ms()
函数就可以了。
5 总结
1)要使用systick定时器,只需调用SysTick_Config(uint32_t ticks)函数即可,函数自动完成:重装载值的装载,时钟源选择,计数寄存器复位,中断优先级的设置(最低),开中断,开始计数的工作。
2)要修改时钟源调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),也可按照SysTick_Config()中默认设置FCLK不变。
3)要修改中断优先级调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
应用说明:
1)因systick是一个24位的定时器,故重装值最大值为2的24次方=16 777 215,要注意不要超出这个值。
2)systick是cortex_m3的标配,不是外设。故不需要在RCC寄存器组打开他的时钟。
3)每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。
4)采用使用库函数的方法,只能采用中断的方法响应定时器计时时间到,如要采用查询的方法,那只能采用设置systick的寄存器的方法,具体操作以后再做分析。
STM32-SysTick定时器相关推荐
- stm32 systick定时器
systick定时器是系统滴答定时器,一个24位的倒计时定时器,计到0时,将从RELOAD寄存器中自动装载定时初值,只要不把它在Systick控制及状态寄存器中的使能位清楚,就永不停息,即使在睡眠状态 ...
- STM32——SysTick 定时器讲解(代码)
一.SysTick-系统定时器简介 SysTick-系统定时器是属于CM3内核中的一个外设,内嵌在NVIC中.系统定时器是一个24bit的向下递减的计数器, 计数器每计数一次的时间为1/SYSCLK, ...
- STM32延时函数的四种方法:普通延时(2种)、SysTick 定时器延时(2种)
STM32延时函数的三种方法:普通延时.SysTick 定时器延时(1.中断方式:2.非中断方式) 单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us( )和毫秒级delay_ ...
- STM32开发 -- Systick定时器
如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/81630311 一.Systick定时器介绍 参看:STM32菜鸟成长记录-系 ...
- 【STM32】SysTick定时器
00. 目录 文章目录 00. 目录 01. SysTick定时器概述 02. SysTick定时器寄存器描述 03. 相关函数实现 04. 延时函数实现 05. 应用示例 06. 附录 07. 声明 ...
- STM32系统定时器SysTick(只能向下递减)延时闪烁灯
参考:stm32 系统定时器 SysTick 作者:点灯小哥 发布时间: 2021-03-10 13:46:00 网址:https://blog.csdn.net/weixin_46016743/ar ...
- STM32学习及应用笔记一:SysTick定时器学习及应用
这几年一直使用STM32的MCU,对ARM内核的SysTick计时器也经常使用,但几乎没有仔细了解过.最近正好要在移植一个新的操作系统时接触到了这块,据比较深入的了解了一下. 1.SysTick ...
- STM32系统定时器SysTick
1. SysTick系统定时器概述 学习完STM32的中断,下来就要学习STM32的定时器.就像电话最基本的功能是与人通话一样,定时器最基本的功能就是定时(STM32有些定时器的功能强大得超乎想象,当 ...
- STM32的SysTick定时器记录一篇
CSDN博客主页 ID : Eterlove 一笔一画,记录我的学习生活!站在巨人的肩上Standing on Shoulders of Giants! 该文章为原创,转载请注明出处和作者! 前言 我 ...
- STM32 SysTick 滴答定时器原理及应用
SysTick滴答定时器 一.功能 SysTick定时器是一个简单的定时器,CM3\CM4内核芯片都具备此定时器.SysTick定时器常用来做延时,采用实时系统时则用来做系统时钟. 无论用作延时还是用 ...
最新文章
- 剑指offer-调整数组顺序使奇数位于偶数前面13
- 树转换为二叉树小技巧
- 使用pagination分页插件实现Ajax动态分页
- 后台代码和前台显示一样a href=' + URL + ' 使用转义字符
- oracle误删除记录或者表的处理方法
- PDF转HTML常用方法分享
- 计算机与信息科学相关教材,AdobeIllustrator实例教程/计算机与信息科学系列规划教材...
- 腐蚀rust服务器命令_腐蚀rust服务器命令一览 腐蚀rust有哪些服务器命令
- css+html投票系统,网上在线投票系统的设计与实现.doc
- SSL1653 数字游戏
- Firefox火狐浏览器插件大全
- 010Java知识点小结--抽象类、接口
- 四成单身、平均年薪19万、最爱买房,原来真实的程序员是这个样子的…...
- @生存技巧!程序员如何应对女朋友的“小脾气”(最后附女友靓照)
- 片上总线Wishbone 学习(三)Wishbone互联的类型
- Unity 第三方SDK框架接入 (Android Studio)
- 响应式布局的实现方法
- yarn unlink 简单使用
- 语义分割--Dilated Residual Networks
- long自动转为float类型
热门文章
- oracle 内部表连接方式,ORACLE 表连接方式
- Java 并发编程之 ThreadLocal 线程局部变量
- Redis HyperLogLog
- linux 如何查看远程代码分支,linux看git 创建分支、删除本地分支、查看远程分支、本地分支例子...
- Flink Java 使用map reduce实现wordcount
- Mac 安装配置 chromedriver
- 计算机图形学在线作业,电子科大16秋《计算机图形学》在线作业3答案
- java volatile关键字的作用_java volatile关键字作用及使用场景详解
- java字符串拼接_字符串拼接,什么时候会走StringBuilder?
- 浅谈密码学中数论基础