【STM32F103ZET6——库函数】11.捕获红外信号

news2025/3/15 0:27:34

目录

红外原理

数据码

引导码

连发码

配置捕获引脚

使能引脚时钟

配置定时器

使能定时器时钟

配置输入捕获

中断优先级分组

配置定时器4中断

定时器中断使能

使能定时器

重写定时器中断服务函数

清空定时器中断标志位

例程

例程说明

main.h

main.c

HongWai.h

HongWai.c

红外原理

红外信号的组成:引导码、地址码、地址反码、键码、键反码、连发码(可有可无)

  • 红色:引导码

  • 橙色:地址码

  • 蓝色:地址反码

  • 绿色:键码

  • 白色:键反码

  • 灰色:连发码

数据码

  • 560us的低电平+560us的高电平=数据“0”

  • 560us的低电平+1690us的高电平=数据“1”

引导码

9ms的低电平+4.5ms的高电平=引导码

连发码

9ms的低电平+2.25ms的高电平=连发码

配置捕获引脚

红外接收继续自己搭建电路,红外接收头的输出引脚必须要接到芯片的时钟引脚上

  1. 配置引脚号

  2. 配置引脚速度

  3. 配置引脚的模式

  4. 引脚初始化

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//初始化引脚
GPIO_InitTypeDef GPIO;

//配置PB9引脚
GPIO.GPIO_Mode=GPIO_Mode_IPD;//下拉输入
GPIO.GPIO_Pin=GPIO_Pin_9;
GPIO_Init(GPIOB,&GPIO);//初始化PA0引脚

使能引脚时钟

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能PB时钟

配置定时器

根据对应的引脚定时器配置对应的定时器。

  1. 配置第一次时钟分频

  2. 配置计数模式

  3. 配置重载值

  4. 配置预分频系数

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

TIM_TimeBaseInitTypeDef DSQ_4;//定时器4

//定时器4配置
DSQ_4.TIM_ClockDivision=TIM_CKD_DIV1;//第一次时钟分频,不分频
DSQ_4.TIM_CounterMode=TIM_CounterMode_Up;//计数模式,向上计数模式
DSQ_4.TIM_Period=10000;//重载值,10ms溢出
DSQ_4.TIM_Prescaler=72-1;//预分频系数,不分频
TIM_TimeBaseInit(TIM4,&DSQ_4);

使能定时器时钟

void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能定时器4时钟

配置输入捕获

  1. 配置捕获通道

  2. 配置输入滤波器

  3. 配置捕获方式

  4. 配置输入/捕获预分频器

  5. 配置捕获/比较选择,映射关系?

void TIM_ICInit(TIM_TypeDef *TIMx,TIM_ICInitTypeDef *TIM_ICInitStruct) ;

TIM_ICInitTypeDef BuHuo4;//捕获4

//PB9 -> TIM4_CH4,输入捕获配置
BuHuo4.TIM_Channel=TIM_Channel_4;//通道4h
BuHuo4.TIM_ICFilter=0x03;//IC1F=0111 配置输入滤波器 8个事件后产生一个输出跳变
BuHuo4.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获
BuHuo4.TIM_ICPrescaler=TIM_ICPSC_DIV1;//输入/捕获1预分频器,无预分频器
BuHuo4.TIM_ICSelection=TIM_ICSelection_DirectTI;//捕获/比较1选择,IC1映射到TI1上
TIM_ICInit(TIM4,&BuHuo4);

中断优先级分组

/*
zu_bie:
	NVIC_PriorityGroup_0
	NVIC_PriorityGroup_1
	NVIC_PriorityGroup_2
	NVIC_PriorityGroup_3
	NVIC_PriorityGroup_4
*/
void NVIC_PriorityGroupConfig(zu_bie);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组

配置定时器4中断

  1. 配置中断源

  2. 配置抢占优先级

  3. 配置子优先级

  4. 定时器3中断源使能

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);//初始化中断

NVIC_InitTypeDef ZhongDuan4;//中断4

//定时器4中断配置
ZhongDuan4.NVIC_IRQChannel=TIM4_IRQn;//定时器4中断
ZhongDuan4.NVIC_IRQChannelCmd=ENABLE;
ZhongDuan4.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
ZhongDuan4.NVIC_IRQChannelSubPriority=1;//子优先级
NVIC_Init(&ZhongDuan4);

定时器中断使能

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

