第四章 STM32学习——对射式红外传感器计次

目录

1. 封装

外部中断配置步骤

开启RCC时钟怎么理解?

为什么总线要分APB1/APB2?

2. 配置外部中断

2.1 开启RCC、AFIO时钟

2.2 配置GPIO(和前几章步骤一样)

2.3 配置AFIO外部中断引脚选择

2.4 配置EXTI(exti.h)

2.5 配置NVIC(misc.h)

2.6 中断程序

2.7 统计中断触发的次数


1. 封装

把传感器功能封装在模块

新建.c 和.h文件

添加头文件和格式

然后,在 void CountSensor_Init(void) 函数中配置外部中断


外部中断配置步骤

a.配置RCC,打开外部时钟

b.配置GPIO,端口选择输入模式

c.配置AFIP,选择用到的GPIO,连接到EXTI

e.配置EXTI,选择边沿触发方式

f.配置NVIC,给中断的选择合适的优先级

最后通过NVIC,外部中断信号进入CPU


开启RCC时钟怎么理解

举例来说就是:

RCC是总电闸室

APB2是其中一条电路线

GPIOB是3楼B房间

开启时钟就是让电工(RCC)把3楼B房间(GPIOB)的电闸合上,才能通电


为什么总线要分APB1/APB2?

就像高速公路分快慢车道:

APB2:高速车道(挂GPIO、高速外设)

APB1:普通车道(挂定时器、串口等)


2. 配置外部中断

2.1 开启RCC、AFIO时钟

//开启RCC时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//开启AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

EXTI、NVIC外设的时钟一直处于打开状态,不用再打开

2.2 配置GPIO(和前几章步骤一样)

 //配置GPIO
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);

2.3 配置AFIO外部中断引脚选择

库函数在GPIO中

了解一下AFIO的配置(gpio.h)

GPIO_PinRemapConfig进行引脚重映射

GPIO_EXTILineConfig配置AFIO的数据选择器,选择想要的中断引脚


这里用到GPIO_EXTILineConfig,右键跳转定义,选择参数

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);

2.4 配置EXTI(exti.h)

EXTI_DeInit   清除配置,恢复上电默认的状态
EXTI_Init   配置外设
EXTI_StructInit   参数传递的结构体变量赋值一个默认值
EXTI_GenerateSWInterrupt   软件触发外部中断
EXTI_GetFlagStatus   获取指定的标志位是否被置1
EXTI_ClearFlag   对置1的标志位清除
EXTI_GetITStatus   获取中断标志位是否被置1
EXTI_ClearITPendingBit   清除中断挂起标志位


调用 EXTI_Init,右键跳转定义,复制结构体类型名字 EXTI_InitTypeDef

起变量名 EXTI_InitStructure,“.”引出结构体成员

EXTI_Line,指定配置的中断线,右键跳转定义

ctrl+f搜索,选择EXTI_Line14

另外几个结构体一样的操作

    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line14;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    EXTI_Init(&EXTI_InitStructure);

2.5 配置NVIC(misc.h)

一样的操作,这里省略

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitTypeDef NVIC_InitStructure;
    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);

2.6 中断程序

点开启动文件md.s,以IRQHandler结尾的字符串就是中断函数的名字

复制EXTI15_10_IRQHandler,中断函数无参无返回值

void EXTI15_10_IRQHandler(void)

然后进行中断标志位的判断

到exti.h里复制EXTI_GetITStatus,跳转参数

判断返回值是不是 = = SET

中断程序结束后,调用清除中断标志位的函数,只有中断标志位置为1,程序会跳转到中断函数,如果不清除中断标志位,就会一直申请中断,程序卡死在中断函数里

void EXTI15_10_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line14) == SET)
    {
        EXTI_ClearITPendingBit(EXTI_Line14);
    }
}

然后测试是否能进入中断

初始化函数在头文件中声明,中断函数不用声明,它是自动执行的

main.c文件

2.7 统计中断触发的次数

定义变量

中断函数加入CountSensor_Count ++;并返回变量,头文件声明

CountSensor.h文件

在main.c文件里,循环调用OLED_ShowNum,显示计次的数据

CountSensor.c 全部代码

#include "stm32f10x.h"                  // Device header

uint16_t CountSensor_Count;

void CountSensor_Init(void)
{
    //开启RCC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    //开启AFIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    
    //配置GPIO
    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;
    EXTI_InitStructure.EXTI_Line = EXTI_Line14;
    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;
    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)
    {
        CountSensor_Count ++;
        EXTI_ClearITPendingBit(EXTI_Line14);
    }
}
 


太忙了,好久没学习了,挤出时间终于把文章写完了,如果对你有帮助的话点个免费的关注和赞吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值