定时器是单片机最重要的一个模块,有了定时器就可以做任何需要的功能。
本例采用通用定时器2来实现基本的定时功能——控制灯的亮灭,时间间隔设置成1S。
定时器需要设置2部分:初始化定时器、中断优先级。需要注意的是设置定时器时需要在开始使能其时钟(对于任何一个模块这一步都是必须的)。
编写定时器初始化时 按照定时器逐个看是否是相关的功能操作位即可,如果不相关,比如我们是用的定时器基本功能,而定时器捕获/比较什么的功能就是无关的,遇到这些寄存器位直接跳过即可,这种方法对于熟悉定时器会相当有帮助。
void Tim2_Init(unsigned int psc,unsigned int period)
{
RCC->PCLKEN|=(1<<11); //定时器2时钟开启
TIM2->CR1&=~(3<<8);//时钟不分频
TIM2->CR1|=1<<7;//自动重装载
TIM2->CR1&=~(3<<5);//边沿对齐模式
TIM2->CR1&=~(1<<4);//向上计数
TIM2->CR1|=(1<<2);//
TIM2->PSC=psc;//分频系数
TIM2->ARR=period;//周期
NVIC->ISER[0]|=1<<19;//使能中断
NVIC->IP[4]|=2<<30;//设置中断优先级
TIM2->CNT=0;
TIM2->CR1|=1<<0;//使能定时器
TIM2->DIER|=1<<0;//允许更新中断
}
LED的初始化,这一步在之前的例子已经写过了
void LED_Init()
{
RCC->HCLKEN|=(1<<0); //GPIOA时钟开启
GPIOA->DIRCR|=1<<3; //PA3输出
GPIOA->OTYPER&=~(1<<3); //PA3开漏输出
GPIOA->SLEWCR&=~(1<<3); //PA3高电压转换速率
GPIOA->DRVCR&=~(1<<3); //PA3高驱动强度
GPIOA->ODR&=~(1<<3); //PA3输出低电平
}
中断函数编写。
在这例中,我们定时1s,假如单片机工作时钟为24M,将其设置成24分频,周期设置成0.1s(100ms)。此时不够1s,我们在中断函数中再累计10次即可。定时公式为:time=((1/(24000000/分频系数))*周期*(中断累计计数)
void TIM2_IRQHandler()
{
if(TIM2->SR&(1<<0))
{
count++;
if(count>10)
{
if(led_status==0)
{
led_status=1;
}
else
{
led_status=0;
}
count=0;
}
TIM2->SR&=~(1<<0);
TIM2->CNT=0;
}
}
状态位的变化是在定时器中更改的,主函数根据状态位的改变来改变LED灯的状态
int main()
{
LED_Init();
Tim2_Init(23,10000);
while(1)
{
if(led_status)
{
GPIOA->ODR|=(1<<3);
}
else
{
GPIOA->ODR&=~(1<<3);
}
}
return 0;
}
?CX32L003最小系统开发板图片来自《嵌入式软硬件爱好者》
|