加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

STM32学习笔记——外部中断EXTI

(2012-10-30 21:25:00)
标签:

arm

stm32f103c8

程序设计

单片机

嵌入式

分类: 学习探讨

STM32学习笔记——外部中断EXTI

 

  Created on: 2012-10-30

      Author: zhang bin

 

学习笔记

for   STM32F103C8

redesigned by zhang bin

2012-10-30

versionsV-0.1

All Rights Reserved

 

main.c如下,注释的比较详细,把下面的例子即说明都看明白基本上就可以用了:

 

 

 

 

 

//抢占级别高的会打断其他中断优先执行,而响应级别高的会在其他中断执行完优先执行。

//EXTI:外部中断/事件控制器

 

//EXTI控制器可以产生高达19个软件事件/中断请求

//19根线配置为中断源,将19根线配置为事件源,将19根线配置为软件中断/事件线,详见《STM32F103xxx使用手册》

//P135

 

//在这个文件中主要是进行各种初始化配置,包括GPIO配置、EXTI配置、系统时钟配置等

//中断服务程序则在stm32f10x_it.c文件中,该文件提供所有异常处理程序和外围中断服务程序的模板,详见该文件

 

#include "stm32f10x_lib.h"

 

 

 

EXTI_InitTypeDef EXTI_InitStructure;  //定义外部中断初始化结构体变量  内部含有4个成员 详见EXTI_InitTypeDef的定义

ErrorStatus HSEStartUpStatus; //定义错误状态变量,是枚举类型

 

 

 

void RCC_Configuration(void);

void GPIO_Configuration(void);

void NVIC_Configuration(void);

 

 

 

int main(void)

{

#ifdef DEBUG

  debug();

#endif

  

 

  RCC_Configuration();  //系统时钟配置   

 

  NVIC_Configuration(); //NVIC配置

    

  GPIO_Configuration();  //配置GPIO

  

   //STM32的外部中断不是固定的,是可以映射的。如EXTI6既可以映射到PB6也可以映射到PA6,详见外部中断/事件与GPIO的映射关系

   //IO端口注册至中断线(IO口映射到中断线N)

  //

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6);  //选择GPIO管脚用作外部中断线路

  //第一个参数选择用作外部中断线源的GPIO端口  第二个参数是待设置的外部中断线路,可以是GPIO_PinSourcex(x可以0~15)

 

    

  //配置按钮中断线触发方式  设置中断配置结构体成员

  EXTI_InitStructure.EXTI_Line EXTI_Line6; //选择外部中断线  EXTI_Line0~EXTI_Line1819根线

  EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt;   //设置为中断请求,可以为EXTI_Mode_Interrupt中断请求或者

  //EXTI_Mode_Event事件请求

  EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Falling; //触发方式下降沿触发 还可以为EXTI_Trigger_Rising上升沿触发或者

  //EXTI_Trigger_Rising_Falling上升沿下降沿触发

  EXTI_InitStructure.EXTI_LineCmd ENABLE; //中断线使能   ENABLE使能,DISABLE失能

  EXTI_Init(&EXTI_InitStructure); //根据参数结构体初始化EXTI中断

 

  

  EXTI_GenerateSWInterrupt(EXTI_Line6); //产生一个软件中断  EXTI_Line6中断允许 

  //到此中断配置完成,可以写中断处理函数。

        

  while (1)

  {

  }

}

 

 

 

void RCC_Configuration(void)

