经过几天的学习之后,我对STM32的系统定时器产生了一些心得和体会,现记录下来,供大家参考交流。
当然,欢迎大家指出其中的错误和不足。现在进入正文。
首先,STM32的系统定时器是什么呢?
这次百度百科查不到了……那我就自己说吧。
系统定时器,就是STM32芯片内部的一个定时器,用于为系统提供定时以及中断的一个设备。
那么,这次的实验难道就是定个时?
当然不是。我们要用定时器制作一个精确延时的闪烁灯。
好吧,和单纯定时差不了太多。
任务比较简单:配置LED,开启定时器,检测是否达到延时时间,改变LED状态。
是不是很简单?那么我们来看一看代码的组成部分:
1. 用于存储相关配置的结构体。
2. 变量i, j;用于检测延时时间是否达到以及保存LED当时的状态。
3. 配置LED灯。
4. 开启系统时钟。
5. 中断服务函数。
好的,代码结构就是这样了。
可以看出,这次的代码结构比较简单,量也很少。下面我就来看看具体代码。
1. 结构体
GPIO_InitTypeDef GPIO_InitStructure;
这次只要配置LED的GPIO就行了,所以只有一句。
2. 变量
int i = 0, j = 0;
好吧,和上次一样,没什么好说的。
3. 配置LED
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
和上次一样,同样不需要多说。
只有一点需要注意:如果GPIO的模式为输出的话,调用GPIO配置函数之后,相应的GPIO口直接就会输出低电平。
不需要调用GPIO_ResetBits函数。
4. 开启系统时钟
SysTick_Config(SystemCoreClock / 100);
虽然只有一行代码,但是从这里开始就进入重点了。
SysTick_Config是用来配置系统时钟的函数,参数可以理解为你想要的一个频率。
我们假设填入的参数为n,那么系统定时器的晶振在震动n次之后,就会将中断标志位置1,并进入一次系统中断,也就是执行中断服务函数。
这之后,中断标志位就会被清零,定时器继续工作。
循环往复,不会停止,除非手动将定时器使能位置零。
忘了说了,SystemCoreClock是一个宏,其值为72000000。
5. 中断服务函数
void SysTick_Handler(void)
{
i++;
if(i == 1000)
{
j = !j;
i = 0;
}
if(j == 0)
GPIO_SetBits(GPIOB, GPIO_Pin_0);
else if(j == 1)
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
}
依然没几行……
好吧,重点不在代码量上。
很明显,这是一个函数,而且是由我来定义的。
大家可能要问,我为什么要起一个如此麻烦的函数名呢?
其实这就是问题所在。函数名不是我起的,我只是写了其中的函数体。函数名是STM32库规定的。
这是怎么回事呢?
这涉及到单片机程序的运行机制。单片机在触发中断时,就会由启动文件来调相应的中断函数。
启动文件是由汇编语言编写的,里面直接调用了一个具体的函数名,你只需要定义一个中断函数,并将其命名为规定的名称就好了。
简单介绍一下函数内容。
变量i起到一个计数的作用每次进入中断都会加1。
累计中断进入1000次之后,i的值就为1000,此时j的值取反,即将改变LED灯的状态(亮和灭)。
之后根据j的值改变LED的状态。
是不是很简单?最后附上完整代码。
#include "stm32f10x.h"
GPIO_InitTypeDef GPIO_InitStructure;
int i = 0, j = 0;
int main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
SysTick_Config(SystemCoreClock / 1000);
while(1);
}
void SysTick_Handler(void)
{
i++;
if(i == 1000)
{
j = !j;
i = 0;
}
if(j == 0)
GPIO_SetBits(GPIOB, GPIO_Pin_0);
else if(j == 1)
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
}