基于STM32F103C8T6的EXTI外部中断感应灯

#一、EXTI外部中断
#二、NVIC中断
##1)中断流程
##2)STM32中断
##3)中断NVIC与EXTI基本结构
##4)中断优先级分组
##5)AFIO复用IO口
##6)EXTI功能框图
#三、EXTI外部中断结构
#四、EXTI中断函数配置
#五、程序代码

一、EXTI外部中断

  • 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

  • EXTI可以检测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。

  • 支持触发方式:上升沿/下降沿/双边沿/软件触发

  • 支持GPIO口:所有的GPIO口,但相同的Pin不能同时触发中断(如,PA1、PB1、PC1则不能同时触发中断,经AFIO_EXTICR1寄存器分配,任选其一产生中断)

  • 通道数:16个GPIO_Pin,外加PVD输出(注1)RTC闹钟(注2)、USB唤醒、以太网唤醒

  • 在程序中应用中断可以代替While(1)以减少单片机在程序运行过程中等待的时间,进一步提高了单片机的利用率及其工作效率,今天程序应用到的是外部中断EXTI

  • 注:
    1)PVD = Programmable Votage Detector 可编程电压监测器
    它的作用是监视供电电压,在供电电压下降到给定的阀值以下时,产生一个中断,通知软件做紧急处理。
    2)RTC是Real Time Clock的简称,定时开机闹钟,它在硬件电路上单独供电,当系统关机时,CPU和其他外部硬件设备全部掉电,但是RTC仍然继续工作。

    硬件如上个项目一致

二、NVIC中断

1)中断流程

  • 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
  • 中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
  • 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

在这里插入图片描述

2)STM32中断

向量表:

  • 68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设(灰色部分为芯片内部中断)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3)中断NVIC与EXTI基本结构

在这里插入图片描述
在这里插入图片描述

  • EXTI中断结构图分析:
  • GPIOA、GPIOB、GPIOC等各有16个Pin口(0~15),相同Pin口由AFIO中断引脚选择寄存器选择GPIOx为通道之一,如, GPIOA_Pin1,GPIOB_Pin1,GPIOC_Pin1,AFIO中断引脚选择寄存器选择GPIOA_Pin1为中断通道,则GPIOA_Pin1为EXTI1通道,其他两个Pin口产生的中断不会得到响应。
  • 通道数:AFIO中断引脚选择器选择出16个GPIO_Pin,外加PVD输出RTC闹钟、USB唤醒、以太网唤醒,一共20个通道通往EXTI边沿检测及控制寄存器
  • 由EXTI边沿检测及控制寄存器检测中断信号,产生相应的中断请求信号沿通道送往NVIC中断
  • NVIC中断结构图分析:
  • NVIC中断收集各个外设的中断请求,分配优先级组,将中断事件依次送入CPU处理。

4)中断优先级分组

  • 使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置

  • NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级

  • 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

在这里插入图片描述

5)AFIO复用IO口

  • AFIO主要用于引脚复用功能的选择和定义
  • 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

如图为中断引脚选择功能

在这里插入图片描述

6)EXTI功能框图
在这里插入图片描述
具体介绍:EXTI中断运行分析

四、EXTI中断函数配置

外部中断软件设计
a) 软件设计思想
i. 初始化中断
ii. EXTI(外部中断)

  1. 所有使用到的外设时钟使能
  2. 初始化GPIO口
  3. 外部中断线配置
    a) AFIO外部中断寄存器选择哪个端口
  4. EXTI相关寄存器
  5. NVIC配置

iii. 中断服务函数

  1. 中断服务函数的编写
    a) 判断是哪一个中断(共用中断服务函数)
    b) 清对应中断挂起标志位
    c) 中断服务函数

五、程序代码

1、Exti.c

#include "stm32f10x.h"
#include "exti.h"


void Exti_Init(void)
{
    
	  //1.配置GPIO
	  GPIO_InitTypeDef shake_init;	
	  EXTI_InitTypeDef exti_init;
	  NVIC_InitTypeDef nvic_init;
	
	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//优先级分组配置

		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);//配置GPIO时钟
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//配置EXTI中断时钟,又输出又中断
	  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource2);
	  
	  
	 
	  
	
	  shake_init.GPIO_Mode   =  GPIO_Mode_IPD;
		shake_init.GPIO_Pin    =  GPIO_Pin_2;
    shake_init.GPIO_Speed  =  GPIO_Speed_10MHz;
	
		GPIO_Init(GPIOA,&shake_init);

	
	  //2.配置Exti外部中断
	  exti_init.EXTI_Line    = EXTI_Line2;//外部中断通道
	  exti_init.EXTI_LineCmd = ENABLE;//使能外部中断通道
	  exti_init.EXTI_Mode    = EXTI_Mode_Interrupt;//选择外部中断模式
	  exti_init.EXTI_Trigger = EXTI_Trigger_Falling;//中断触发方式
	 
	  EXTI_Init(&exti_init);//中断初始化
	   
	
	  //3.配置NVIC中断控制器
		
	  nvic_init.NVIC_IRQChannel    =  EXTI2_IRQn;//中断通道2
		nvic_init.NVIC_IRQChannelCmd =  ENABLE;    //使能通道
		nvic_init.NVIC_IRQChannelPreemptionPriority =  1; //抢占优先级
		nvic_init.NVIC_IRQChannelSubPriority   =  1;//子优先级
		
		NVIC_Init(&nvic_init);  

}



2、Exti.h

#include "stm32f10x.h"

void Exti_Init(void);


3、shake.c

#include "stm32f10x.h"
#include "shake.h"

