STM32F103RCT6开发板M3单片机教程06--定时器中断

前言

除非特别说明,本章节描述的模块应用于整个STM32F103xx微控制器系列,因为我们使用是STM32F103RCT6开发板是mini最小系统板。
本教程使用是(++光明谷SUN_STM32mini开发板++)

STM32F10X定时器(Timer)基础

首先了解一下是STM32F10X定时器(Timer)

注:

小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx, STM32F102xx和STM32F103xx微控制器。
中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx, STM32F102xx和STM32F103xx微控制器。
大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。

定时器类型

大容量的STM32F103xx增强型系列产品包含最多2个高级控制定时器、 4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。
下表比较了高级控制定时器、普通定时器和基本定时器的功能:

高级控制定时器(TIM1和 TIM8)

两个高级控制定时器(TIM1和TIM8)可以被看成是分配到6个通道的三相PWM发生器,它具有带死区插入的互补PWM输出,还可以被当成完整的通用定时器。四个独立的通道可以用于:

● 输入捕获

● 输出比较

● 产生PWM(边缘或中心对齐模式)

● 单脉冲输出

配置为16位标准定时器时,它与TIMx定时器具有相同的功能。配置为16位PWM发生器时,它具有全调制能力(0~100%)。

在调试模式下,计数器可以被冻结,同时PWM输出被禁止,从而切断由这些输出所控制的开关。

很多功能都与标准的TIM定时器相同,内部结构也相同,因此高级控制定时器可以通过定时器链接功能与TIM定时器协同操作,提供同步或事件链接功能。

通用定时器 (TIMx)

STM32F103xC、 STM32F103xD和STM32F103xE增强型系列产品中,内置了多达4个可同步运行的标准定时器(TIM2、 TIM3、 TIM4和TIM5)。每个定时器都有一个16位的自动加载递加/递减计数器、一个16位的预分频器和4个独立的通道,每个通道都可用于输入捕获、输出比较、 PWM和单脉冲模式输出,在最大的封装配置中可提供最多16个输入捕获、输出比较或PWM通道。

它们还能通过定时器链接功能与高级控制定时器共同工作,提供同步或事件链接功能。在调试模式下,计数器可以被冻结。任一标准定时器都能用于产生PWM输出。每个定时器都有独立的DMA请求机制。

这些定时器还能够处理增量编码器的信号,也能处理1至3个霍尔传感器的数字输出。

基本定时器-TIM6和 TIM7

这2个定时器主要是用于产生DAC触发信号,也可当成通用的16位时基计数器。

独立看门狗

独立的看门狗是基于一个12位的递减计数器和一个8位的预分频器,它由一个内部独立的40kHz的RC振荡器提供时钟;因为这个RC振荡器独立于主时钟,所以它可运行于停机和待机模式。它可以被当成看门狗用于在发生问题时复位整个系统,或作为一个自由定时器为应用程序提供超时管理。通过选项字节可以配置成是软件或硬件启动看门狗。在调试模式下,计数器可以被冻结。

窗口看门狗

窗口看门狗内有一个7位的递减计数器,并可以设置成自由运行。它可以被当成看门狗用于在发生问题时复位整个系统。它由主时钟驱动,具有早期预警中断功能;在调试模式下,计数器可以被冻结。

系统时基定时器

这个定时器是专用于实时操作系统,也可当成一个标准的递减计数器。它具有下述特性:

● 24位的递减计数器

● 自动重加载功能

● 当计数器为0时能产生一个可屏蔽系统中断

● 可编程时钟源

高级控制定时器框图

了解基本概念后,今天用通用定时器 (TIM2),  写一个定时中断的程序

编写代码

建工程写代码

