ir_drv.c

红外传输协议地位在前,所以我们可以这样保存数据到数组

假使接收到1就>>1再|0x80,如果接收到0就>>1

新建红外驱动层代码ir_drv.c

#include <stdio.h>  
#include "gd32f30x.h"
#include <stdbool.h>  static void GpioInit(void) 
{rcu_periph_clock_enable(RCU_GPIOC);gpio_init(GPIOC,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_6);
}static void TimerInit()
{timer_parameter_struct timerInitPara;timer_struct_para_init(&timerInitPara);//给定时器结构体赋初值/*使能定时器时钟*/rcu_periph_clock_enable(RCU_TIMER7);/*复位定时器*/timer_deinit(TIMER7);/*设置预分频值*/timerInitPara.prescaler = 120 - 1;//时钟频率为1Mhz,周期为1us/*设置自动重装载值*/timerInitPara.period = 65535;/*初始化定时器*/timer_init(TIMER7,&timerInitPara);//给定时器结构体赋初值timer_ic_parameter_struct icInitPara;timer_channel_input_struct_para_init(&icInitPara);/*设置上升沿/下降沿捕获*/icInitPara.icpolarity = TIMER_IC_POLARITY_FALLING;/*设置输入通道*/icInitPara.icselection = TIMER_IC_SELECTION_DIRECTTI;timer_input_capture_config(TIMER7,TIMER_CH_0,&icInitPara);/*使能定时器的捕获中断*/timer_interrupt_flag_clear(TIMER7 ,TIMER_INT_FLAG_CH0);//清除中断标志位timer_interrupt_enable(TIMER7,TIMER_INT_CH0);/*使能定时器中断优先级*/nvic_irq_enable(TIMER7_Channel_IRQn, 0, 0);/*使能定时器*/timer_enable(TIMER7);
}#define TICK_HEAD_MAX   20000//引导码的最长时间
#define TICK_HEAD_MIN   10000//引导码的最短时间
#define TICK_0_MAX      1800//0的最长时间
#define TICK_0_MIN      500 //0的最短时间
#define TICK_1_MAX      3000//1的最长时间
#define TICK_1_MIN      1800//1的最短时间
static uint8_t g_irCode[4]; //存放数组
static bool g_irCodeFlag = false; //解析到完整的数据
static void ParseIrFrame(uint32_t tickNum)
{static bool s_headFlag = false;//表示是否收到static uint8_t s_index = 0;//数组索引值if(tickNum > TICK_HEAD_MIN && tickNum < TICK_HEAD_MAX)//引导码时间是否正常{//正常s_headFlag = true;return;}if(!s_headFlag)//如果引导码不正常{//说明没有解析到引导码return;}if(tickNum > TICK_1_MIN && tickNum < TICK_1_MAX)//1{//s_index / 8:s_index为8位数据,整个数据长为32位,//s_index0-7存到g_irCode[0];s_index8-15存到g_irCode[1]....g_irCode[s_index / 8] >>= 1;g_irCode[s_index / 8] |= 0x80;s_index++;}if(tickNum > TICK_0_MIN && tickNum < TICK_0_MAX)//0{g_irCode[s_index / 8] >>= 1;s_index++;}if(s_index == 32){   //if(g_irCode[2] == (uint8_t)~g_irCode[3])//校验数据反码,两种方法一样if((g_irCode[2] & g_irCode[3]) == 0)//按位与{//如果相等g_irCodeFlag = true;}else{g_irCodeFlag = false;}            s_headFlag = false;//清除接收到标志s_index = 0;//数组索引清零}
}/**
***********************************************************
* @brief 获取红外码值
* @param  code,输出,按键码值
* @return 返回是否成功获取按键码值
***********************************************************
*///*code:
bool GetIrCode(uint8_t *code)
{if(!g_irCodeFlag)//如果没有解析到完整数据{return false;}*code = g_irCode[2];//把数据取到指向的地址g_irCodeFlag = false;//把解析完成标志位清零return true;
}void TIMER7_Channel_IRQHandler()
{   static uint32_t icValue;//1 = 1usif(timer_interrupt_flag_get(TIMER7 , TIMER_INT_FLAG_CH0) == SET)//判断是否产生中断{timer_interrupt_flag_clear(TIMER7 , TIMER_INT_FLAG_CH0);//清除中断标志位icValue = timer_channel_capture_value_register_read(TIMER7, TIMER_CH_0) + 1;//读取计数值timer_counter_value_config(TIMER7 , 0);//计数器清零ParseIrFrame(icValue);}
}/**
***********************************************************
* @brief 红外接收硬件初始化函数
* @param 
* @return 
***********************************************************
*/
void IrDrvInit()
{GpioInit();TimerInit();
}