TIM_ITConfig(TIM4,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许更新中断 ,允许CC4IE捕获中断

使能定时器

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

TIM_Cmd(TIM4,ENABLE);//使能定时器4

重写定时器中断服务函数

        注意:中断服务函数的函数已经固定,重新定义相同名字的函数即可,在定义好的函数里写中断的操作,哪个串口发生中断就得重定义哪个串口中断的函数

void TIM4_IRQHandler(){//定时器4中断服务函数
    if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET){//获取定时器5溢出的中断标志位
        if(YinDaoMa_flag){//已经捕获到引导码
            if(DSQ_YiChu_CiShu<=13){//计算溢出次数
                DSQ_YiChu_CiShu++;
            }
            else{
                YinDaoMa_flag=0;//引导码清零,为下次捕获红外信号做准备
                BuHuo_flag=1;//记为成功捕获一次红外信号
            }
        }
    }
    if(TIM_GetITStatus(TIM4,TIM_IT_CC4)!=RESET){//发生捕获事件
        if(BuHuo_ShangShengYan_flag==0){//第一次捕获到上升沿
            TIM_OC4PolarityConfig(TIM4,TIM_OCPolarity_Low);//配置定时器4通道4的捕获极性,配置为下降沿捕获
            TIM_SetCounter(TIM4,0);//设置定时器4从0开始计数
            BuHuo_ShangShengYan_flag=1;//成功捕获到上升沿
        }
        else{//捕获到下降沿
            GaoDianPing_Time=TIM_GetCapture4(TIM4);//获取定时器4通道4的值,高电平的持续时间
            TIM_OC4PolarityConfig(TIM4,TIM_OCPolarity_High);//配置定时器4通道4的捕获极性,配置为上升沿捕获
            if(BuHuo_ShangShengYan_flag){//完成一次高电平捕获
                if(GaoDianPing_Time>4200&&GaoDianPing_Time<4700){//4500,接收到引导码
                    YinDaoMa_flag=1;
                }
                else if(YinDaoMa_flag){//接收到引导码后,进行对数据处理
                    if(GaoDianPing_Time>300&&GaoDianPing_Time<800){//560us,接收到数据0
                        data=data<<1;
                        data=data|0;
                    }
                    else if(GaoDianPing_Time>1400&&GaoDianPing_Time<1800){//1680us,接收到数据1
                        data=data<<1;
                        data=data|1;
                    }
                    else if(GaoDianPing_Time>2200&&GaoDianPing_Time<2600){//2500us,接收到连发码
                        YinDaoMa_flag=0;//引导码清零,为下次捕获红外信号做准备
                        BuHuo_flag=1;//记为成功捕获一次红外信号
                    }
                }
                BuHuo_ShangShengYan_flag=0;//清零,为下一次捕获上升沿做准备
            }
        }
    }
    TIM_ClearITPendingBit(TIM4,TIM_IT_CC4|TIM_IT_Update);//清除中断标志位
}

清空定时器中断标志位

void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

TIM_ClearITPendingBit(TIM4,TIM_IT_CC4|TIM_IT_Update);//清除中断标志位

例程

例程说明

捕获红外信号,并进行解码

main.h

#ifndef _MAIN_H_
#define _MAIN_H_

#include "stm32f10x.h"                  // Device header
#include <string.h>
#include <stdio.h>

#include "delay.h"
#include "usart.h"
#include "HongWai.h"

#endif

main.c


#include "main.h"

u8 BuHuo_flag=0;//捕获成功标志位,0:未捕获一次成功;1:捕获1次成功
u8 BuHuo_ShangShengYan_flag=0;//捕获上升沿标志位,0:未捕获到上升沿;1:捕获到上升沿
u8 DSQ_YiChu_CiShu=0;//定时器溢出次数
u16 GaoDianPing_Time=0;//高电平时间
u8 YinDaoMa_flag=0;//引导码标志位,0:没有接收到引导码;1:接收到引导码
u32 data=0;//红外数据