复制上节工程文件夹打开(这个方法比较方便)

  • 新建源文件,编辑代码
    编辑main.c, 在上节基础上增加TIM配置及中断服务函数。

    cpp 复制代码
    /**********************************************************************************
    
    * Sun STM32 mini Demo
    
    *   Description  
    
        TIM2 Interrupt Demo
    
       
    
    * Version    Date       Auther      Reversed History
      ----------------------------------------------------------------------------
    
      V1.0.0    2021-11-07  Lojam Fan  Fisrt Created
    
      
    
    * (C) Sunshine Silicon Corporation
    
    *  Website: http://www.sunsili.com  http://sunsili.taobao.com http://bbs.sunsili.com
    
    *  E-Mail : fan@sunsili.com
    
    **********************************************************************************/
    
    
    
    #include "stm32f10x.h"
    #include "usart.h"
    #include "SysTick.h"
    #include "led.h"
    #include "key.h"
    #include <stdio.h>
    
    static u8 flag;
    static u8 tim2_tick;
    
    void Timer2_Init_Config(void);
    void RCC_Configuration(void);
    
    
    /*******************************************************************************
    * 函数名  : main
    * 描述    : 主函数,用户程序从main函数开始运行
    
    * 输入    : 无
    * 输出    : 无
    
    * 返回值  : int:返回值为一个16位整形数
    
    * 说明    : 无
    
    *******************************************************************************/
    
    int main(void)
    {
        u8 keyVal;
    
        RCC_Configuration();
        SysTick_Init_Config();
            USART1_Init_Config(115200);//USART1初始化配置
        LED_GPIO_Config();
        Key_GPIO_Config();
        Timer2_Init_Config();        //Timer2初始化配置
    
        printf ("*===================================================*\n");
        printf ("*  *  Name: Sun STM32 mini Demo Code.    *************\n");
        printf ("*  * (C) Sunshine Silicon Corporation    *************\n");
        printf ("*  *  Website: http://www.sunsili.com    *************\n");
        printf ("*  *   E-Mail : fan@sunsili.com          *************\n");
        printf ("*===================================================*\n");
        printf ("* Sun STM32 mini TIM2 Interrupt Demo code .*\n");
    
       
    
            while (1)
            {
            if(tim2_tick)
            {
    
                tim2_tick = 0;
    
                if(flag)
                {
                    printf("LED ON\n");               
    
                }
                else
                {
                    printf("LED OFF\n");
                }
    
            }
            }
    }
    
    
    
    /*******************************************************************************
    
    * 函数名  : Timer2_Init_Config
    * 描述    : Timer2初始化配置
    
    * 输入    : 无
    * 输出    : 无
    
    * 返回    : 无
    
    * 说明    : 无
    
    *******************************************************************************/
    
    void Timer2_Init_Config(void)
    {
    
            TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
            NVIC_InitTypeDef NVIC_InitStructure;       
    
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);                //使能Timer2时钟      
    
            TIM_TimeBaseStructure.TIM_Period = 4999;                                        //设置在下一个更新事件装入活动的自动重装载寄存器周期的值(计数到5000为500ms)
            TIM_TimeBaseStructure.TIM_Prescaler = 7199;                                        //设置用来作为TIMx时钟频率除数的预分频值(10KHz的计数频率)
            TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;                //设置时钟分割:TDTS = TIM_CKD_DIV1
            TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        //TIM向上计数模式
            TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);                                //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    
            /*中断优先级NVIC设置*/
            NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                                //TIM2中断
            NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;        //先占优先级1级
            NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                        //从优先级1级
            NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                //使能IRQ通道
            NVIC_Init(&NVIC_InitStructure);                                                         //初始化NVIC寄存器         
    
            TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE );                                 //使能TIM2指定的中断      
    
            TIM_Cmd(TIM2, ENABLE);                                                                          //使能TIMx外设
    }         
    
    
    
    /*******************************************************************************
    * 函数名  : TIM2_IRQHandler
    * 描述    : 定时器2中断服务函数
    * 输入    : 无
    * 输出    : 无
    
    * 返回    : 无
    
    * 说明    : 无
    
    *******************************************************************************/
    
    void TIM2_IRQHandler(void)   //TIM2中断服务函数
    {
        tim2_tick = 1;
    
            if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
            {
                    TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIMx更新中断标志
    
                    if(flag)
                    {
                            LED4_ON();
                            flag=0;
    
                    }
                    else
                    {
                            LED4_OFF();
                            flag=1;
    
                    }
            }
    }
    
    
    
    /*******************************************************************************
    * 函数名  : RCC_Configuration
    * 描述    : 设置系统时钟为72MHZ(这个可以根据需要改)
    
    * 输入    : 无
    * 输出    : 无
    
    * 返回值  : 无
    
    * 说明    : STM32F107x和STM32F105x系列MCU与STM32F103x系列MCU时钟配置有所不同
    
    *******************************************************************************/
    
    void RCC_Configuration(void)
    {
      ErrorStatus HSEStartUpStatus;               //外部高速时钟(HSE)的工作状态变量  
    
      RCC_DeInit();                               //将所有与时钟相关的寄存器设置为默认值
      RCC_HSEConfig(RCC_HSE_ON);                  //启动外部高速时钟HSE
      HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部高速时钟(HSE)稳定
    
      if(SUCCESS == HSEStartUpStatus)             //如果外部高速时钟已经稳定
      {
        /* Enable Prefetch Buffer */
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Flash设置
    
        /* Flash 2 wait state */
        FLASH_SetLatency(FLASH_Latency_2);  
    
        RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置AHB时钟等于系统时钟(1分频)/72MHZ
        RCC_PCLK2Config(RCC_HCLK_Div1);  //设置APB2时钟和HCLK时钟相等/72MHz(最大为72MHz)
        RCC_PCLK1Config(RCC_HCLK_Div2);  //设置APB1时钟是HCLK时钟的2分频/36MHz(最大为36MHz)
    
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHz * 9 = 72 MHz
    
        RCC_PLLCmd(ENABLE); //使能PLL
    
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL稳定
    
    
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);          //设置系统时钟的时钟源为PLL
    
        while(RCC_GetSYSCLKSource() != 0x08);               //检查系统的时钟源是否是PLL
    
        RCC_ClockSecuritySystemCmd(ENABLE);                 //使能系统安全时钟
    
       
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO,ENABLE);
    
      }
    }
    
    
    
    
    /******************* (C) COPYRIGHT SUNSHINE SILICON  **************************
    
    ********************        END OF FILE main.c        *******************/

    编译调试程序

