STM32学习笔记之EXTI应用实例:对射式红外传感器计次

系列文章目录

第N章 STM32学习笔记之OLED屏幕

第N章 STM32学习笔记之EXTI外部中断

第N章 STM32学习笔记之对射式红外传感器计次


目录

系列文章目录

一、对射式红外传感器

1.简介

2.硬件电路

二、软件驱动

1.模块化编程

2.初始化函数

a.开启外设时钟

b.配置GPIO

c.配置AFIO

d.配置EXTI

e.配置NVIC

3.编写中断函数

4.声明初始化函数

5.main函数处理

三、功能实现

1.传感器.c文件

1.传感器.h文件

3.main.c文件

总结


前言:

笔记:跟着B站教学视频做的学习笔记,基于STM32F103C8T6


一、对射式红外传感器

1.简介

测速传感器模块,可用于电机转速检测,脉冲计数,位置限位等

  • 输出状态指示灯:输出高电平-灯灭  输出低电平-灯亮
  • 遮挡:输出低电平;无遮挡:输出高电平
  • 输出形式:数字开关量输出(0到1)

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第1张图片

2.硬件电路

VCC:接电源正极-3.3V~5V

GND:接电源负极

DO:TTL开关信号输出,这里接STMF103C8T6的PB14引脚

AO:此模块不起作用,不用接

二、软件驱动

1.模块化编程

新增红外传感器模块.c和.h文件和一些预处理,详情见第N章 STM32....

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第2张图片

2.初始化函数

根据EXTI基本结构图可以看出,使用外部中断需要配置GPIO、AFIO、EXTI、NVIC这些外设

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第3张图片

a.开启外设时钟

外设工作需要先开启时钟,由于EXTI和NVIC外设时钟是一直开启的,所以只需要开启GPIO和AFIO的时钟就好

void CountSensor_Init(void)
{

    //GPIO时钟在APB2总线上
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  

    //AFIO时钟在APB2总线上
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

    //NVIC和EXTI时钟总是开着的,不需要再开启  
}

b.配置GPIO

  • 定义一个GPIO结构体
  • GPIO_Mode:根据数据手册得知有三种配置方式,这里配置成上拉输入,即默认为高电平输入方式

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第4张图片

  • GPIO_Pin:这里选择14号口
  • GPIO_Speed:不是很重要,选择50M即可
  • 调用GPIO初始化函数对GPIO结构体进行初始化

void CountSensor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   
    
    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);
    
}

c.配置AFIO

AFIO的库函数是和GPIO在同一个文件里的,可以在GPIO的.h文件里找

  • 调用GPIO_EXTILineConfig()函数来配置AFIO数据选择器,配置完成后就进入到EXTI电路了

void CountSensor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   
    
    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);
    //因为是PB14,所以两个参数分别是PortSourceGPIOB和PinSource14
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);    
}

d.配置EXTI

在库函数中找到exti.h文件

  • 定义一个EXTI结构体
  • EXTI_Line:指定配置的中断线,因为需要用PB14所在的第14个线路,所以选择EXTI_Line14
  • EXTI_LineCmd:指定中断线的状态,因为要开启中断,所以选择“ENABLE”
  • EXTI_Mode:指定外部中断线的模式,中断模式和事件模式中,选择“中断模式”
  • EXTI_Trigger:指定触发信号的有效边缘,自我选择“上升沿触发”
  • 调用EXTI初始化函数对EXTI结构体进行初始化

void CountSensor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   
    
    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);
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);    
    
    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_InitStruct.EXTI_Line = EXTI_Line14;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&EXTI_InitStruct);
}

e.配置NVIC

因为NVIC是内核外设,它的库函数被ST发配到misc.h(杂项)文件里,在这里找它的库函数

  • NVIC_PriorityGroupConfig:指定下中断的分组,这里选择两位抢占两位响应
  • 定义一个NVIC结构体
  • NVIC_IRQChannel:因为库函数所以兼容所以的F1系列芯片,但是不同的芯片中断通道列表是不一样的,所以有很多条件编译,这里选择MD(中等密度)里的EXTI15_10_IRQn

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第5张图片

  • NVIC_IRQChannelCmd:指定中断通道是使能还是失能,选择“ENABLE”
  • NVIC_IRQChannelPreemptionPriority:抢占优先级,这里只有一个中断源,比较随意,设置为1即可
  • NVIC_IRQChannelSubPriority:响应优先级,这里只有一个中断源,比较随意,设置为1即可
  • 调用NVIC初始化函数初始化结构体

void CountSensor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 
    
    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);
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);    
    
    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_InitStruct.EXTI_Line = EXTI_Line14;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&EXTI_InitStruct);
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStruct);
}

3.编写中断函数

在STM32中,中断通道的名字都是固定的,每个中断通道都对应一个中断函数,可以在启动文件里查看,里面以“ IRQHandler ”结尾的字符串就是中断函数的名字

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第6张图片

找到“  EXTI15_10_IRQHandler ”这一项,这就是EXTI15_10的中断函数,复制后回到.c文件里编写中断函数

  • 中断函数都是无参无返回值的
  • 中断函数名字不要写错,写错就进不来中断

void EXTI15_10_IRQHandler(void)
{

}

  • 中断函数一般先进行一个中断标志位的判断,因为这个函数EXTI10~15都能进来,所以要判断下是不是EXTI14进来的,所以用EXTI_GetFlagStatus函数看下中断标志位是不是1,它的返回值是SET或者RESET,即看下这个返回值是不是等于SET

void EXTI15_10_IRQHandler(void)
{
    if(EXTI_GetFlagStatus(EXTI_Line14) == SET)
    {
        
    }

}

  • 中断程序结束后,一定要再调用下清除中断标志位的函数,因为只要标志位为1,程序就会调到中断函数,不清除中断标志位,它就会一直申请中断,然后不断响应中断,程序就会卡死

void EXTI15_10_IRQHandler(void)
{
    if(EXTI_GetFlagStatus(EXTI_Line14) == SET)
    {
        EXTI_ClearFlag(EXTI_Line14);
    }

}

4.声明初始化函数

在.h文件里声明刚刚编写的传感器初始化函数,这样在别的文件里就能调用该函数了,中断函数不用声明

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第7张图片

5.main函数处理

声明红外传感器.h文件和调用初始化函数

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第8张图片

三、功能实现

1.传感器.c文件

定义一个变量“Count”,用于计数

uint16_t Count;

在中断函数里让Count++

void EXTI15_10_IRQHandler(void)
{
    if(EXTI_GetFlagStatus(EXTI_Line14) == SET)
    {
        Count ++;
        EXTI_ClearFlag(EXTI_Line14);
    }

}

写一个Get函数,返回Count值

uint16_t GetCount(void)
{
    return Count;
}

1.传感器.h文件

声明Get函数

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第9张图片

3.main.c文件

在OLED屏幕上显示计数,即“Count:0000X”

int main()
{
    OLED_Init();
    CountSensor_Init();
    OLED_ShowString(1,1,"Count:");//显示“Count”这个字符串
    
    while(1)
    {
        OLED_ShowNum(1,7,GetCount(),5);//显示计数
    }


}

最终效果

STM32学习笔记之EXTI应用实例:对射式红外传感器计次_第10张图片


总结

本节内容是基于EXTI外部中断内容来进行的实操,一些外设的初始化步骤基本都差不多,驱动写出来后,至于怎么让其计数就见仁见智了。

你可能感兴趣的:(STM32,stm32,学习,笔记)