void Shake_Init(void)
{
	    GPIO_InitTypeDef shake_init;	
	
	  //1.使能GPIOA时钟
			RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
	
	
		//2.结构体配置
	    shake_init.GPIO_Mode   =  GPIO_Mode_IPD;
			shake_init.GPIO_Pin    =  GPIO_Pin_2;
	    shake_init.GPIO_Speed  =  GPIO_Speed_10MHz;
	
			GPIO_Init(GPIOA,&shake_init);

	
			
	
	  
	
	

}


4、skake.h

#include "stm32f10x.h"

void Shake_Init(void);







5、relay.c

#include "stm32f10x.h"
#include "relay.h"


void Relay_Init(void)
{
	
	    GPIO_InitTypeDef relay_init;
		//1.使能GPIOA时钟
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	
	  //2.GPIOA3结构体配置
			relay_init.GPIO_Mode  = GPIO_Mode_Out_PP;
	    relay_init.GPIO_Pin   = GPIO_Pin_3 ;
	    relay_init.GPIO_Speed = GPIO_Speed_10MHz;
	
	    GPIO_Init(GPIOA, &relay_init); 
	
}


6、relay.h

#include "stm32f10x.h"

void Relay_Init(void);


7、main.c

#include "stm32f10x.h"
#include "main.h"
#include "LED.h"
#include "usart.h"
#include "relay.h"
#include "shake.h"
#include "exti.h"

void delay(uint16_t time)//延迟函数
{
		uint16_t i=0;
	  while(time--)
		{
				i=12000;
			  while(i--);
		}
}



int  main()
{
	 LED_Init();
	 usart_init(); 
	 Relay_Init();
	 Shake_Init();
	 Exti_Init();
	
	 GPIO_SetBits(GPIOA,GPIO_Pin_3);
	
}


void  EXTI2_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line2)!=RESET)//如果函数发生中断
		{
				GPIO_ResetBits(GPIOA,GPIO_Pin_3);//接通继电器,开灯
			  delay(1000);
			  GPIO_SetBits(GPIOA,GPIO_Pin_3);//关闭继电器,关灯
		}
		else
		{
				GPIO_SetBits(GPIOA,GPIO_Pin_3);//关闭继电器,关灯
		}
		
		EXTI_ClearITPendingBit(EXTI_Line2);//中断标志清除 

}





8、USART.C

#include "stm32f10x.h"
#include "usart.h"

void usart_init(void)   //串口初始化
{
	    GPIO_InitTypeDef GPIO_initstructure;
	    USART_InitTypeDef USART_initstructure;
	    NVIC_InitTypeDef Nvic_Init;
	    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   //配置中断组为中断组2   misc.h
	
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   //配置中断复用时钟
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	

	 	
        //配置PA9 TX	
      GPIO_initstructure.GPIO_Mode   =GPIO_Mode_AF_PP; //推挽输出
			GPIO_initstructure.GPIO_Pin    =GPIO_Pin_9;
			GPIO_initstructure.GPIO_Speed  =GPIO_Speed_50MHz;
			GPIO_Init(GPIOA,&GPIO_initstructure); 

	      //配置PA10 RX
	    GPIO_initstructure.GPIO_Mode   =GPIO_Mode_IN_FLOATING; //浮空输入
			GPIO_initstructure.GPIO_Pin    =GPIO_Pin_10;
			
	    GPIO_Init(GPIOA,&GPIO_initstructure); 
	     
	     //串口1打开
	    USART_initstructure.USART_BaudRate=115200;    //波特率
	    USART_initstructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	    USART_initstructure.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
			USART_initstructure.USART_Parity=USART_Parity_No;     //校验位
			USART_initstructure.USART_StopBits= USART_StopBits_1;         //停止位
			USART_initstructure.USART_WordLength= USART_WordLength_8b;  //有效字节长度  8位
	    USART_Init(USART1,&USART_initstructure);
      //使能串口1
			USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);   //串口中断配置
			USART_Cmd(USART1,ENABLE);

       
   //配置中断
      
						
		  Nvic_Init.NVIC_IRQChannel       =USART1_IRQn;       //设置中断通道  stm32f10x.h
		  Nvic_Init.NVIC_IRQChannelCmd    =ENABLE;                   //控制是否使能
		  Nvic_Init.NVIC_IRQChannelPreemptionPriority  =1;          //设置抢占优先级
		  Nvic_Init.NVIC_IRQChannelSubPriority   =1;             //设置子优先级
		
		  NVIC_Init(&Nvic_Init);

}


//发送单个字符   调用方法   USARTSendByte(USART1,'o');
void USARTSendByte(USART_TypeDef* USARTx, uint16_t Data){

  USART_SendData(USART1,Data);
 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);  //判断是否发送完成
 
}



//发送字符串   //原理字符发送最后一位是\0判断是否最后一位\0就能发送字符串   调用方法   USARTSendStr(USART1,"ruanzebin");
void USARTSendStr(USART_TypeDef* USARTx, char *str){

   uint16_t i=0; //无符号整形十六位
  
    do{
			
		USARTSendByte(USARTx, *(str+i));
			i++;
		
		
		}while(*(str+i)!='\0');

   while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);  //判断是否发送完成

}
  //printf 函数  putchar函数(输出单个字符)  通过重定向  输出数值
int fputc(int ch ,FILE *f){


  USART_SendData(USART1,(uint8_t)ch);
  while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);  //判断是否发送完成

  return (ch);
}
  //scanf()  getchar函数    
int fgetc(FILE *f)
{
	
     while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)==RESET); //判断是否接收成功

       return (int)USART_ReceiveData(USART1);


}






  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值