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();}
}