网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
SysTick Control and Status Register
更多寄存器详细介绍,请参考文档Cortex™-M3 r1p1 技术参考手册(TRM),这里不在一一列举。
SysTick_Config() 函数是一个 CMSIS 函数,它通过配置SysTick Reload寄存器,其值作为函数参数传递。
//core\_cm3.h P1694行~P1705行
static __INLINE uint32_t SysTick\_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /\* Reload value impossible \*/
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /\* set reload register \*/
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /\* set Priority for Cortex-M0 System Interrupts \*/
SysTick->VAL = 0; /\* Load the SysTick Counter Value \*/
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /\* Enable SysTick IRQ and SysTick Timer \*/
return (0); /\* Function successful \*/
}
3.配置SysTick定时器的步骤
1.配置时钟源
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
//在misc.c文件
void SysTick\_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
/\* Check the parameters \*/
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;
}
}
2.计算重载值
Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s)
3.启用 SysTick 中断
4.使能SysTick 计数器
4.程序代码(注释详细)
#include "stm32f10x.h" //包含需要的头文件
#include "delay.h"
/\*-------------------------------------------------\*/
/\*函数名:初始化延迟计数器函数 \*/
/\*参 数:无 \*/
/\*返回值:无 \*/
/\*-------------------------------------------------\*/
void Delay\_Init(void)
{
SysTick\_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//SysTick\_CLKSource\_HCLK\_Div8 = 8 表示分频系数
//因为分频系数我们设置为8,所以SysTick(滴答时钟)的频率是主频率的1/8
//通常主频率为最大的72M,那么SysTick的频率是9M
//那么SysTick计数器的1个数,代表(1/9)us
}
/\*-------------------------------------------------\*/
/\*函数名:延迟微秒函数 \*/
/\*参 数:us:延时多少微秒 \*/
/\*返回值:无 \*/
/\*-------------------------------------------------\*/
void delay\_us(unsigned int us)
{
unsigned int temp; //定义一个变量待用
SysTick->LOAD=us\*9; //计数器的重载值,要注意SysTick是倒数计数的
//SysTick计数器每倒数一个数是1/9微秒,所以我们用us\*9,就是计数器的重载值
SysTick->VAL=0x00; //清空当前计数器的值
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能SysTick计数器,重载值加载到计数器中,开始倒数计数
do{
temp=SysTick->CTRL; //循环读取SysTick状态寄存器,用于判断计时结束与否
}while(temp&0x01&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
}
/\*-------------------------------------------------\*/
/\*函数名:延迟毫秒函数 \*/
/\*参 数:ms:延时多少毫秒 \*/
/\*返回值:无 \*/
/\*-------------------------------------------------\*/
void delay\_ms(unsigned int ms)
{
//我们首先注意一个问题SysTick时钟计数器是24位的,9M频率下,总共能延时1864.135ms
//所有我们以1800为界限,小于1800的延时一次计数就行,大于1800的多次计数
unsigned char i; //定义一个变量待用
unsigned int temp; //定义一个变量待用
/\*-----------if判断,小于1800ms延时的情况,执行if分支------------------\*/
if(ms<1800){
SysTick->LOAD=(unsigned int)ms\*9\*1000; //计数器的重载值,要注意SysTick是倒数计数的
//SysTick计1个数是1/9微秒,换算成ms的话,乘以9再乘以1000,就是计数器的重载值
SysTick->VAL=0x00; //清空当前计数器的值
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能SysTick计数器,重载值加载到计数器中,开始倒数
do{
temp=SysTick->CTRL; //循环读取SysTick状态寄存器,判断计时结束与否
}while(temp&0x01&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;} //关闭计数器
/\*--------------大于1800ms延时的情况,执行else分支-------------------\*/
else{
for(i=0;i<(ms/1800);i++){ //除以1800,整数部分,用for循环,每次延时1800ms
SysTick->LOAD=(unsigned int)1800\*9\*1000; //计数器的重载值,要注意SysTick是倒数计数的
//SysTick一个数是1/9微秒,1800ms就是 1800\*9\*1000
SysTick->VAL=0x00; //清空当前计数器的值
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能SysTick计数器,重载值加载到计数器中,开始倒数
do{
temp=SysTick->CTRL; //循环读取SysTick状态寄存器,判断计时结束与否
}while(temp&0x01&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;} //关闭计数器
//接下来余数部分的延时
SysTick->LOAD=(unsigned int)(ms%1800)\*9\*1000; //计数器的重载值,要注意SysTick是倒数计数的
//SysTick一个数是1/9微秒,余数部分就是(ms%1800)\*9\*1000
SysTick->VAL =0x00; //清空当前计数器的值
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能SysTick计数器,重载值加载到计数器中,开始倒数
do{
temp=SysTick->CTRL; //循环读取SysTick状态寄存器,判断计时结束与否
}while(temp&0x01&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
}
}
关于Cortex-M3核心、SysTick定时器和NVIC的详细说明,请参考另一篇ST的文档和一篇ARM的文档: 《STM32F10xxx Cortex-M3编程手册》和《Cortex™-M3技术参考手册》
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!