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.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…