实验二 、中断实验

实验二 、中断实验

​ 自律 学习 坚强 ,拒绝迷茫。

作者:行走的皮卡丘

时间:2021/3/23

喜欢就去追,这个红灯等不到,说不定下一个红灯等到了,嘻嘻!!!!!!!


文章目录

一、实验目的

1、 掌握STM32中断程序设计流程。

2、 熟悉STM32固件库的基本使用。

3、 掌握STM32定时器设计流程。

二、实验内容

任务一、LED

(1)按键未按下时,主程序状态如下:LED1、LED2、LED3交替闪烁,每个LED闪烁间隔时间0.2S(一亮一灭共0.2S),持续1S。

(2)K2按键按下,进入中断状态。按1次,亮1个LED,持续1S后退出中断;按2次,亮2个LED,持续2S后退出中断;按3次,亮3个LED,持续3S后退出中断;按4次等同于按1次;

(3)(2)的基础上继续编程。若键盘K3按下,也进入中断状态:LED1、LED2、LED3反向流水灯功能(即依次顺序点亮,从下到上),LED间隔时间0.2S; 经过3 次循环后,结束中断。要求:键盘K3 中断级别 比 键盘K2 中断级别高。

首先主函数先进行各个模块的初始化,while死循环则使3个灯循环点亮。

实验二 、中断实验

KEY2对应的外部中断的服务函数

实验二 、中断实验

KEY3对应的外部中断的服务函数

实验二 、中断实验

main函数代码

//STM32的头文件
#include <stm32f10x.h>
//STM32函数
#include "delay.h"
/**************************************************
* Function       main
* @author        行走的皮卡丘
* @date          2021/3/24 
* @brief        
* @param[in]    
* @param[out]    void
* @retval        void
* @par History   无
*	LED1 ---> PB.0
*	LED2 ---> PC.4
*	LED3 ---> PC.3
*   KEY1 ---> PA0
*   KEY2 ---> PC13
*************************************************/
//定义LED1 LED2 LED3 方便管理修改和命名查看
//对应的IO硬件
// LED1  LED2  LED3
// PB4   PC4   PC3
#define LED1 PBout(0)    
#define LED2 PCout(4)
#define LED3 PCout(3)

//定义读取按键的定义
//对应的IO硬件
// KEY2    KEY3
// PA0     PC13
#define KEY2  GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键 
#define KEY3  GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)//读取按键 

//应用于控制LED的变量
short i = 0;

//LED函数
void LED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStr;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);//   
	
	
	GPIO_InitStr.GPIO_Mode=GPIO_Mode_Out_PP;//推挽
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStr.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStr);  // PB0   LED1
	
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_4;
	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC4   LED2
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_3;
	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC3   LED3

	GPIO_SetBits(GPIOB,GPIO_Pin_0); 
	GPIO_SetBits(GPIOC,GPIO_Pin_4); 
	GPIO_SetBits(GPIOC,GPIO_Pin_3); 
}

//按键函数
void KEY_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStr;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);  //开启时钟
	
	
	GPIO_InitStr.GPIO_Mode=GPIO_Mode_IPD;//下拉输入
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_0;
	GPIO_Init(GPIOA,&GPIO_InitStr);  // PA0   KEY2
	
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_13;
	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC13   KEY3
}

//中断函数
void EXTIX_Init(void)
{
 
   	EXTI_InitTypeDef EXTI_InitStructure;
 	  NVIC_InitTypeDef NVIC_InitStructure;

    KEY_Init();	 //	按键端口初始化

  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能复用功能时钟



   //GPIOA—0  中断线以及中断初始化配置 上升沿触发 //KEY2
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  	EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
	
	 //GPIOC.13	  中断线以及中断初始化配置 下降沿触发 //KEY3
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line13;
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  	EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


  	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			//使能按键KEY2所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//抢占优先级1 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;					//子优先级1 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
		
		NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;			//使能按键KEY3所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	//抢占优先级0 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;					//子优先级1 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}

//外部中断0服务程序 
void EXTI0_IRQHandler(void)
{
	if( KEY2 == 1)	 	 //KEY2按键  硬件上以消抖
	{				 
		i++;
		
		switch( i%4)
		{
			case 1: LED1 = 0; LED2 = 1; LED3 = 1; delay_ms(1000); break;
			case 2: LED1 = 0; LED2 = 0; LED3 = 1; delay_ms(1000); delay_ms(1000); break;
			case 3: LED1 = 0; LED2 = 0; LED3 = 0; delay_ms(1000); delay_ms(1000); delay_ms(1000);i=0;break;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位  
}

//外部中断0服务程序 
void EXTI15_10_IRQHandler(void)
{
  short  n;
	if( KEY3 == 0)	 	 //KEY3按键  硬件上以消抖
	{		
		for(n = 0; n<3; n++)
		{
			LED1 = 1; LED2 = 1;  LED3 = 0;	delay_ms(200);
			LED1 = 1; LED2 = 0;  LED3 = 1;	delay_ms(200);
			LED1 = 0; LED2 = 1;  LED3 = 1;	delay_ms(200);
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line13); //清除LINE0上的中断标志位  
}

//主函数
int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    //分别
	delay_init(); 
	LED_Init();
	KEY_Init();
	EXTIX_Init();
	
	while(1)
	{
			LED1 = 0; LED2 = 1;  LED3 = 1;	delay_ms(200);
			LED1 = 1; LED2 = 1;  LED3 = 1;	delay_ms(200);
			LED1 = 1; LED2 = 0;  LED3 = 1;	delay_ms(200);
			LED1 = 1; LED2 = 1;  LED3 = 1;	delay_ms(200);
			LED1 = 1; LED2 = 1;  LED3 = 0;	delay_ms(200);
								
			
	}
	
}

任务二、 利用定时器编程实现以下内容:

LED1交替亮灭,间隔时间0.2S。

定时器中断服务函数

实验二 、中断实验

时钟初始化函数

实验二 、中断实验

main函数

//STM32的头文件
#include <stm32f10x.h>
//STM32函数
#include "delay.h"
/**************************************************
* Function       main
* @author        行走的皮卡丘
* @date          2021/3/24 
* @brief        
* @param[in]    
* @param[out]    void
* @retval        void
* @par History   无
*	LED1 ---> PB.0
*	LED2 ---> PC.4
*	LED3 ---> PC.3
*   KEY1 ---> PA0
*   KEY2 ---> PC13
*************************************************/
//定义LED1 LED2 LED3 方便管理修改和命名查看
//对应的IO硬件
// LED1  LED2  LED3
// PB4   PC4   PC3
#define LED1 PBout(0)    
#define LED2 PCout(4)
#define LED3 PCout(3)

//定义读取按键的定义
//对应的IO硬件
// KEY2    KEY3
// PA0     PC13
#define KEY2  GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键 
#define KEY3  GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)//读取按键 

void LED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStr;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);//   
	
	
	GPIO_InitStr.GPIO_Mode=GPIO_Mode_Out_PP;//推挽
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStr.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStr);  // PB0   LED1
	
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_4;
	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC4   LED2
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_3;
	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC3   LED3

	GPIO_SetBits(GPIOB,GPIO_Pin_0); 
	GPIO_SetBits(GPIOC,GPIO_Pin_4); 
	GPIO_SetBits(GPIOC,GPIO_Pin_3); 
}

void KEY_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStr;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);  //开启时钟
	
	
	GPIO_InitStr.GPIO_Mode=GPIO_Mode_IPD;//下拉输入
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_0;
	GPIO_Init(GPIOA,&GPIO_InitStr);  // PA0   KEY2
	
	GPIO_InitStr.GPIO_Pin=GPIO_Pin_13;
	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC13   KEY3
}


//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  //先占优先级3级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
		LED1=!LED1;
	}
}


int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	delay_init();
	LED_Init();
	KEY_Init();
  TIM3_Int_Init(1999,7199);//10Khz的计数频率,计数到2000为200ms  
	
	while(1)
	{						
			
	}
	
}

三、实验总结

加油!!!行走的皮卡丘!!!!

实验二代码下载链接(包含任务一、任务二)

上一篇:蓝桥杯嵌入式第12届模拟赛


下一篇:STM32CUBEMX点亮LED灯