STM32L152RE实现定时器控制中断代码及原理

本文主要讲解用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的详解将于之后放上来,书上的坑很多,不仅需要改代码,还需要用杜邦线在板子上把一些接口连起来。大家可以先自己尝试一下,代码很多,尽量自己打出来方便理解。如果有同学能自己做出来,那已经很棒了!

至于拓展实验的超声测距,我自己也还没有做出来,代码里全是坑,硬件也不知道连没连对,只能说参照给的代码中的思路,每一句代码都要知道是想要干什么的,真正的过程还需要自己理解。如果有同学能做出来,欢迎来讨论思路。

由于鄙人时间有限,细节的疑问请大家认真思考,自力更生

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值