5.2 对射式红外传感器旋转编码器计次

news/2024/7/7 21:44:04
  1. 对射式红外传感器

1.1 接线图

VCC GND分别接电源的正负极

DO数字输出端,随意选择一个GPIO口

1.2 硬件原理

当挡光片或者编码盘在对射式红外传感器中间经过时,DO就会输出电平变化信号,电平跳变信号触发STM32 PB14号口中断,在中断函数中执行变量++程序,并在主循环里调用OLED中显示变量。

1.3 设计思路

  • 本次设计采用模块化编程,分为CountSensor.c、CountSensor.h、main.c三部分。

  • 先进行初始化

EXTI(中断)配置

1. 第⼀步,配置RCC,把所涉及到的外设时钟都打开 (GPIOB,AFIO(NVIC,EXTI无需打开)) 2. 第⼆步,配置GPIO,选择端口为输⼊模式 3. 第三步,配置AFIO,选择使⽤的⼀路GPIO,连接到EXTI 4. 第四步,配置EXTI,选择边沿触发⽅式,选择触发响应⽅式 5. 第五步,配置NVIC,给中断选择⼀个合适的优先级

最后通过NVIC,外部中断信号进入CPU,CPU收到中断信号,跳转到中断函数里执行中断程序。

EXTI和NVIC时钟默认是打开的,NVIC是内核的外设,内核的外设都不需要开启时钟,RCC 管的都是内核外的外设

1.4 知识储备 AFIO

  • 复位AFIO外设

void GPIO_AFIODeInit(void);
  • 锁定GPIO配置函数

锁定引脚的配置,防⽌意外更改

void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
  • 配置AFIO的事件输出功能函数

void GPIO_EventOutputConfig(uint8_t GPIO_PortSource,uint8_tGPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
  • 引脚重映射函数

void GPIO_PinRemapConfig(uint32_t GPIO_Remap,FunctionalStateNewState);
  • 配置AFIO的数据选择器

通过配置AFIO数据选择器,选择中断引脚。

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource,uint8_tGPIO_PinSource);
  • 恢复上电默认的状态函数

void EXTI_DeInit(void);

1.5 知识储备EXTI

  • 清除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);

下面四个是库函数的模板函数

在主程序里查看和清除标志位用下面两个函数

  • 获取指定的标志位是否被置1

FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
  • 对置1的标志位进⾏清除函数

void EXTI_ClearFlag(uint32_t EXTI_Line);

在中断函数里查看和清除标志位用下面两个

  • 在中断函数中获取标志位函数

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
  • 清除中断挂起标志位函数

void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

1.6 知识储备NVIC

  • 中断分组函数

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
  • 根据结构体⾥⾯的参数初始化NVIC函数

void NVIC_Init(NVIC_InitTypedef* NVIC_InitStruct);
  • 设置中断向量表函数

NVIC_SetVectorTable函数的功能是设置向量表的位置和偏移。其中输⼊参数中,对于32位 的OFFSET向量表基地址的偏移量对于FLASH,参数值必须⾼于0x08000100,对于RAM必 须⾼于0X100

void NVIC_SetVectorTable(uint8_t NVIC_VectTab,uint32_t Offset);
  • 系统低功耗配置函数

void NVIC_SystemLPConfig(uint8_t LowPowerMode,FunctionalStateNewState)

注意:中断函数要简短快速,不要在中断中执⾏Delay

1.7 程序设计

CountSensor.c

#include "stm32f10x.h"                  // Device header

uint16_t CountSensor_Count;

void CountSensor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//开启AFIO的时钟
    //配置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);//配置AFIO外部中断引脚选择
    //配置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_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体
    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)//中断标志位判断是否为1
    {
        /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
        {
            CountSensor_Count ++;//统计中断返回次数
        }
        EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
    }
}

CountSensor.h

#ifndef __COUNT_SENSOR_H
#define __COUNT_SENSOR_H

void CountSensor_Init(void);
uint16_t CountSensor_Get(void);

#endif

main.c

#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:");/1行1列显示Count:
    
    while (1)
    {
        OLED_ShowNum(1, 7, CountSensor_Get(), 5);//一行七列显示返回次数,长度为5
    }
}

2. 旋转编码器计次

2.1 接线图

VCC GND接正负极,A,B相输出引脚,接到STM32的PB0和PB1引脚。

2.2 设计思路

本设计采用模块化编程,分为Encoder.c、Encoder.h、mian.c三部分。

2.3 程序设计

Encoder.c

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

void CountSensor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//开启AFIO的时钟
    //配置GPIO
    GPIO_InitTypeDef GPIO_InitStructure;//定义初始化结构体
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1;//开启引脚
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置响应速度
    GPIO_Init(GPIOB, &GPIO_InitStructure);//配置参数
    //配置AFIO
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//配置AFIO外部中断引脚选择
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1); 
    //配置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_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//设置中断通道
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
    NVIC_Init(&NVIC_InitStructure);//写入参数

    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//设置中断通道
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//响应优先级
    NVIC_Init(&NVIC_InitStructure);//写入参数
}   

int16_t Encoder_Get(void)
{
    int16_t Temp;//定义临时变量,方便Count清零
    Temp = Encoder_Count;
    Encoder_Count = 0;
    return Temp;
}

void EXTI0_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line14) == SET)//中断标志位判断是否为1
    {
        /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)//读取输入高低电平
        {
            if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
            {
                Encoder_Count --;
            }
        }
        EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
    }
}

void EXTI1_IRQHandler(void)//线路1中断函数
{
    if (EXTI_GetITStatus(EXTI_Line14) == SET)//中断标志位判断是否为1
    {
        /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)//读取输⼊⾼低电平
        {
            if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
            {
                Encoder_Count ++;
            }
        }
        EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
    }
}

Encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int16_t Encoder_Get(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"

int16_t Num;

int main(void)
{
    OLED_Init();
    Encoder_Init();
    
    OLED_ShowString(1, 1, "Num:");
    
    while (1)
    {
        Num += Encoder_Get();
        OLED_ShowSignedNum(1, 5, Num, 5);
    }
}


http://lihuaxi.xjx100.cn/news/978125.html

相关文章

mysql死锁 gap next key 加锁分析

这个案例的原文参见: mysql死锁场景汇总整理_死锁业务场景_秃了也弱了。的博客-CSDN博客 那么我们就来分析下整个加锁过程吧。 关键词: next-key & gap 锁 & 插入意向锁 & 二级普通索引 前提:RR级别 CREATE TABLE t_user ( id…

【蓝桥杯集训·每日一题】AcWing 3555. 二叉树

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴最近公共祖先一、题目 1、原题链接 3555. 二叉树 2、题目描述 给定一个 n 个结点(编号 1∼n)构成的二叉树,其根结点为 1 号点。 进行 m…

基于ChatRWKV智能问答和内容创作

ChatRWKV是对标ChatGPT的开源项目,希望做大规模语言模型的Stable Diffusion,测试很一段时间确实很像ChatGPT,从使用方法和内容结果上都很相似,但是还有一些差异。 文章目录 准备工作环境配置创建虚拟环境激活虚拟环境pip安装匹配版本ChatRWKV 使用模型替换常用参数设置使用…

【springmvc】执行流程

SpringMVC执行流程 原理图 1、SpringMVC常用组件 DispatcherServlet:前端控制器,不需要工程师开发,由框架提供 作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求 HandlerMa…

< JavaScript小技巧:Array构造函数妙用 >

文章目录👉 Array构造函数 - 基本概念👉 Array函数技巧用法1. Array.of()2. Array.from()3. Array.reduce()4. (Array | String).includes()5. Array.at()6. Array.flat()7. Array.findIndex()📃 参考文献往期内容 💨今天这篇文章…

项目实战典型案例23——-注册上nacos上的部分服务总是出现频繁掉线的情况

注册上nacos上的部分服务总是出现频繁掉线的情况一:背景介绍二:思路&方案解决问题过程涉及到的知识nacos服务注册和服务发现一:背景介绍 spring cloud项目通过nacos作为服务中心和配置中心,出现的问题是其中几个服务总是出现…

基于Three.js和MindAR实现的网页端WebAR人脸识别追踪功能的京剧换脸Demo(含源码)

前言 近段时间一直在玩MindAR的功能,之前一直在弄图片识别追踪的功能,发现其强大的功能还有脸部识别和追踪的功能,就基于其面部网格的例子修改了一个国粹京剧的换脸程序。如果你不了解MindAR的环境配置可以先参考这篇文章:基于Mi…

[nodejs开发] typescript引入js模块或文件

首先更改tsconfig.json 中的compilerOptions属性:"moduleResolution": "Node"假设有一个abc.js其内容如下:var Circle (function () {function Circle() {}Circle.prototype.draw function () {console.log("Cirlce is drawn…