C51微控制器——紅外遙控 驅動程式

Mr-Loser發表於2020-10-20


本文為學習HC6800-EM3 V2.2開發板的學習筆記彙總,本文所用 紅外接收頭的引腳封裝如圖下:

引腳封裝

驅動函式封裝

宣告:請自行根據晶振編寫相匹配的延時函式

IrReceive.h檔案

#ifndef __IRRECEIVE_H__
#define __IRRECEIVE_H__

#include "delay.h"//請自行根據晶振編寫相匹配的延時函式;

typedef struct{
	uchar usercode;//使用者碼
	uchar cmd;//操作碼
	uchar ok;//完成標誌位
	uchar irtime; //時間控制
	uint  count_repeat;//重複碼計數器
	u32 receive;//資料快取
}ir_value_t;

extern ir_value_t IrValue;//結構體宣告

void irReceiveInit(void);//初始化
void IrValueParse(u32 recv);//資料處理函式

#endif

IrReceive.c檔案

紅外接收頭的out引腳接在微控制器的P3.2口,以外部中斷0下降沿方式觸發

#include "IrReceive.h"

void irReceiveInit(void)//初始化
{
  TMOD=0x02;//定時器0工作方式2,TH0是重灌值,TL0是初值
  TH0=0; //過載值
  TL0=0; //初始化值
  ET0=1;    //開中斷
  TR0=1;    
	
	IT0 = 1;   //指定外部中斷0下降沿觸發,INT0 (P3.2)
	EX0 = 1;   //使能外部中斷
	EA = 1;    //開總中斷
}

void IrValueParse(u32 recv)//資料處理函式
{
	uchar temp1;
	uchar temp2;
	temp1=recv;
	temp2=recv>>8;
	IrValue.usercode=temp1;
	if(temp1!=(uchar)(~temp2))
	{
		IrValue.ok=0;
		return;
	}
	temp1=recv>>16;
	temp2=recv>>24;
	IrValue.cmd=temp1;
	if(temp1!=(uchar)(~temp2))
	{
		IrValue.ok=0;
		return;
	}
	IrValue.ok=1;
}

ir_value_t IrValue;

void timer0_isr(void) interrupt 1 //定時器0中斷服務函式
{
	IrValue.irtime++;
}

void ir_ex0_interrupt() interrupt 0 //外部中斷0 下降沿觸發
{   
		static bit flag_start=0;
		static uchar IrCountBit=0;     //位計數器
		if(IrValue.irtime<60&&IrValue.irtime>=40) 
		{
			flag_start=1;引導碼 9ms+4.5ms 資料開始接收
			IrCountBit=0;//開始數數
			IrValue.count_repeat=0;//重發碼清零
		}
		if(flag_start)
		{
			IrValue.receive>>=1;
			if(IrValue.irtime>6&&IrValue.irtime<10) //邏輯1
			{
				IrValue.receive|=0x80000000;
			}
			else if(IrValue.irtime<513&&IrValue.irtime>=268)
			{
				IrValue.count_repeat++;
			}
			IrCountBit++;
			if(IrCountBit==33)	//接收完成
			{
				IrValueParse(IrValue.receive);	
			}
		}
		IrValue.irtime=0;//清空定時器變數
}

測試實驗

為驗證驅動程式是否正確,採用紅外遙控鍵值的變化顯示到LCD1602上進行驗證;
注:LCD驅動程式碼請參看連結: LCD驅動篇.

main.c檔案

#include "IrReceive.h"
#include "lcd1602.h"

void main(void)
{
	uchar buf[16];
	irReceiveInit();
	lcd1602Init();	//LCD初始化
	lcd1602Clear();	//清屏
	
	while(1)
	{
		if(IrValue.ok==1)//接收解碼完成
		{
			sprintf(buf,"%d",IrValue.cmd); //組包;
			lcd1602WriteString(0,0,buf); //列印字串
			IrValue.ok=0;//每按下一次顯示一次;
		}
	}
}

相關文章