C51红外遥控驱动程序
本文为学习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;//每按下一次显示一次;
}
}
}