STM32F429的定时器的使用方法

        电子时代,硬件在突飞猛进的发展,频率不断上升,目前的STM32系列,Cortex M系列,Cortex-M4的频率已经为:180MHz了,基本上与之前的ARM7/9频率差不多了,还有Cortex-M7,频率更高,出现了BGA封装与SDRAM DDR等。看来处理器越来越大众化了,物联网上的电子设备联网,也越来越普及了,硬件成本不断降低是大势所趋,因此,作为一个电子设计人员,还是要不断的学习掌握更多的技术知识与基础,从而不会被社会很快淘汰。

      最近买了一个现成的STM32F429 Discovery 的开发板,想尝试一下较大点的嵌入式操作系统如RTEMS的移植与应用。因为有了STM32F103/107的基础,熟悉了硬件与固件库,STM32F429其实很容易入手。下面就先定时器中断点个LED试下吧,主要是要组织好工程目录。

      我是根据之前一直使用STM32F103的工程目录改了一下,使用STM32F4XX的最新固件库V1.6.1,至于为何不去直接操作寄存器,我想,虽然自己是硬件出身,搞寄存器更深入的了解处理器,但是,毕竟寄存器过多,有了库,可以封装一下,这样更可以快速的上手。如果需要查看寄存器,也是可以查的。用固件库可以少一些错误,毕竟我们是做应用的,首先要学会使用CPU来实现我们要的功能。

       工程目录如下:这里使用最新的Keil MDK V5.17版本的,STM32F4XX的器件库等还需要进一步下载。这里使用的是自带的ST-Link下载程序,当然使用Jlink也是可以的。


STM32F429的定时器的使用方法_第1张图片



        STM32F429的系统定时器,原来是系统时钟180MHz的8分频,这个可以看一下STM32F4XX的参考手册,里面时钟RCC部分的框架介绍。我这里为了定时为1S,因此计算了一下。


STM32F429的定时器的使用方法_第2张图片



以下为Tim2.c的主程序。Tim2.h 只是函数声明。


/********************     (C) COPYRIGHT 2016     **************************
 * 文件名  :Tim2.c
 * 描述    :定时器timer2 测试例程       
 * 实验平台:STM32F429ZIT6
 * 库版本  :V1.6.1
 *
 * 编写日期:2016-05-02
 * 修改日期:
 * 作者    :
****************************************************************************/
#include "Tim2.h"

/*
 * 函数名:TIM2_NVIC_Configuration
 * 描述  :TIM2中断优先级配置
 * 输入  :无
 * 输出  :无	
 */
void TIM2_NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);  													
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;	  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}


/*TIM_Period--1000   TIM_Prescaler--(22500-1) -->中断周期为
  ((1/180000000)*8)*22500*1000=1S    1秒定时器 */
void TIM2_Configuration(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
    TIM_DeInit(TIM2);
    TIM_TimeBaseStructure.TIM_Period=1000;		 /* 自动重装载寄存器周期的值(计数值) */
    /* 累计 TIM_Period个频率后产生一个更新或者中断 */
    TIM_TimeBaseStructure.TIM_Prescaler= (22500 - 1);	/* 时钟预分频数 (180M/8)/22500 */
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 		/* 采样分频 */
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /* 向上计数模式 */
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);							/* 清除溢出中断标志 */
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    TIM_Cmd(TIM2, ENABLE);														/* 开启时钟 */    
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE);		/* 先关闭等待使用 */    
}

/*
 * 函数名:TIM2_Config
 * 描述  :TIM2配置
 * 输入  :无
 * 输出  :无	
 */
void TIM2_Config(void)
{
  TIM2_Configuration();
	TIM2_NVIC_Configuration();
}


/*******************      (C) COPYRIGHT 2016        *END OF FILE************/



以下为:led.c的文件。


/********************       (C) COPYRIGHT 2014  ***************************
 * 文件名  :led.c
 * 描述    :led 应用函数库         
 * 实验平台:
 * 硬件连接:-----------------------
 *          |   PG14 - LED1(RUN)     |   
 *           ----------------------- 
 * 库版本  :ST3.5.0
 * 编写日期:2014-11-04
 * 修改日期:
 * 作者    :
****************************************************************************/
#include "led.h"

/*
 * 函数名:LED_GPIO_Config
 * 描述  :配置LED用到的I/O口
 * 输入  :无
 * 输出  :无
 */
void LED_GPIO_Config(void)
{		
	/*定义一个GPIO_InitTypeDef类型的结构体*/
	GPIO_InitTypeDef GPIO_InitStructure;

	/*开启 LED1 的GPIOx的外设时钟*/
	RCC_AHB1PeriphClockCmd( RCC_LED1, ENABLE); 
	/*选择要控制的LED1 GPIOx引脚*/															   
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_LED1;	
	/*设置引脚模式为通用推挽输出*/
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   
	/*设置引脚速率为50MHz */   
  	GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed; 
	/* 设置为推挽输出模式 */
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	/* 设置为上拉 */	
		GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_UP;
	/*调用库函数,初始化LED1 的GPIOx*/	
  	GPIO_Init(GPIO_LED1_PORT, &GPIO_InitStructure);		  

		/*开启 LED2 的GPIOx的外设时钟*/
	RCC_AHB1PeriphClockCmd( RCC_LED2, ENABLE); 
	/*选择要控制的LED2 GPIOx引脚*/															   
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_LED2;	
	/*设置引脚模式为通用推挽输出*/
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   
	/*设置引脚速率为50MHz */   
  	GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed; 
	/* 设置为推挽输出模式 */
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	/* 设置为上拉 */	
		GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_UP;
	/*调用库函数,初始化LED1 的GPIOx*/	
  	GPIO_Init(GPIO_LED2_PORT, &GPIO_InitStructure);	
		
	/* 关闭LED1	*/
	//GPIO_ResetBits(GPIO_LED1_PORT, GPIO_Pin_LED1);
	//GPIO_ResetBits(GPIO_LED2_PORT, GPIO_Pin_LED2);	
}




/******************* (C) COPYRIGHT  2014 *****END OF FILE************/



以下为LED的引脚定义:led.h


/********************       (C) COPYRIGHT 2014  ***************************
 * 文件名  :led.h
 * 描述    :led 应用函数库         
 * 实验平台:
 * 硬件连接:-----------------------
 *          |   PG14 - LED1(RUN)     |   
 *           ----------------------- 
 * 库版本  :V1.6.1
 * 编写日期:2016-04-30
 * 修改日期:
 * 作者    :
****************************************************************************/
#ifndef __LED_H
#define	__LED_H

#include "stm32f4xx.h"

/* the macro definition to trigger the led on or off 
 * 1 - off
 - 0 - on
 */
#define ON  1
#define OFF 0

#define RCC_LED1						RCC_AHB1Periph_GPIOG
#define GPIO_LED1_PORT			GPIOG
#define GPIO_Pin_LED1				GPIO_Pin_13

#define RCC_LED2						RCC_AHB1Periph_GPIOG
#define GPIO_LED2_PORT			GPIOG
#define GPIO_Pin_LED2				GPIO_Pin_14

//带参宏,可以像内联函数一样使用
#define LED1(a)	if (a)	\
					GPIO_SetBits(GPIO_LED1_PORT,GPIO_Pin_LED1);\
					else		\
					GPIO_ResetBits(GPIO_LED1_PORT,GPIO_Pin_LED1)

#define LED2(a)	if (a)	\
					GPIO_SetBits(GPIO_LED2_PORT,GPIO_Pin_LED2);\
					else		\
					GPIO_ResetBits(GPIO_LED2_PORT,GPIO_Pin_LED2)
					

void LED_GPIO_Config(void);

#endif /* __LED_H */



主程序:硬件的初始化。


/********************        (C) COPYRIGHT 2016        **************************
 * 文件名  :main.c
 * 描述    :STM32F429 LED测试    
 * 实验平台: STM32F429ZIT6
 * 库版本  :V1.6.1
 * 编写日期:2016-05-02
 * 修改日期:
 * 作者    :
**********************************************************************************/

#include "stm32f4xx.h"
//#include "usart1.h"
#include "led.h"
#include "Tim2.h"

void Delay(__IO uint32_t nTime)
{ 
 
  while(--nTime != 0);
}


/* 
 * 函数名:main
 * 描述  : "主机"的主函数
 * 输入  :无
 * 输出  : 无
 */
int main(void)
{	 
	LED_GPIO_Config();
	TIM2_Config();
	LED1(ON);
  LED2(ON);
	while(1)
	{ 
#if 0
		Delay(0x2FFFFF);
		LED1(OFF);
		LED2(OFF);
		Delay(0x2FFFFF);		
		LED1(ON);
		LED2(ON);
#endif
	}	
}
/******************* (C) COPYRIGHT 2014 *****END OF FILE************/


以下为真正的实现函数:定时器2中断函数 stm32f4xx_it.c


/**
  * @brief  This function handles TIM2 Handler.
  * @param  None
  * @retval None
  */
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
	{   
		TIM_ClearFlag(TIM2, TIM_FLAG_Update);
		TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
		GPIO_WriteBit(GPIO_LED1_PORT,GPIO_Pin_LED1,
		(BitAction)(1-GPIO_ReadOutputDataBit(GPIO_LED1_PORT,GPIO_Pin_LED1)));
	}
}


      编译并烧写,基本上可以看到LED 1S的亮,1S的灭,然后不断的循环下去,一般用于程序的运行指示灯。

重要的总结:

(1)GPIO的时钟,STM32F103的是APB时钟,STM32F429为:RCC_AHB1PeriphClockCmd,我开始弄错了,程序不运行!!

(2)STM32F429虽然180MHz的主频,但是系统定时器的时钟为其的8分频,STM32F103是直接使用的72MHz的主频,因此在计算分频与周期数时,要使用180MHz/8 的定时器基本时钟去计算。


Keil MDK 5.17的工程下载:点击打开链接


你可能感兴趣的:(嵌入式软件)