续上 用中断方式


中断方式一:外部中断

步骤:
1.系统上电初始化
2.系统时钟参数设置–同前
3.引脚设置

//***********gpio.c

#include "gpio.h"

void GPIOConfiguration()
{
     GPIO_InitTypeDef  GPIO_InitStructure;

     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
     GPIO_Init(GPIOA,&GPIO_InitStructure);//用PA0作数字输出引脚

     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
     GPIO_Init(GPIOA,&GPIO_InitStructure);

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
    //用PA1作外部中断输入引脚
}
//***********gpio.h略

4.开中断,等触发

//***********nvic.c

#include "nvic.h"                       
void NVICConfiguation()
{

    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    //外部中断线
    EXTI_InitStructure.EXTI_Line=EXTI_Line1;
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd=ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    //内部中断向量表
    #ifdef VECT_TAB_RAM
        NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
    #else
        NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
    #endif

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure); 
}

//***********nvic.h略

对misc.h的解释:
STM32 V3.5版本的库函数中没有原来版本中单独对于NVIC(中断向量嵌套)的外设驱动,把NVIC的外设驱动放在了misc.c中,实际上是代替原来的stm32f10x_nvic.c.

NVIC即嵌套中断向量控制器.
关于优先级别移步
http://www.cnblogs.com/dyllove98/archive/2013/08/01/3230973.html

http://bbs.ednchina.com/BLOG_ARTICLE_3009999.HTM

对于不同的外部中断请求,分类如下:

EXTI_InitStructure.EXTI_Line=EXTI_LineN;
这个就是选择不同的外部中断线N
EXTI16接到PVD输出
EXTI17接到RTC闹钟事件
EXTI18连接到USB唤醒事件(这三个没画出来)

这里写图片描述

5.进入中断服务子程序并返回

同时在stm32f10x_it.c里面添加中断服务函数,并将其在stm32f10x_it.h里面声明。

void EXTI1_IRQHandler()
{
    extern vu16 BreakFlag;
    if(EXTI_GetFlagStatus(EXTI_Line1)!=RESET)
    {
      GPIO_SetBits(GPIOA,GPIO_Pin_0);

    //*********可添加其他代码,这里我们将自己的程序放在中断服务子函数当中来,也可以用全局变量进行传递到主函数当中,进行编程.下面将用到这种方法.

      Delay(4000);
      Delay(4000);

      EXTI_ClearITPendingBit(EXTI_Line1);   //软件清除中断
    }
    else
    {;}
}

注:关于中断服务子函数的函数名可参考启动文件

EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_IRQHandler
DMA1_Channel3_IRQHandler
DMA1_Channel4_IRQHandler
DMA1_Channel5_IRQHandler
DMA1_Channel6_IRQHandler
DMA1_Channel7_IRQHandler
ADC1_2_IRQHandler
USB_HP_CAN1_TX_IRQHandler
USB_LP_CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler
CAN1_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler

主函数main() 如下:

#include "stm32f10x.h"
#include "gpio.h"
#include "rcc.h"
#include "nvic.h"

vu16 BreakFlag;

 extern void Delay(vu32 nCount)
{
    for(;nCount>0;nCount--)
        ;
}

int main()
 {
     #ifdef DEBUG
            debug();
     #endif

    for(;;);
 }

中断方式二:采用定时器产生中断

STM32定时器简介:

这里写图片描述

挂线时钟分频(来自于系统时钟方框图):
这里写图片描述

注:只要是使用默认的函数配置时钟,无论是TIM1-TIM8,定时器的内部计数频率均为72MHz(STM32F103内部8M的内部震荡,经过倍频后最高可以达到72M.就是默认晶振 8M 的时候,推荐的 CPU 频率选择)。尽管APB1最高只能是36MHz,但是当预分频值为2时,可以让APB1挂线的低速定时器时钟变为72MHz。

打开system_stm32f10x.c,如果系统时钟设置为72MHz,系统会运行

#elif defined SYSCLK_FREQ_72MHz
/**
  * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2 
  *          and PCLK1 prescalers. 
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo72(void)

里面有

    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

    /* PCLK2 = HCLK */  
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

    //AHB总线时钟,由系统时钟SYSCLK 分频得到,一般不分频,等于系统时钟
    //PCLK2对应APB2外设,PCLK2=72MHz
    //PCLK1对应APB1外设,PCLK1=36MHz.但是图下面的一个框这样解释,如果APB1的预分频系数=1,则频率不变,否则频率*2,所以后来TIM的时钟频率又自动变成之前的两倍,又72MHz。

    //查头文件,RCC_CFGR_PPRE2类似
 #define  RCC_CFGR_PPRE1_DIV1                 ((uint32_t)0x00000000)        /*!< HCLK not divided */
#define  RCC_CFGR_PPRE1_DIV2                 ((uint32_t)0x00000400)        /*!< HCLK divided by 2 */
#define  RCC_CFGR_PPRE1_DIV4                 ((uint32_t)0x00000500)        /*!< HCLK divided by 4 */
#define  RCC_CFGR_PPRE1_DIV8                 ((uint32_t)0x00000600)        /*!< HCLK divided by 8 */
#define  RCC_CFGR_PPRE1_DIV16                ((uint32_t)0x00000700)        /*!< HCLK divided by 16 */

下面先采用通用定时器

这里写图片描述

这里写图片描述

这里CK_PSC即是挂线时钟,经过我们设定的TIM_Init()之后,即设定里面的TIM_Prescaler值,输出为我们所需要的实际定时器时钟CK_CNT,要使得CK_CNT有效,TIM1_CR1.CEN必须=1.

且在计数器可以产生
a.更新事件(上溢,下溢)
b.触发事件(输出比较和输入捕获)

/********************************************************************
实现结果:利用通用定时器TIM2产生中断,定时1s,发生中断的时候LED灯点亮,
且延迟若干时间,同时用户可自行添加其他的程序.
定时时间=(1/定时器时钟频率)*周期
********************************************************************/

1)引脚配置值搞PA0即可,其他去掉。
2)添加TIM2定时器时钟使能

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

3)外部中断不用,中断向量表通道要改成

NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;

4)添加stm32f10x_tim.h到FWlib,并自建time.c(和time.h)

#include "time.h"

void TIM2_Configuration()
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

     //采用内部时钟给TIM2提供时钟源
     //TIM_InternalClockConfig(TIM2);

    TIM_TimeBaseStructure.TIM_Period=2000;
    TIM_TimeBaseStructure.TIM_Prescaler=0x8c9f;
    //预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz
    TIM_TimeBaseStructure.TIM_ClockDivision=0;
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE);//ʹÄÜTIM2ͨµÀ1ÖжÏ

    TIM_Cmd(TIM2,ENABLE);
}

5)中断服务函数

当有TIM2的无论哪个中断(事件)触发中断发生那么就会进入这个函数 TIM2_IRQHandler()

而更新事件的中断判断要依靠以下语句:if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)

最后别忘了TIM_ClearITPendingBit(TIM32, TIM_FLAG_Update).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值