编译调试

保存直接编译,发现编译出错, 因为未添加tim库。解决方法添加库文件stm32f10x_tim.c

重新编译,通过。

调试

方法不再重复,经过前两节练习,大家应该是会了.

看到效果是, LED 1s闪烁一次, uart1 定时打印LED状态

总结课后练习

改变TIM定时中断频率

工程源码

查看原文,可下载工程源码

相关推荐
嵌新程2 小时前
day06(单片机高级)PCB设计
单片机·嵌入式硬件·pcb
stm 学习ing3 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
wenchm7 小时前
细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的另一种方法
stm32·单片机·嵌入式硬件
编码追梦人8 小时前
如何实现单片机的安全启动和安全固件更新
单片机
电子工程师UP学堂8 小时前
电子应用设计方案-16:智能闹钟系统方案设计
单片机·嵌入式硬件
飞凌嵌入式8 小时前
飞凌嵌入式T113-i开发板RISC-V核的实时应用方案
人工智能·嵌入式硬件·嵌入式·risc-v·飞凌嵌入式
blessing。。10 小时前
I2C学习
linux·单片机·嵌入式硬件·嵌入式
嵌新程11 小时前
day03(单片机高级)RTOS
stm32·单片机·嵌入式硬件·freertos·rtos·u575
Lin20123011 小时前
STM32 Keil5 attribute 关键字的用法
stm32·单片机·嵌入式硬件
电工小王(全国可飞)11 小时前
STM32 RAM在Memory Map中被分为3个区域
stm32·单片机·嵌入式硬件