rikirobot——millisecondtime.c延时

#ifdef __cplusplus//为了在C++代码中调用用C写成的库文件,就需要用extern"C"来告诉编译器:这是一个用C写成的库文件,请用C的方式来链接它们。
extern "C" {
#endif

#include "millisecondtimer.h"

volatile uint32_t _counter;//volatile确保本条指令不会因编译器的优化而省略,且要求每次直接读值。

void initialise(void) //初始化
{
	_counter = 0;
	SysTick_Config(SystemCoreClock / 1000);//1ms定时器
}

void delay(uint32_t millis) 
{ 
	uint32_t target;
	
	target = _counter + millis;
	while(_counter < target);
} 
void delay_us(uint32_t uillis)
{ 
	uint32_t target;
  SysTick_Config(SystemCoreClock / 100000);
	target = _counter + uillis;
	while(_counter < target);
}
void SysTick_Handler(void) 
{
	_counter++;
}

uint32_t millis(void) 
{
	return _counter;
}

void reset(void) 
{
	_counter = 0;
}

#ifdef __cplusplus
}
#endif


volatile
1> 编译器的优化

在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。

当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。

当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。

2>volatile
“直接存取原始内存地址”
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。
例如:
volatile int i=10;
int j = i;

int k = i;
volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。
而 优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。
_SysTick_Config
操作系统的多任务,在微观上,CPU对多任务的管理是分时的。每个任务都给一定的时间片,就是把时间分成N个等份,优先级高或是重要的任务多占几个时间片,优先级低的或是不重要的任务就少占几个时间片。大部分嵌入式操作系统基于时间片的。如ucos。

 if(SysTick_Config(SystemCoreClock/1000))

含义
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
如果需要1S则,可以统一设置一个全局变量,然后定初值得为1000,这样,每个systick中断一次,这个全局变量减1,减到0,即systick中断1000次,时间
为:1ms*1000=1S。从而实现1S的定时。

你可能感兴趣的:(rikirobot——millisecondtime.c延时)