1.SysTick寄存器结构
SYSTICK 寄存器结构,SysTick_TypeDef,在文件“stm32f10x_map.h”中定义如下:
typedef struct
{
vu32 CTRL;
vu32 LOAD;
vu32 VAL;
vuc32 CALIB;
} SysTick_TypeDef;
SysTick 外设声明于文件“stm32f10x_map.h”:
#define SCS_BASE ((u32)0xE000E000)
#define SysTick_BASE (SCS_BASE + 0x0010)
#ifndef DEBUG
...
#ifdef _SysTick
#define SysTick ((SysTick_TypeDef *) SysTick_BASE)
#endif /*_SysTick */
...
#else /* DEBUG */
...
#ifdef _SysTick
EXT SysTick_TypeDef *SysTick;
#endif /*_SysTick */
...
#endif
使用Debug模式时,初始化指针SysTick于文件“stm32f10x_lib.c”:
#ifdef _SysTick
SysTick = (SysTick_TypeDef *) SysTick_BASE;
#endif /*_SysTick */
为了访问SysTick寄存器,, _SysTick必须在文件“stm32f10x_conf.h”中定义如下:
#define _SysTick
SysTic定时可应用与以下两个方面:
1).设置简单的延时,eg:led灯闪烁显示:
///MyTime.h
#ifndef __MYTIME_H__
#define __MYTIME_H__
#include "stm32f10x.h"
/****************************
*@Fun 定时延时
****************************/
void MySysTick_Init(void);
void MyDelay_us(u32 nTime);
void MyDelay_ms(u32 nTime);
#endif
///MyTime.c
#include "MyTime.h"
void MySysTick_Init(void)
{
SysTick->CTRL &= ~0x01; //失能SysTick定时器
SysTick->CTRL &= ~(0x01<<1); //失能中断响应(异常响应)
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//设置系统时钟源
}
void MyDelay_us(u32 nTime)
{
u32 nLastRead;
u32 nus; //1us时间内动作次数
nus = SystemCoreClock/8000000; // 72M/8M=9<2^4(只需4位,用u8即可)
nus*=nTime; //nTime微妙共需动作次数(假设1000us(1ms),9*1000=9000<9*2^10(10个位即可),假设延时1000000us(1s),则9*1000000=9000000=9M<9*2^20(需要20个位)),所以nus最终用u32.
SysTick->VAL = 0; //清空当前值寄存器
SysTick->LOAD = nus; //重装载值寄存器
SysTick->CTRL |= 0x01; //使能定时器
do
{
nLastRead = SysTick->CTRL;
}while(nLastRead&0x01 && !(nLastRead&(1<<16))); //定时器使能状态 && SysTick->CTRL==0时满足条件
//当SysTick->CTRL == 1时,说明定时周期已到。
SysTick->CTRL &= ~(0x01); //失能定时器
SysTick->LOAD = 0;
SysTick->VAL = 0;
}
void MyDelay_ms(u32 nTime)
{
u32 nLastRead;
u16 nms; //1ms动作次数
nms = SystemCoreClock/8000;// 72M/8000=9000<9*2^10;(10个位即可)
SysTick->VAL = 0;
SysTick->LOAD = (u32)nms*nTime;
SysTick->CTRL |= 0x01;
do
{
nLastRead = SysTick->CTRL;
}while(nLastRead&0x01 && !(nLastRead&(1<<16)));
SysTick->CTRL &= ~0x01;
SysTick->LOAD = 0;
SysTick->VAL = 0;
}
///main.c
#include "stm32f10x_conf.h"
#include "MyTime.h"
int main(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
while(1)
{
GPIO_SetBits(GPIOB,GPIO_Pin_5);
MyDelay_ms(100);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
MyDelay_ms(100);
}
}
2).定时做某一动作,相当于定时器。
///MyTime.h
#ifndef __MYTIME_H__
#define __MYTIME_H__
#include "stm32f10x.h"
/*******************************
*@Fun 定时器
********************************/
void MySetTimer(u16 nSec);
#endif
///MyTime.c
void MySetTimer(u16 nSec)
{
u16 ns;
ns = SystemCoreClock/8; //1s动作次数
SysTick->CTRL &= ~0x01;
SysTick->CTRL &= ~(0x01<<1);
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
SysTick->VAL = 0;
SysTick->LOAD = (u32)nSec*ns;
SysTick->CTRL |= 0x01;
}
///main.c
int main(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
MySetTimer(10);
while(1)
{
u32 nLastRead = SysTick->CTRL;
if(nLastRead&0x01 && (nLastRead&(1<<16))) //这里有个很奇怪的问题,如果用1 == nLastRead&(1<<16),则无法显示正确结果。。。。。
{
//时间到
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
else
{
GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
}
}
转载于:https://blog.51cto.com/whatever957/1627476