在单片机中存在着中断系统,这个系统的逻辑和功能在51单片机中已经有所了解。
1.在32单片机中的内核有一个nvic 里面存放许多优先级的设定,外接许多中断源,比如“exti、tim、adc、usart等”接入之后,nvic再通过中断优先级进行排队,再内接入cpu中进行处理,这样子大大减少了cpu的运算,提高了工作效率。
2.其中里面的优先级又有响应优先级 抢占优先级,响应的可以进行优先排队(插队),而抢占可以进行中断嵌套。
3.exti外部中断,注意在支持的gpio口中,不能选择pin相同的来同时触发,比如pa1不能与pb1等等。
4.在外部中断的结构中,有一个afio中断引脚选择,就是一个选择器,用来选择是那个引脚触发。触发方式有上升沿、下降沿、双边沿、软件触发。
5.在exti框图中,当接入的线,可以选择上升、下降来选择触发,出来的值与软件中断事件寄存器进行相或(有1则为1)。出来的值,兵分两路,其一接入请求挂起寄存器,出来与中断屏蔽寄存器共同相与,则中断屏蔽给1,则输出请求挂起的值,给0,则直接输出0。
======================================
代码部分
#include "stm32f10x.h" // Device header
uint16_t CountSensor_Count;
void CountSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //注意GPIOB是APB2的外设
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //注意AFIO是APB2的外设
//EXTI和NVIC外设的时钟是一直打开的,不需要打开了,NVIC属于内核外设,均不用开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //外部中断:浮空、上拉、下拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//配置AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
//配置EXTI
EXTI_InitTypeDef EXTI_InitStructure; //起个变量名 同GIPO一样
EXTI_InitStructure.EXTI_Line = EXTI_Line14; //指定配置的中断线 14对应pin14
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //指定中断线的状态 ENABLE开启中断
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_Falling下降沿 EXTI_Trigger_Rising_Falling双边沿
EXTI_Init(&EXTI_InitStructure);//初始化
//配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//指定中断优先级分组,2组即是2响应2抢占,整个工程(芯片)只需要一种即可
NVIC_InitTypeDef NVIC_InitStructure; //起个变量名 同GIPO一样
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //指定中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定中断通道是使能还是失能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定抢占取值范围,即是优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定响应取值范围,即是优先级
NVIC_Init(&NVIC_InitStructure);//初始化
}
uint16_t CountSensor_Get(void)
{
return CountSensor_Count;
}
void EXTI15_10_IRQHandler(void) //中断函数
{
if (EXTI_GetITStatus(EXTI_Line14) == SET) //中断标志位判断,因为EXTI_Line10-EXTI_Line15都能进来,判断是否14进来
//如果是等于set(1),则可以进入中断程序
{
/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
{
CountSensor_Count ++;
}
EXTI_ClearITPendingBit(EXTI_Line14); //清除中断标志位
}
}
======================================
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"
int main(void)
{
OLED_Init();
CountSensor_Init();
OLED_ShowString(1, 1, "Count:");
while (1)
{
OLED_ShowNum(1, 7, CountSensor_Get(), 5);
}
}
======================================
补充
上图可以看到APB2总线可以连接的外设
介绍一下相关函数:
void GPIO_AFIODeInit(void);复位AFIO
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);锁定GPIO,
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState); 配置事件输出
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
用来进行引脚重映射,参数1选择重映射方式,参数2是新的状态 。
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
调用此函数,可以配置AFIO的数据选择器,选择中断引脚,参数1可以选择GPIOA-G,参数2选择pin0-15。
=========
exti
void EXTI_DeInit(void);调用这个函数,可以清除exti的配置,恢复上电默认状态
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);初始化
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);调用之后,可以把参数传递的结构体变量赋一个默认值
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
软件触发外部中断,参数给指定的中断线
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);读写状态寄存器
void EXTI_ClearFlag(uint32_t EXTI_Line);
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
在单片机中存在着中断系统,这个系统的逻辑和功能在51单片机中已经有所了解。
1.在32单片机中的内核有一个nvic 里面存放许多优先级的设定,外接许多中断源,比如“exti、tim、adc、usart等”接入之后,nvic再通过中断优先级进行排队,再内接入cpu中进行处理,这样子大大减少了cpu的运算,提高了工作效率。
2.其中里面的优先级又有响应优先级 抢占优先级,响应的可以进行优先排队(插队),而抢占可以进行中断嵌套。
3.exti外部中断,注意在支持的gpio口中,不能选择pin相同的来同时触发,比如pa1不能与pb1等等。
4.在外部中断的结构中,有一个afio中断引脚选择,就是一个选择器,用来选择是那个引脚触发。触发方式有上升沿、下降沿、双边沿、软件触发。
5.在exti框图中,当接入的线,可以选择上升、下降来选择触发,出来的值与软件中断事件寄存器进行相或(有1则为1)。出来的值,兵分两路,其一接入请求挂起寄存器,出来与中断屏蔽寄存器共同相与,则中断屏蔽给1,则输出请求挂起的值,给0,则直接输出0。
======================================
代码部分
#include "stm32f10x.h" // Device header
uint16_t CountSensor_Count;
void CountSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //注意GPIOB是APB2的外设
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //注意AFIO是APB2的外设
//EXTI和NVIC外设的时钟是一直打开的,不需要打开了,NVIC属于内核外设,均不用开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //外部中断:浮空、上拉、下拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//配置AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
//配置EXTI
EXTI_InitTypeDef EXTI_InitStructure; //起个变量名 同GIPO一样
EXTI_InitStructure.EXTI_Line = EXTI_Line14; //指定配置的中断线 14对应pin14
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //指定中断线的状态 ENABLE开启中断
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_Falling下降沿 EXTI_Trigger_Rising_Falling双边沿
EXTI_Init(&EXTI_InitStructure);//初始化
//配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//指定中断优先级分组,2组即是2响应2抢占,整个工程(芯片)只需要一种即可
NVIC_InitTypeDef NVIC_InitStructure; //起个变量名 同GIPO一样
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //指定中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定中断通道是使能还是失能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定抢占取值范围,即是优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定响应取值范围,即是优先级
NVIC_Init(&NVIC_InitStructure);//初始化
}
uint16_t CountSensor_Get(void)
{
return CountSensor_Count;
}
void EXTI15_10_IRQHandler(void) //中断函数
{
if (EXTI_GetITStatus(EXTI_Line14) == SET) //中断标志位判断,因为EXTI_Line10-EXTI_Line15都能进来,判断是否14进来
//如果是等于set(1),则可以进入中断程序
{
/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
{
CountSensor_Count ++;
}
EXTI_ClearITPendingBit(EXTI_Line14); //清除中断标志位
}
}
======================================
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"
int main(void)
{
OLED_Init();
CountSensor_Init();
OLED_ShowString(1, 1, "Count:");
while (1)
{
OLED_ShowNum(1, 7, CountSensor_Get(), 5);
}
}
======================================
补充
上图可以看到APB2总线可以连接的外设
介绍一下相关函数:
void GPIO_AFIODeInit(void);复位AFIO
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);锁定GPIO,
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState); 配置事件输出
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
用来进行引脚重映射,参数1选择重映射方式,参数2是新的状态 。
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
调用此函数,可以配置AFIO的数据选择器,选择中断引脚,参数1可以选择GPIOA-G,参数2选择pin0-15。
=========
exti
void EXTI_DeInit(void);调用这个函数,可以清除exti的配置,恢复上电默认状态
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);初始化
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);调用之后,可以把参数传递的结构体变量赋一个默认值
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
软件触发外部中断,参数给指定的中断线
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);读写状态寄存器
void EXTI_ClearFlag(uint32_t EXTI_Line);
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
评论记录:
回复评论: