Systick定时时间的设定:
重装载值=systick 时钟频率(Hz)X想要的定时时间(S) 如:时钟频率为:AHB的8分频;AHB=72MHz那么systick的时钟频率为72/8MHz=9MHz;要定时1秒,则 重装载值=9000000X1=9000000; 定时10毫秒 重状态值=9000000X0.01=90000 Systick的中断处理函数, 在startup_stm32f10x_hd.s启动文件中有定义。 DCD SysTick_Handler ; SysTick Handler 根据需要直接编写中断处理函数即可: Void SysTick_Handler (void) { ;} 注意: 如果在工程中,加入了stm32f10x_it.c,而又在主函数中编写中断函数,则会报错。
因为在stm32f10x_it.c文件中,也有这个中断函数的声明,只是内容是空的。 /** * @brief This function handles SysTick Handler. * @param None * @retval None */ void SysTick_Handler(void) { }
中断优先级的修改 在调用SysTick_Config(uint32_t ticks)之后,调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)。这个函数在core_cm3.h头文件中。 具体内容如下:
/** * @brief Set the priority for an interrupt * * @param IRQn The number of the interrupt for set priority * @param priority The priority to set * * Set the priority for the specified interrupt. The interrupt * number can be positive to specify an external (device specific) * interrupt, or negative to specify an internal (core) interrupt. * * Note: The priority cannot be set for every core interrupt. */
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if(IRQn < 0) { SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */ else { NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ }
下面以一个实例来说明: 利用systick来实现以1秒的时间间隔,闪亮一个LED指示灯,指示灯接在GPIOA.8,低电平点亮。
#include "stm32f10x.h" //函数声明 void GPIO_Configuration(void);//设置GPIOA.8端口 u32 t;//定义一个全局变量 int main(void) { // SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); SysTick_Config(9000000); SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); GPIO_Configuration(); while(1); }
//GPIOA.8设置函数 void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStruct;//定义一个端口初始化结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开GPIOA口时钟 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//设置为推挽输出 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//设置输出频率50M GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;//指定第8脚 GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIOA.8 GPIO_SetBits( GPIOA, GPIO_Pin_8);//置高GPIOA.8,关闭LED } //systick中断函数 void SysTick_Handler(void) { t++; if(t>=1) { if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==1) {GPIO_ResetBits( GPIOA, GPIO_Pin_8);} } if(t>=2) { if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==0) {GPIO_SetBits( GPIOA, GPIO_Pin_8);} t=0; } }
模拟后的结果 1、8分频后结果
2、直接调用SysTick_Config(9000000);即不分频的结果,间隔为1/8=0.125s
总结: 1、要使用systick定时器,只需调用SysTick_Config(uint32_t ticks)函数即可, 自动完成了,重装载值的装载,时钟源选择,计数寄存器复位,中断优先级的设置(最低),开中断,开始计数的工作。 2、要修改时钟源调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)。 3、要修改中断优先级调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) 应用说明: 1、因systick是一个24位的定时器,故重装值最大值为2的24次方=16 777 215, 要注意不要超出这个值。 2、systick是cortex_m3的标配,不是外设。故不需要在RCC寄存器组打开他的时钟。 3、每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。 4、采用使用库函数的方法,只能采用中断的方法响应定时器计时时间到,如要采用查询的方法,那只能采用设置systick的寄存器的方法,具体操作以后再做分析。
|