本文参考 如有侵权请联系删除
参考代码是正点原子的ov2640的摄像头例程代码
了解systick的寄存器
/*******************************************************************************
* 函 数 名 : SysTick_Init
* 函数功能 : SysTick初始化,SYSTICK的时钟固定为AHB时钟的1/8
* 输 入 : SYSCLK:系统时钟频率
* 输 出 : 无
*******************************************************************************/
void SysTick_Init(u8 SYSCLK)
{SystemCoreClock
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SYSCLK/8; //SYSCLK的8分频 保存1us所需的计数次数
fac_ms=(u16)fac_us*1000; //每个ms需要的systick时钟数
}
/*******************************************************************************
* 函 数 名 : delay_us
* 函数功能 : us延时,
* 输 入 : nus:要延时的us数
注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)
* 输 出 : 无
*******************************************************************************/
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=0x01 ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~0x01; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
分别用了systick的CTRL、LOAD、VAL寄存器
CTRL: 控制和状态寄存器
LOAD:放置重装载的值,也就是一个周期的大小。
VAL:放置倒计时值
解析代码:
先在systick_Init中求出当前时钟频率下1us要计时几次(fac_us),清空VAL的计时值,将需要延时的时间赋值入LOAD,将CTRL的0位置1(开始计时),循环调取CTRL的值,如果上次读取的时候VAL的值为0,则CTRL的第16位置1,所以判断定时器如果为打开状态且CTRL第16位不为1着循环读取CTRL的值,直至CTRL的值为1跳出该do——while循环。