int main() {
    u8 DiZhiMa=0;//地址码
    u8 DiZhiMa_FanMa=0;//地址码反码
    u8 JianMa=0;//键码
    u8 JianMa_FanMa=0;//键码反码
    delay_init();
    HongWai_Init();
    uart_init(115200);
    printf("程序开始运行!!!\n");
    while(1){
        if(BuHuo_flag){//捕获一次成功
            DiZhiMa=(u8)(data>>24);
            DiZhiMa_FanMa=(u8)((data>>16)&0xff);
            JianMa=(u8)(data>>8);
            JianMa_FanMa=(u8)data;
            printf("data:%d  ",data);
            printf("地址码:%d  ",DiZhiMa);
            printf("地址码反码:%d  ",DiZhiMa_FanMa);
            printf("键码:%d  ",JianMa);
            printf("键码反码:%d\n",JianMa_FanMa);
            if(DiZhiMa==(u8)(~DiZhiMa_FanMa)){
                printf("地址码正确!地址码为:%d\n",DiZhiMa);
            }
            else{
                printf("地址码错误!\n");
            }
            if(JianMa==(u8)(~JianMa_FanMa)){
                printf("键码正确!键码为:%d\n",JianMa);
            }
            else{
                printf("键码错误!\n");
            }
            BuHuo_flag=0;//开启下一次捕获
            data=0;//红外数据清零
            BuHuo_ShangShengYan_flag=0;
            DSQ_YiChu_CiShu=0;
            YinDaoMa_flag=0;
        }
    }
}

void TIM4_IRQHandler(){//定时器4中断服务函数
    if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET){//获取定时器5溢出的中断标志位
        if(YinDaoMa_flag){//已经捕获到引导码
            if(DSQ_YiChu_CiShu<=13){//计算溢出次数
                DSQ_YiChu_CiShu++;
            }
            else{
                YinDaoMa_flag=0;//引导码清零,为下次捕获红外信号做准备
                BuHuo_flag=1;//记为成功捕获一次红外信号
            }
        }
    }
    if(TIM_GetITStatus(TIM4,TIM_IT_CC4)!=RESET){//发生捕获事件
        if(BuHuo_ShangShengYan_flag==0){//第一次捕获到上升沿
            TIM_OC4PolarityConfig(TIM4,TIM_OCPolarity_Low);//配置定时器4通道4的捕获极性,配置为下降沿捕获
            TIM_SetCounter(TIM4,0);//设置定时器4从0开始计数
            BuHuo_ShangShengYan_flag=1;//成功捕获到上升沿
        }
        else{//捕获到下降沿
            GaoDianPing_Time=TIM_GetCapture4(TIM4);//获取定时器4通道4的值,高电平的持续时间
            TIM_OC4PolarityConfig(TIM4,TIM_OCPolarity_High);//配置定时器4通道4的捕获极性,配置为上升沿捕获
            if(BuHuo_ShangShengYan_flag){//完成一次高电平捕获
                if(GaoDianPing_Time>4200&&GaoDianPing_Time<4700){//4500,接收到引导码
                    YinDaoMa_flag=1;
                }
                else if(YinDaoMa_flag){//接收到引导码后,进行对数据处理
                    if(GaoDianPing_Time>300&&GaoDianPing_Time<800){//560us,接收到数据0
                        data=data<<1;
                        data=data|0;
                    }
                    else if(GaoDianPing_Time>1400&&GaoDianPing_Time<1800){//1680us,接收到数据1
                        data=data<<1;
                        data=data|1;
                    }
                    else if(GaoDianPing_Time>2200&&GaoDianPing_Time<2600){//2500us,接收到连发码
                        YinDaoMa_flag=0;//引导码清零,为下次捕获红外信号做准备
                        BuHuo_flag=1;//记为成功捕获一次红外信号
                    }
                }
                BuHuo_ShangShengYan_flag=0;//清零,为下一次捕获上升沿做准备
            }
        }
    }
    TIM_ClearITPendingBit(TIM4,TIM_IT_CC4|TIM_IT_Update);//清除中断标志位
}

HongWai.h

#ifndef __HONGWAI_H_
#define __HONGWAI_H_

#include "stdio.h"
#include "sys.h"

void HongWai_Init();//红外初始化

#endif

HongWai.c

//PB9 -> TIM4_CH4

#include "HongWai.h"

