本文主要讲解用keil软件实现定时器中断控制,默认读者keil环境已经配好,且头文件已正确引入,如出现编译错误以及st-link下载问题,请自行百度解决。
功能一:用SysTick实现led 时延
利用定时器实现 500ms 的灯闪烁。(用SysTick时钟控制)
1.头文件
#include "stm32l1xx_gpio.h"
#include "stm32l1xx_rcc.h"
#include "stm32l1xx.h"
2.初始化函数
除了初始化PA5控制LED灯的GPIO管脚之外,还要设置SysTick时钟的参数,设置完时钟会自动开始计数,并在达到指定的数目时发生中断并重新计数。这里参数设置的是500321000,因为SysTick时钟的计数频率是32MHz。
void GPIO_Configuration(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&GPIO_InitStructure);
SysTick_Config(500*32*1000);
}
3.设置全局变量flag
flag用于判断灯的状态
int flag=0;
4.主函数main()
在while循环中设置灯的状态
int main(void)
{
GPIO_Configuration();
while(1)
{
if(flag)
GPIO_SetBits(GPIOA,GPIO_Pin_5);
else
GPIO_ResetBits(GPIOA,GPIO_Pin_5);
}
}
5.SysTick_Handler函数
打开stm32l1xx_it.c文件,把函数写在文件末尾(或者写哪都行,只要别插在其他函数里面就行)
要先引入全局变量flag,当中断发生时,将flag取反,以达到反转的目的。
extern int flag;
void SysTick_Handler(void)
{
flag=!flag;
}
第一个简单的功能就实现了。
功能二:例7-5:用通用定时器实现LED灯的反转
观察 7-5 LED 灯的翻转频率,修改程序源代码将频率改为 3K、6K、9K 和 12K。
通用定时器比系统时钟复杂很多,下面让我们看看怎么来实现吧!
1.头文件
#include "stm32l1xx_gpio.h"
#include "stm32l1xx_rcc.h"
#include "stm32l1xx.h"
#include "misc.h"
#include "stm32l1xx_tim.h"
2.GPIO初始化
void GPIO_Configuration(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
3.NVIC初始化
初始化TIM2中断通道
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
4.TIM初始化
由于TIM2的主频为32MHz,预分频系数为3200时,时钟频率为10000Hz,由此算出频率为3K,6K,9K,12K时预分频系数的大小(此处存疑,如有误请指出)
void TIM_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//TIM2:32MHz
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_DeInit(TIM2);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseStructure.TIM_Prescaler=3200-1;//10667/5333/3556/2667
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period=5000-1;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
TIM_ARRPreloadConfig(TIM2,DISABLE);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM2,ENABLE);
}
思考:TIM_ClearFlag,TIM_ARRPreloadConfig是否可以删除
大家可以删了试试,我删了之后程序还是正常的
5.主函数main()
int main(void)
{
GPIO_Configuration();
NVIC_Configuration();
TIM_Configuration();
while(1);
}
6.TIM2_IRQHandler函数
打开stm32l1xx_it.c文件,把函数写在文件末尾(或者写哪都行,只要别插在其他函数里面就行),懒得打字所以define了一下
#define PA5 GPIOA,GPIO_Pin_5
void TIM2_IRQHandler(void)
{
uint8_t ReadValue;
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
ReadValue=GPIO_ReadInputDataBit(PA5);
if(ReadValue==0)
GPIO_SetBits(PA5);
else
GPIO_ResetBits(PA5);
}
}
完成
功能三:例7-6四个通道控制四个灯按照四个频率闪烁
由于时间问题,例7-6的详解将于之后放上来,书上的坑很多,不仅需要改代码,还需要用杜邦线在板子上把一些接口连起来。大家可以先自己尝试一下,代码很多,尽量自己打出来方便理解。如果有同学能自己做出来,那已经很棒了!
至于拓展实验的超声测距,我自己也还没有做出来,代码里全是坑,硬件也不知道连没连对,只能说参照给的代码中的思路,每一句代码都要知道是想要干什么的,真正的过程还需要自己理解。如果有同学能做出来,欢迎来讨论思路。
由于鄙人时间有限,细节的疑问请大家认真思考,自力更生