{

//复位RCC外部设备寄存器到默认值

  RCC_DeInit();  

 

  //打开外部高速晶振

  RCC_HSEConfig(RCC_HSE_ON); 

 

 //等待外部高速时钟准备好

  HSEStartUpStatus RCC_WaitForHSEStartUp(); 

 

  //外部高速时钟已经准别好

  if(HSEStartUpStatus == SUCCESS)  

  {

    

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

 

   

    FLASH_SetLatency(FLASH_Latency_2);

  

   //配置AHB(HCLK)时钟=SYSCLK

    RCC_HCLKConfig(RCC_SYSCLK_Div1);

  

    //配置APB2(PCLK2)=AHB时钟

    RCC_PCLK2Config(RCC_HCLK_Div1); 

 

    //配置APB1(PCLK1)=AHB 1/2时钟

    RCC_PCLK1Config(RCC_HCLK_Div2);  

 

    //配置ADC时钟=PCLK2 1/4

    RCC_ADCCLKConfig(RCC_PCLK2_Div4); 

  

    //配置PLL时钟 == 外部高速晶体时钟*9 8MHz*9MHz=72MHz

    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); 

    

//配置ADC时钟PCLK2/4

    RCC_ADCCLKConfig(RCC_PCLK2_Div4);

 

   //使能PLL时钟

    RCC_PLLCmd(ENABLE);  

 

   //等待PLL时钟就绪

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)  

    {

    }

 

    //配置系统时钟 PLL时钟

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 

 

   //检查PLL时钟是否作为系统时钟

    while(RCC_GetSYSCLKSource() != 0x08)  

    {

    }

  }

   

  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB

                         RCC_APB2Periph_AFIO, ENABLE);

   //使能GPIOAGPIOBAFIOAPB2

}

 

 

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;   //定义配置GPIO的结构体

   

  GPIO_InitStructure.GPIO_Pin GPIO_Pin_8; //选中第8个脚

  GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;       //推挽输出

  GPIO_Init(GPIOB, &GPIO_InitStructure); //用配置好的结构体初始化GPIOB PB8用于驱动led

 

  GPIO_InitStructure.GPIO_Pin GPIO_Pin_6;   //选中6

  GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING;   //配置浮空输入

  GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化GPIOB   PB6脚连接外部中断线6的中断源

  //所有的端口都有外部中断的能力,为了使用外部中断线,端口必须配置为输入模式

 

}

 

 

void NVIC_Configuration(void)  //配置嵌套向量中断控制器

{

  NVIC_InitTypeDef NVIC_InitStructure;//定义初始化NVIC的结构体变量 

  

#ifdef  VECT_TAB_RAM  

    //配置向量表基址

  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);   //分配中断向量表

#else  

   

  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   

#endif

 

  

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  //设置中断优先级

  //设置优先级分组:先占优先级和从优先级  输入参数设定优先级分组位长度  本例中NVIC_PriorityGroup_1:先占优先级1为,从优先级3

  //详见《STM32函数说明》P165

  //优先级分组只能设定一次

  

  //EXTI5-9共用一个中断源,EXTI10-15共用一个中断源

     //详见详见《STM32函数说明》P166

  NVIC_InitStructure.NVIC_IRQChannel EXTI9_5_IRQChannel; //中断通道  指定IRQ通道 这里指定外部中断线9-5中断  因为使用的是EXTI6

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  0;  //设定指定IRQ通道的先占优先级

  NVIC_InitStructure.NVIC_IRQChannelSubPriority 0;//设定指定IRQ通道的从优先级

  NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;  //设定指定IRQ通道中断使能  DISABLE失能

  NVIC_Init(&NVIC_InitStructure);//根据结构体中指定的参数初始化NVIC中断

}

 

#ifdef  DEBUG

 

void assert_failed(u8* file, u32 line)

  

 

  

  while (1)

  {

  }

}

#endif

 

 

 

 

 

stm32f10x_it.c文件中的中断服务函数如下:

 

void EXTI9_5_IRQHandler(void) //外线路5-9的中断处理程序

{

  if(EXTI_GetITStatus(EXTI_Line6) != RESET) //检测制定的EXTI6线路触发请求是否发生。  

  //该函数检查指定的EXTI线路出发请求是否发生

  {

      //其实就是对PB8取反

    GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_8))));

//该函数可以对指定的端口位进行操作  指定端口和位,然后指定操作。第三个参数指定待写入的值

//该参数必须取枚举类型BitAction的其中一个值,可以是Bit_RESET:清除数据端口位和Bit_SET:设置数据端口位

//GPIO_ReadOutputDataBit()函数读取指定的IO端口管脚的输出,参数指定端口和位

 

 //EXTI_ClearFlag(EXTI_Line6);    //清除中断标志位(必须)   我在网上看到要求必须,但是在本例中并没有这句

    

    EXTI_ClearITPendingBit(EXTI_Line6); //清除EXTI线路挂起位

  }

}

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有