5.EXIT外部中断

使用外部中断步骤:(以对射式传感器计数为例,1-6为完整中断需要的步骤,其余自设)

1.开启时钟

    /**开启GPIO与AFIO外设的时钟,EXIT在外设中是默认开启的,
NVIC是内核外设(相当于皇帝(CPU)身边太监,可以帮忙下达命令,管理中断),也默认开启**/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

 2.配置GPIO输入

    GPIO_InitTypeDef GPIO_Structure;
    GPIO_Structure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Structure.GPIO_Pin =GPIO_Pin_14;
    GPIO_Init(GPIOB,&GPIO_Structure);

3.AFIO选择中断引脚

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);

4.配置EXTI数据选择器

  //配置EXIT寄存器配置,因为只有一个,不需要像GPIO一样选择端口
    EXTI_InitTypeDef EXTI_Structure;             //结构体命名
    EXTI_Structure.EXTI_Line = EXTI_Line14;      //对应Pin14    
    EXTI_Structure.EXTI_LineCmd = ENABLE;        //开启中断
    EXTI_Structure.EXTI_Mode = EXTI_Mode_Interrupt;       //选择中断模式
    EXTI_Structure.EXTI_Trigger = EXTI_Trigger_Falling;  //触发方式:下降沿    
    EXTI_Init(&EXTI_Structure);//调用函数,完成配置

5.配置NVIC的寄存器,设置中断优先级

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    //配置优先级分组,2组两位抢占,两位响应,整个芯片只能用一种分组方式,可放主函数最开始
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel =  EXTI15_10_IRQn; //选择通道,该通道包含10-15,包含Pin14
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;       //使能中断通道
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //设置抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority =  1; //设置响应优先级
    /** 分组2:2位抢占优先级,2位响应优先级,取值范围都为0-3,即2的2次方
        多个中断产生拥挤时,才有作用**/
    NVIC_Init(&NVIC_InitStruct); 

6.写中断程序(识别到中断触发就跳到该程序)

每个EXIT线路都有属于自己的函数名,可在.s文件查看

void EXTI15_10_IRQHandler(void) //不需要声明,因为不用调用,自动执行
{
    if (EXTI_GetITStatus(EXTI_Line14) == SET);//10-15口公用一个函数,判断是否是14口
    {
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
        {   
            Delay_ms(10);
            if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)//消抖
                {       
                        
                        Delay_ms(10);
                        Count ++;
            
                }

        }   
        EXTI_ClearITPendingBit(EXTI_Line14); //清楚14口的中断标志位,否则会卡死在中断里
    }
    

}

注:不写消抖程序会出现遮和拿开时都计数,改成下拉输入也可以解决该问题,个人猜测原因:红外对射式传感器正常状态是输入低电平,遮挡时输入高电平,由于上拉输入,在未遮挡完(产生抖动)就被上拉为高电平,此时其实还是低电平,又快速下降,实现一次计数。

7.返回计数值

uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}

8.mian.c文件调用

int main(void)
{
    OLED_Init();
    CountSensor_Init();
    OLED_ShowString(1,1,"Count:");

    
    while(1)
    {
        OLED_ShowNum(1,7,Count_Get(),5);//获取返回值,在OLED上显示
        
    }


}

9.(改写)用EXTI15_10端口实现旋转编码器计数

.h文件配置

void Encoder_Init(void)
{
    //开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    //配置GPIOA和B
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;        
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;        
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    
    //配置AFIO通道
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);

    //配置EXTI
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line14|EXTI_Line15;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&EXTI_InitStructure);

    //配置NVIC
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
    /**15到10共用一个,后续需要通过读取中断标志位,识别不同口的中断**/
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStructure);  

}

int16_t Encoder_get(void)
{
    int16_t Temp;
    Temp = Encoder_Count;
    Encoder_Count=0; 
/**如果不清0,由于有数值在main.c中会无无限加+1,清0后就是+0,直到下次触发变为1**/
    return Temp ;

}

void EXTI15_10_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line14) == SET)// 14口触发中断程序
    {
        if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)==1)
        {
            Encoder_Count--;
        }
        
        EXTI_ClearITPendingBit(EXTI_Line14);
    
    }

    if (EXTI_GetITStatus(EXTI_Line15) == SET) //15口触发中断程序
    {
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==1)
        {
            Encoder_Count ++;
        }
        
        EXTI_ClearITPendingBit(EXTI_Line15);
    
    }

}

main.c文件

int main(void)
{
    Encoder_Init();
    OLED_Init();

    
    OLED_ShowString(1,1,"Num:");

    
    while(1)
    {
        Num+= Encoder_get();
        OLED_ShowSignedNum(1,5,Num,5);
    }


}

另一种更简洁的累加方式

.h文件中修改
int16_t Encoder_get(void)
{
    return Encoder_Count;
}


.c文件修改
 while(1)
 {
     Num= Encoder_get();
     OLED_ShowSignedNum(1,5,Num,5);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值