void HongWai_Init(){
    TIM_TimeBaseInitTypeDef DSQ_4;//定时器4
    TIM_ICInitTypeDef BuHuo4;//捕获4
    NVIC_InitTypeDef ZhongDuan4;//中断4
    GPIO_InitTypeDef GPIO;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能定时器4时钟
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能PB时钟

    //定时器4配置
    DSQ_4.TIM_ClockDivision=TIM_CKD_DIV1;//第一次时钟分频,不分频
    DSQ_4.TIM_CounterMode=TIM_CounterMode_Up;//计数模式,向上计数模式
    DSQ_4.TIM_Period=10000;//重载值,10ms溢出
    DSQ_4.TIM_Prescaler=72-1;//预分频系数,不分频
    TIM_TimeBaseInit(TIM4,&DSQ_4);

    //PB9 -> TIM4_CH4,输入捕获配置
    BuHuo4.TIM_Channel=TIM_Channel_4;//通道4
    BuHuo4.TIM_ICFilter=0x03;//IC1F=0111 配置输入滤波器 8个事件后产生一个输出跳变
    BuHuo4.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获
    BuHuo4.TIM_ICPrescaler=TIM_ICPSC_DIV1;//输入/捕获1预分频器,无预分频器
    BuHuo4.TIM_ICSelection=TIM_ICSelection_DirectTI;//捕获/比较1选择,IC1映射到TI1上
    TIM_ICInit(TIM4,&BuHuo4);

    TIM_ITConfig(TIM4,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许更新中断 ,允许CC4IE捕获中断

    //定时器4中断配置
    ZhongDuan4.NVIC_IRQChannel=TIM4_IRQn;//定时器4中断
    ZhongDuan4.NVIC_IRQChannelCmd=ENABLE;
    ZhongDuan4.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
    ZhongDuan4.NVIC_IRQChannelSubPriority=1;//子优先级
    NVIC_Init(&ZhongDuan4);

    TIM_Cmd(TIM4,ENABLE);//使能定时器4

    //配置PB9引脚
    GPIO.GPIO_Mode=GPIO_Mode_IPD;//下拉输入
    GPIO.GPIO_Pin=GPIO_Pin_9;
    GPIO_Init(GPIOB,&GPIO);//初始化PA0引脚
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2311275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

unity调用本地部署deepseek全流程

unity调用本地部署deepseek全流程 deepseek本地部署 安装Ollama 搜索并打开Ollama官网[Ollama](https://ollama.com/download) 点击Download下载对应版本 下载后点击直接安装 安装deepseek大语言模型 官网选择Models 选择deepseek-r1&#xff0c;选择对应的模型&#xff0…

AI绘画软件Stable Diffusion详解教程(6):文生图、提示词细说与绘图案例

文生图即以文字描述来生成图像&#xff0c;这是目前所有AI绘画软件的基本功能之一。要想画一副好的图片&#xff0c;除了选择好的模型&#xff0c;在文生图中&#xff0c;提示词特别关键。 一、什么是提示词&#xff08;Prompt&#xff09; 提示词又称创意、关键词、咒语、ca…

SAP监控体系和机制

SAP监控体系 SAP监控体系是一个多层次、多维度的综合系统&#xff0c;旨在确保SAP系统的性能、可用性、安全性和稳定性。以下是SAP监控体系的主要组成部分&#xff1a; 1. 技术监控&#xff08;Technical Monitoring&#xff09; 目标&#xff1a;监控SAP系统的基础设施和技术…

SLAM评估工具安装及使用EVO(Ubuntu20.04安装evo)--缺少 onnx 库还有Pandas 版本不兼容解决

介绍一下我的是ubuntu20.04.机载电脑是orinnx&#xff0c;通过源码烧写的系统。 首先打开终端&#xff0c;输入 pip install evo --upgrade --no-binary evo 安装过程中出现如下问题 缺少 onnx 库还有Pandas 版本不兼容&#xff0c; ONNX&#xff08;Open Neural Network E…

【YashanDB认证】yashandb23.3.1 个人版单机部署安装实践

YCA报名链接如下: YashanDB|崖山数据库系统YashanDB学习中心-YCA认证详情 目前免费 主要参考文档&#xff1a; 单机&#xff08;主备&#xff09;部署 | YashanDB Doc 另外还参考摩天轮文章&#xff1a; YashanDB 23.2.9.101 企业版安装步骤抢先看&#xff01; - 墨天轮 …

ProfibusDP主站转ModbusTCP网关如何进行数据互换

ProfibusDP主站转ModbusTCP网关如何进行数据互换 在现代工业自动化领域&#xff0c;通信协议的多样性和复杂性不断增加。Profibus DP作为一种经典的现场总线标准&#xff0c;广泛应用于工业控制网络中&#xff1b;而Modbus TCP作为基于以太网的通信协议&#xff0c;因其简单易…

正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-2.1 uboot简介

前言&#xff1a; 本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用&#xff1a; …

Qt 实现绘图板(支持橡皮擦与 Ctrl+Z 撤销功能)[特殊字符]

作业&#xff1a; 1&#xff1a;实现绘图的时候&#xff0c;颜色的随时调整 2&#xff1a;追加橡皮擦功能 3&#xff1a;配合键盘事件&#xff0c;实现功能 当键盘按 ctrlz的时候&#xff0c;撤销最后一次绘图 头文件.h #ifndef WIDGET_H #define WIDGET_H#include <QWidge…

基于STM32的智能家居蓝牙系统(论文+源码)

1总体方案设计 本次基于STM32的智能家居蓝牙系统&#xff0c;其系统总体架构如图2.1所示&#xff0c;采用STM32f103单片机作为控制器&#xff0c;通过DHT11传感器实现温湿度检测&#xff0c;MQ-2烟雾传感器实现烟雾检测&#xff0c;光敏电阻实现光照检测&#xff0c;同时将数据…

el-table一格两行;概率;find

样式&#xff1a; 根据概率表头关键代码&#xff1a;rateRanges&#xff1b; scope.row.targetHitTable.find((target:any) > target.targetHitRate > range.min && target.targetHitRate < range.max)!.targetHitNum &#xff08;1&#xff09;!.是TypeScri…

前端跨域设置 withCredentials: true

在做登录认证的时候&#xff0c;会出现请求未登录的情况&#xff0c;查看请求头的时候发现并没有把登录时的cookie设置到第二次的请求头里面。查看资料才知道跨域请求要想带上cookie&#xff0c;必须要在ajax请求里加上 withCredentials: true 再次访问发现请求头可以携带cook…

私有云基础架构与运维(一)

私有云基础架构与运维&#xff08;OpenStackopenEuler版&#xff09; 项目一.OpenStack 云计算基础架构平台概述 任务1.1 安装部署虚拟化环境 通过安装 openEuler-22.09 操作系统来熟悉虚拟机的安装&#xff0c;在操作过程中熟悉计算机虚 拟化资源的分配管理。 1.1.1 VMware…

PySide(PyQT)的视图(QGraphicsView)范例(一) 基本框架

最近学习了视图&#xff08;QGraphicsView&#xff09;的知识&#xff0c;总结一下&#xff0c;做一个demo以备忘。在demo中演示了常用的设置方法和信号槽传递机制。 QT的视图&#xff08;QGraphicsView&#xff09;体系是建立在场景&#xff08;QGraphicsScene&#xff09;基础…

深入理解seata使用和源码分析

一、数据库事务ACID特性 基础概念:事务ACID A(Atomic):原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失 败的情况。C(Consistency):一致性,在事务执行前后,数据库的一致性约束没有被破坏。比如:张三向李四转100元, 转账前和…

centos8更换阿里云yum源

1.centos8更换为阿里云yum源 2.更换阿里云Yum-centos8源 mv /etc/yum.repos.d/CentOS-Stream-BaseOS.repo /etc/yum.repos.d/CentOS-Stream-BaseOS.repo.backupcurl -o /etc/yum.repos.d/CentOS-Stream-BaseOS.repo https://mirrors.aliyun.com/repo/Centos-8.repowget -O /et…

单粒子翻转对FPGA的影响及解决方法

1 单粒子翻转对FPGA 的影响 对于在轨的空间应用而言,需要考虑外太空辐射对电子元器件带来的影响,包括单粒子翻转(Single Event Upset,SEU)、多粒子翻转(Multiple Bit Upset,MBU)、单粒子瞬态效应(Single Event Transient,SET)、单粒子功能中断(SingleEvent Functi…

基于Python Django的人脸识别上课考勤系统(附源码,部署)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Oracle数据库监听学习

官方文档&#xff1a; Net Services Administrators Guide Net Services Reference 一、动态注册 1.实例启动后&#xff0c;LREG 进程每分钟自动将服务名&#xff08;service_name&#xff09;注册到监听器中 也可以通过 alter system register 命令实现立刻注册。&#x…

Vue Hooks 深度解析:从原理到实践

Vue Hooks 深度解析&#xff1a;从原理到实践 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff01;点我试试&#xff01;&#xff01; 文章目录 Vue Hooks 深度解析&#xff1a;从原理到实践一、背景…

5c/c++内存管理

1. C/C内存分布 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)malloc(sizeof(int) * 4);i…