STM32 学习笔记(3)中断

stm32的中断功能比较丰富,首先要了解下NVIC(嵌套向量中断控制器),在core_CM3.h中有定义NVIC_Type。关键使用这三个寄存器,ISER 中断使能寄存器、ICER中断清除(失能)寄存器、IP优先级寄存器8位。

NVIC有个专用的寄存器来配置外部中断的优先级,NVIC_IPRx。F103使用了高4位,低四位没有使用。注意:

(1)这四位有分成了抢占优先级和子优先级。

1)多个中断同时来临时,抢占优先级高的会比抢占优先级低的先得到执行。

2)抢占优先级相同的,比较子优先级,子优先级高的先执行。

3)如果抢占、子优先级都相同的话,比较硬件中断号,编号越小,优先级越高。

4)要注意,优先级号越低,优先级越高。

在STM32 中进行了分组:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)函数进行配置分组。

NVIC_PriorityGroup_0:     0bit for 抢占优先级       4 bits for 子优先级;(优先级抢占不存在,有子优先级控制。)

NVIC_PriorityGroup_1:     1 bit for 抢占优先级       3 bits for 子优先级;

NVIC_PriorityGroup_2:     2 bit for 抢占优先级        2 bits for 子优先级;

共有0~4 五组。

如何进行中断编程呢?

(1)先使能外设某个中断

(2)初始化NVIC_InitTypeDef 结构体。这个结构体包含中断源、抢占优先级、子优先级和使能或失能中断。

1)NVIC_IROChannel在stm32f10x.h 中IRQn_Type 中定义。

2)NVIC_IRQChannelPreemptionPriority:抢占优先级

3)NVIC_IRQChannelSubPriority:子优先级

4)NVIC_IRQChannelCmd;中断使能(ENABLE)或者失能(DISABLE)  

(3)编写中断服务函数

在启动文件中预先为每一个中断都写了中断服务函数,都是空的,用来初始化中断向量表。重新在stm32f10x_it.c 编写中断服务函数。

(4)EXTI(External interrupt/event controller)—外部中断/事件控制器 

看这幅图(来源野火)

 

EXTI0 至EXTI15 用于GPIO。EXTI0 可以通过AFIO的外部中断配置寄存器1(AFIO_EXTICR1)的EXTI0[3:0]位选择配置为PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0 或者PI0。

结构体:typedef struct {
 uint32_t EXTI_Line; // 中断/事件线
 EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
 EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
 FunctionalState EXTI_LineCmd; // EXTI 使能
 } EXTI_InitTypeDef;

 

NVIC配置:

static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

    //优先组1
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    // 中断源key1
	NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
    //抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	//子优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	//中能中断
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	//初始化NVIC
	NVIC_Init(&NVIC_InitStructure);

	// 中断源KEY2
	NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
		//初始化NVIC
	NVIC_Init(&NVIC_InitStructure);
}


EXITI 配置:

void EXIT_Key_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	EXTI_InitTypeDef  EXTI_InitStruct;
	
	// 配置中断优先级
	NVIC_Configuration();
	
	// 初始化GPIO
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK, ENABLE);	
	GPIO_InitStruct.GPIO_Pin = KEY1_INT_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;		
	GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStruct);	
	
	// 初始化EXTI
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK, ENABLE); // 时钟
	
	GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE);
	
	EXTI_InitStruct.EXTI_Line = KEY1_INT_EXTI_LINE;
	
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;      // 中断模式
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;   //上升沿中断
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;                //中断使能
	EXTI_Init(&EXTI_InitStruct);	
	
	
		// 初始化GPIO
	RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK, ENABLE);	
	GPIO_InitStruct.GPIO_Pin = KEY2_INT_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;		
	GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStruct);	
	
	// 初始化EXTI
	RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK, ENABLE); // 时钟
	
	GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE);
	
	EXTI_InitStruct.EXTI_Line = KEY2_INT_EXTI_LINE;
	
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;      // 中断模式
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;   //下升沿中断
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;                //中断使能
	EXTI_Init(&EXTI_InitStruct);		
}

我们在stm32f10x_it.c 中写中断服务函数


void EXTI0_IRQHandler (void)
{
	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET)         //读是否产生了中断,
	{
		LED1_TOGGLE;     //LED1翻转
	}
	EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);   // 清除中断标志位
}



void KEY2_IRQHandler (void)
{
	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET)         //读是否产生了中断,
	{
		LED2_TOGGLE;     //LED1翻转
	}
	EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);   // 清除中断标志位
}

 

main.c 中包含相关头文件后,

while(1){;}

循环就可以了。

注意:(1)初始化GPIO时钟 GPIO ,(2)配置NVIC (3)初始化EXITI 时钟,信号源、边沿触发、使能中断 EXITI_Init() (4)编写中断服务函数;(5)EXTI_GetITStatus()中断检测 ,EXTI_ClearITPendingBit(); 中断标志位清除。

(6)EXITI10~EXITI15 公用一个处理函数。

当MDK注释出现乱码:处理如下

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值