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

您所在的位置:网站首页 如何关闭红外线遮挡 STM32学习笔记之EXTI应用实例:对射式红外传感器计次

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

2024-07-09 12:22| 来源: 网络整理| 查看: 265

系列文章目录

第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)

2.硬件电路

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

GND:接电源负极

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

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

二、软件驱动 1.模块化编程

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

2.初始化函数

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

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:根据数据手册得知有三种配置方式,这里配置成上拉输入,即默认为高电平输入方式

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_Line14EXTI_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

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 ”结尾的字符串就是中断函数的名字

找到“  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文件里声明刚刚编写的传感器初始化函数,这样在别的文件里就能调用该函数了,中断函数不用声明

5.main函数处理

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

三、功能实现 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函数

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);//显示计数     }

}

最终效果

总结

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3