在项目中使用I2C接口传感器时要求有比较精确的延时,在网上搜了下,如果不想用中断SysTick定时器可以做到,找到如下资料:
主要仿照原子的《STM32不完全手册》。SYSTICK 的时钟固定为HCLK 时钟的1/8,在这里我们选用内部时钟源72M,所以SYSTICK的时钟为9M,即SYSTICK定时器以9M的频率递减。SysTick 主要包含CTRL、LOAD、VAL、CALIB 等4 个寄存器,
SysTick->CTRL
位段 | 名称 | 类型 | 复位值 | 描述 |
16 | COUNTFLAG | R | 0 | 如果在上次读本寄存器后systick已为0,则该位为1,若 读该位自动清零 |
2 | CLKSOURCE | RW | 0 | 0:外部时钟源 1:内部时钟 |
1 | TICKINT | RW | 0 | 0:减到0无动作;1:减到0产生systick异常请求 |
0 | ENABLE | RW | 0 | systick定时器使能位 |
SysTick-> LOAD
位段 | 名称 | 类型 | 复位值 | 描述 |
23:0 | RELOAD | RW | 0 | 减到0时被重新装载的值 |
SysTick-> VAL
位段 | 名称 | 类型 | 复位值 | 描述 |
23:0 | CURRENT | RW | 0 | 读取时返回当前倒计数的值,写则清零,同时还会清除在systick控制及状态寄存器中的COUNTFLAG 标志 |
SysTick-> CALIB 不常用,在这里我们也用不到,故不介绍了。
/*定时器初始化函数*/
void Delay_Init(u8t SYSCLK) //SYSCLK为系统时钟频率除以1000000后的值,例:如果系统时钟频率为72MHz,则调用该函数时此处的实参为72
{
SysTick->CTRL&=0xFFFFFFFB;
fac_us=SYSCLK/8;
fac_ms=(u16t)(fac_us*1000);
}
/*1微秒延时函数*/
void Delay_us(u32t nus)
{
u32t temp;
SysTick->LOAD=nus*fac_us;
SysTick->VAL=0x00;
SysTick->CTRL=0x01;
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&0x10000));
SysTick->CTRL=0x00;
SysTick->VAL=0x00;
}
/*1毫秒延时函数*/
void Delay_ms(u16t nms)
{
u32t temp;
SysTick->LOAD=(u32t)(nms*fac_ms);
SysTick->VAL=0x00;
SysTick->CTRL=0x01;
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&0x10000));
SysTick->CTRL=0x00;
SysTick->VAL=0x00;
}