ir_drv.h

#ifndef _IR_DRV_H_
#define _IR_DRV_H_#include <stdint.h>
#include <stdbool.h>#define KEY1_CODE   0X45
#define KEY2_CODE   0X46/**
***********************************************************
* @brief 红外接收硬件初始化函数
* @param 
* @return 
***********************************************************
*/
void IrDrvInit(void);/**
***********************************************************
* @brief 获取遥控按键码值
* @param code,输出,按键码值
* @return 返回是否成功获取到按键码值
***********************************************************
*/
bool GetIrCode(uint8_t *code);#endif

hmi_app.c

#include <stdint.h>
#include "led_drv.h"
#include "ir_drv.h"
#include <stdio.h>
/**
***********************************************************
* @brief 人机交互任务处理函数
* @param 
* @return 
***********************************************************
*/
void HmiTask(void)
{uint8_t keyVal;if(!GetIrCode(&keyVal))//如果没有获取到码值{return;}printf("ir keyVal is 0x%x.\n",keyVal);switch (keyVal){case KEY1_CODE:TurnOnLed(LED1);break;case KEY2_CODE:TurnOffLed(LED1);break;default:break;}
}

main.c

#include <stdint.h>
#include <stdio.h>
#include "led_drv.h"
#include "key_drv.h"
#include "systick.h"
#include "usart_drv.h"
#include "delay.h"
#include "usb2com_app.h"
#include "hmi_app.h"
#include "ir_drv.h"typedef struct
{uint8_t run;                // 调度标志,1:调度,0:挂起uint16_t timCount;          // 时间片计数值uint16_t timRload;          // 时间片重载值void (*pTaskFuncCb)(void);  // 函数指针变量,用来保存业务功能模块函数地址
} TaskComps_t;/*任务调度结构体*/static TaskComps_t g_taskComps[] =  /*任务调度结构体数组,存放各个业务功能模块调度参数*/
{/*填入各个业务功能模块*/{0, 5,   5,   HmiTask},{0, 200, 200, usartTask},/* 添加业务功能模块 */
};#define TASK_NUM_MAX   (sizeof(g_taskComps) / sizeof(g_taskComps[0]))
/*用宏定义计算结构体数组的个数*///sizeof(g_taskComps):计算整个数组 g_taskComps 的大小(以字节为单位)。
//sizeof(g_taskComps[0]):计算数组中单个元素的大小(以字节为单位)。
//通过整个数组的大小除以单个元素的大小,得到数组中元素的数量/*
******************************************
* @brief 任务调度函数(判断所有业务模块的标志位)
* @param 
* @return
********************************************
*/
static void TaskHandler(void)
{for (uint8_t i = 0; i < TASK_NUM_MAX; i++){if (g_taskComps[i].run)                  // 判断时间片标志{g_taskComps[i].run = 0;              // 标志清零g_taskComps[i].pTaskFuncCb();        // 执行调度业务功能模块}}
}/*
******************************************
* @brief 时间片递减函数 1ms-1时间片
* @param 
* @return
********************************************
*/
static void TaskScheduleCb(void)
{for (uint8_t i = 0; i < TASK_NUM_MAX; i++){if (g_taskComps[i].timCount){g_taskComps[i].timCount--;if (g_taskComps[i].timCount == 0){g_taskComps[i].run = 1;g_taskComps[i].timCount = g_taskComps[i].timRload;}}}
}static void DrvInit(void)
{SystickInit();LedDrvInit();DelayInit();UsartDrv_Init();IrDrvInit();
}
static void AppInit(void)
{TaskScheduleCbReg(TaskScheduleCb);
}int main(void)
{	DrvInit();AppInit();while (1){TaskHandler();}
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zkML-JOLT——更快的ZK隐私机器学习:Sumcheck +Lookup

1. 引言 ICME团队开源的zkML项目&#xff1a; https://github.com/ICME-Lab/jolt-atlas&#xff08;Rust&#xff09; zkML-JOLT&#xff08;JOLT ‘Atlas’&#xff09;构建在a16z Crypto团队的JOLT研究和实现基础上&#xff0c;其性能比其他zkML项目快了3到7倍。 a16z Cr…

【大模型记忆-Mem0详解-2】系统架构

概述 Mem0 实现了双架构系统&#xff0c;通过两种主要部署模型为 AI 应用提供智能内存能力&#xff1a; 托管平台 &#xff1a;通过 MemoryClient 和 AsyncMemoryClient 类访问的托管服务开源 &#xff1a;以 Memory 类为中心的自托管组件&#xff0c;具有可插拔提供程序 此架构…

[Java]PTA:jmu-Java-01入门-取数字浮点数

本题目要求读入若干以回车结束的字符串表示的整数或者浮点数&#xff0c;然后将每个数中的所有数字全部加总求和。输入格式:每行一个整数或者浮点数。保证在浮点数范围内。输出格式:整数或者浮点数中的数字之和。题目保证和在整型范围内。输入样例:-123.01 234输出样例:7 9代码…

FFmpeg音视频处理解决方案

核心组件&#xff1a; ffmpeg&#xff1a;主要的命令行工具&#xff0c;用于转码、转换格式等 ffprobe&#xff1a;用于分析多媒体文件信息的工具 ffplay&#xff1a;简单的媒体播放器 主要功能&#xff1a; ✅ 格式转换&#xff08;转码&#xff09; ✅ 视频裁剪、合并 ✅ 调整…

机器学习回顾——决策树详解

决策树基础概念与应用详解1. 决策树基础概念1.1 什么是决策树决策树是一种树形结构的预测模型&#xff0c;其核心思想是通过一系列规则对数据进行递归划分。它模拟人类决策过程&#xff0c;广泛应用于分类和回归任务。具体结构包括&#xff1a;内部节点&#xff1a;表示对某个特…

Linux开发必备:yum/vim/gcc/make全攻略

目录 1.学习yum、apt⼯具&#xff0c;进⾏软件安装 1-1 什么是软件包 1-2 yum/apt具体操作 2. 编辑器Vim 2-1 Linux编辑器-vim的引入 2-2 vim的基本概念 2-3 vim的基本操作 2-4 vim正常模式命令集 2-5 vim末⾏模式命令集 3. 编译器gcc/g 3-1 背景知识 3-2 gcc编译选…

【Linux系统】万字解析,进程间的信号

前言&#xff1a; 上文我们讲到了&#xff0c;进程间通信的命名管道与共享内存&#xff1a;【Linux系统】命名管道与共享内存-CSDN博客​​​​​​ 本文我们来讲一讲&#xff0c;进程的信号问题 点个关注&#xff01; 信号概念 信号是OS发送给进程的异步机制&#xff01;所谓异…

AI时代SEO关键词实战解析

内容概要 随着人工智能技术深度融入搜索引擎的运行机制&#xff0c;传统的SEO关键词研究方法正经历着根本性的变革。本文聚焦于AI时代背景下&#xff0c;如何利用智能化的策略精准定位目标用户&#xff0c;实现搜索可见度的实质性跃升。我们将深入探讨AI技术如何革新关键词研究…

Spring Boot + Spring MVC 项目结构

下面一个既能返回 JSP 页面&#xff0c;又能提供 JSON API 的 Spring Boot Spring MVC 项目结构&#xff0c;这样你就能同时用到 Controller 和 RestController 的优势。 &#x1f3d7; 项目结构 springboot-mvc-mixed/ ├── src/main/java/com/example/demo/ │ ├── …

通俗易懂的讲解下Ceph的存储原理

Ceph存储原理解析 要理解 Ceph 的存储原理&#xff0c;我们可以用一个 “分布式仓库” 的比喻来拆解 —— 把 Ceph 想象成一个由多个 “仓库管理员”&#xff08;硬件节点&#xff09;共同打理的大型仓库&#xff0c;能高效存储、管理海量货物&#xff08;数据&#xff09;&…

软件测试小结(1)

一、什么是测试&#xff1f;1.1 生活中常见的测试例如去商场买衣服&#xff1a;①、选择一件符合审美的衣服 -> 外观测试&#xff1b;②、穿上身上试试是否合身 -> 试穿测试&#xff1b;③、 看看衣服的材料是否纯棉 -> 材料测试&#xff1b;④、 询问衣服的价格 ->…

Python未来3-5年技术发展趋势分析:从AI到Web的全方位演进

Python作为全球最流行的编程语言之一&#xff0c;在开发者社区中占据核心地位。其简洁语法、丰富库生态和跨领域适用性&#xff0c;使其在AI、Web开发、数据科学等领域持续领先。本文基于当前技术演进趋势&#xff08;如2023-2024年的开源项目、社区讨论和行业报告&#xff09;…

【ComfyUI】SDXL Turbo一步完成高速高效的图像生成

今天演示的案例是一个基于 ComfyUI 与 Stable Diffusion XL Turbo 的图生图工作流。整体流程通过加载轻量化的 Turbo 版本模型&#xff0c;在文本编码与调度器的配合下&#xff0c;以极快的推理速度完成从提示词到高质量图像的生成。 配合演示图可以直观感受到&#xff0c;简洁…

基于 GPT-OSS 的在线编程课 AI 助教追问式对话 API 开发全记录

本文记录了如何在 3 天内使用 GPT-OSS 开源权重搭建一个 在线编程课 AI 助教追问式对话 API&#xff0c;从需求分析、数据准备到微调与部署全流程实战。 1️⃣ 需求与指标 回答准确率 ≥ 95%响应延迟 < 1 秒支持多学生并发提问 2️⃣ 数据准备 收集课程问答对清理无效数据…

YOLO v11 目标检测+关键点检测 实战记录

流水账记录一下yolo目标检测 1.搭建pytorch 不做解释 看以往博客或网上搜都行 2.下载yolo源码 &#xff1a; https://github.com/ultralytics/ultralytics 3.样本标注工具&#xff1a;labelme 自己下载 4.准备数据集 4.1 新建一个放置数据集的路径4.2 构建训练集和测试集 运行以…

uniApp 混合开发全指南:原生与跨端的协同方案

uniApp 作为跨端框架&#xff0c;虽能覆盖多数场景&#xff0c;但在需要调用原生能力&#xff08;如蓝牙、传感器&#xff09;、集成第三方原生 SDK&#xff08;如支付、地图&#xff09; 或在现有原生 App 中嵌入 uniApp 页面时&#xff0c;需采用「混合开发」模式。本文将系统…

【大模型】使用MLC-LLM转换和部署Qwen2.5 0.5B模型

目录 ■准备工作 下载模型 安装依赖 安装基础依赖 安装mlc-llm ■权重转换 ■生成配置文件 ■模型编译 GPU版本编译 CPU版本编译 ■启动服务 启动GPU服务 启动CPU服务 ■服务测试 ■扩展 优化量化版本(可选,节省内存) INT4量化版本 调整窗口大小以节省内存…

云计算学习100天-第43天-cobbler

目录 Cobbler 基本概念 命令 搭建cobbler 网络架构 Cobbler 基本概念 Cobbler是一款快速的网络系统部署工具&#xff0c;比PXE配置简单 集中管理所需服务&#xff08;DHCP、DNS、TFTP、WEB&#xff09; 内部集成了一个镜像版本仓库 内部集成了一个ks应答文件仓库 提供…

接口测试:如何定位BUG的产生原因

1小时postman接口测试从入门到精通教程我们从在日常功能测试过程中对UI的每一次操作说白了就是对一个或者多个接口的一次调用&#xff0c;接口的返回的内容(移动端一般为json)经过前端代码的处理最终展示在页面上。http接口是离我们最近的一层接口&#xff0c;web端和移动端所展…

GPIO的8种工作方式

GPIO的8种工作方式&#xff1a;一、4 种输入模式1.1 Floating Input 浮空输入1.2 Pull-up Input 上拉输入1.3 Pull-down Input 下拉输入1.4 Analog Input 模拟输入二、4种输出模式2.1 General Push-Pull Output 推挽输出2.2 General Open-Drain Output 开漏输出2.3…