当前位置: 首页 > backend >正文

GD32入门到实战22--红外NEC通信协议

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.xdnf.cn/news/19133.html

相关文章:

  • 超越传统SEO:用生成引擎优化(GEO)驱动下一轮增长
  • Tomcat 企业级运维实战系列(三):Tomcat 配置解析与集群化部署
  • UI前端大数据可视化实战策略:如何设计符合用户认知的数据可视化界面?
  • JUC并发编程10 - 内存(02) - volatile
  • vscode terminal远程连接linux服务器GUI图形界面
  • 鸿蒙NEXT布局全解析:从线性到瀑布流,构建自适应UI界面
  • 深入理解计算机端口:为什么通信需要端口?
  • 【读论文】质心重分配显微镜实现活样本超分辨成像
  • Qt中的QSS介绍
  • Time-MOE添加MLP分类头进行分类任务
  • 用户自定义字段(Custom Fields)设计方案,兼顾多语言、分组、校验、权限、查询性能、审计与多租户
  • 创维E910V10C_晶晨S905L2和S905L3芯片_线刷固件包
  • HDMI2.1 8K验证平台
  • 【拍摄学习记录】05-对焦、虚化、景深
  • 告别音色漂移!微软超长语音合成模型VibeVoice正式开源​
  • 数列寻方:等差数列和为完全平方数
  • MinIO社区版“背刺“之后:RustFS用Apache 2.0协议重构开源信任
  • Java接口和抽象类的区别,并举例说明
  • 【Spring Cloud Alibaba】前置知识(一)
  • LeetCode 01背包 494. 目标和
  • 2025_WSL2_Ubuntu20.04_C++20_concept 环境配置
  • AntSK知识库多格式导入技术深度解析:从文档到智能,一站式知识管理的技术奇迹
  • zyplayer-doc 开源知识库:部署与使用指南
  • 千年智造,一触即发 耐达讯自动化Profibus集线器如何让HMI触摸屏在工业4.0中“点石成金“?
  • 新人桌球笔记
  • Web前端入门:JavaScript 一个简单的 IndexedDB 数据库入门示例
  • 【开题答辩全过程】以 基于Vue Spring Boot的教师资格证考试助力系统设计与实现为例,包含答辩的问题和答案
  • QML Chart组件之坐标轴共有属性
  • AI人工智能系统搭建实战指南:常见陷阱与解决方案
  • 从零开始学习单片机17