STM32中断梅开二度(一)

目录

一.中断的组成和理解

 1.1中断:

1.2中断优先级:

1.3中断嵌套

1.4中断图解:                                                              1.5中断嵌套图解:

 1.5中断的类型

1.6NVIC优先级分组

响应优先级:

抢占优先级:

二.EXTI外部中断

2.1触发方式:

注意:EXTI支持所有的GPIO口,但是相同的IO口号不可以同时申请中断,比如PB0和PA0不可以同时申请配置中断。

2.2EXTI基本结构

2.2.1AFIO

2.2.2EXTI通道对应的NVIC中断处理

三.EXTI中断配置编码器和对射式红外传感器代码思路和解析

四.TIM中断定时器和PWM波输出

4.1定时器相关理解

4.1.1定时器种类

4.1.2TIM计数器的计数模式:

4.2整个配置流程

4.2PWM输出比较OC


一.中断的组成和理解

 1.1中断:

     在主程序运行过程中,出现中断源(特定的中断触发条件),使得CPU先去处理中断程序,然后继续按照主程序执行。

1.2中断优先级:

   多个中断源同时申请中断时,根据优先级的排列逐一执行。

1.3中断嵌套

   一个中断程序正在运行时,有新的更高优先级的中断源申请中断,从而暂停当前中断函数,执行高优先级的中断处理函数。处理后依次返回。

1.4中断图解:                                                              1.5中断嵌套图解:

 1.5中断的类型

   EXTI外部中断、TIM、ADC、USART、SPI、IIC等多个外设。都是使用NVIC统一管理中断,每个中断有16个可编程优先等级。对优先级进行分组,进一步设置抢占优先级和响应优先级。

1.6NVIC优先级分组

 NVIC身为中断管理,他的中断优先级是优优先级寄存器的4位决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级。下图位优先级分组方式:

响应优先级:

在执行一个中断函数时,响应优先级高的不会让中断函数停止执行自己的中断函数,而是等目前执行的中断函数执行完毕,下一个执行自己的中断函数。也就是插队。

抢占优先级:

即使目前已经有中断函数执行,也会暂停该函数,执行抢占优先级高的中断函数。也就是中断嵌套。

二.EXTI外部中断

EXTI是指定GPIO口电平变化而产生的中断。

2.1触发方式:

上升沿/下降沿/双边沿/软件触发。可以想象一下,一个IO口电平变化不是瞬时的,从高电位到低电位会有一段向下的电平变化线,这就是下降沿。其他可以类推。

软件触发就是自己在程序代码中设定的触发。

EXTI的通道数有16个,但是部署之后会自带4个"蹭网"的通道,PVD,RTC,USB,以太网。

注意:EXTI支持所有的GPIO口,但是相同的IO口号不可以同时申请中断,比如PB0和PA0不可以同时申请配置中断。

这里再补充一句:GPIOA,B,C,D都会有16个IO口,即0-15,但是EXTI最多就接收16个通道,所以相同的IO口号不可以同时配置中断。

2.2EXTI基本结构

GPIO口选择------>AFIO中断引脚选择------>EXTI边沿检测和控制------->NVIC管理------->CPU执行。

2.2.1AFIO

AFIO数据选择器,讲GPIO的IO口号连接到EXTI,同时EXTI的16个通道0-15,连接对应AFIO选择的引脚0-15。比如AFIO选择GPIO_B1那么EXTI对应配置上的通道就是通道1。

2.2.2EXTI通道对应的NVIC中断处理

为了节省资源,EXTI的0-15通道对应的NVIC处理不会有15个,对于STM32C8T6来说,EXTI5-9和EXTI 10-15是一个通道。

即5-9和10-15会触发同一个中断函数。

三.EXTI中断配置编码器和对射式红外传感器代码思路和解析

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

void Encoder_Init(void)
{//CODE五部曲
	//1.配置时钟RCC
//	2.配置GPIO数据
//	3.配置AFIO
//	4.配置EXTI
//	5.配置NVIC
	//1.
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	//2.
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//3.  AFIO的代码就是显示为EXTI
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);
	//4.
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	//5.
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);
}

int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}

void EXTI2_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line2) == SET)
	{
		if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == 0)
		{
			Encoder_Count --;
		}
		EXTI_ClearITPendingBit(EXTI_Line2);
	}
}

void EXTI3_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line3) == SET)
	{
		if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == 0)
		{
			Encoder_Count ++;
		}
		EXTI_ClearITPendingBit(EXTI_Line3);
	}
}

四.TIM中断定时器和PWM波输出

4.1定时器相关理解

定时器可以对输入的时钟进行技术,并在计数值达到ARR(重装载值)触发中断。根据STM32型号的不同基准时钟不同,可以进行最大的定时也不同。

时基单元:PSC(预分频器),CNT(计数器),ARR(重装载值)组成。这些都是16位寄存器。

注意:实际分频系数=PSC+1,比如1分频那么PSC=0。

4.1.1定时器种类

 使用较多的就是通用定时器,如果不知道挂载哪个总线,可以输入一个总线查看头文件说明即可。

4.1.2TIM计数器的计数模式:

向上计数/向下计数/中央对齐。中央对齐就是0-ARR-0 触发两次。通用定时器和高级定时器可以选择三种。基本定时器就只可以向上啦。

补充:定时器时钟源选择可以是内部和外部,基本定时器仅可以内部。

4.2整个配置流程

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{	//开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	//选择内部时钟源
	TIM_InternalClockConfig(TIM2);
	//配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	//配置NVIC分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	//NVIC通道选择和优先级配置
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	//使能
	TIM_Cmd(TIM2, ENABLE);
}

4.2PWM输出比较OC

在TIM的基础上配置一下CCR即可。

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{	//配置时钟源
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);//选择内部时钟源
	//配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	//配置CCR 
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
	//使能TIM2
	TIM_Cmd(TIM2, ENABLE);
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自动控制自己

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值