<p>//很简单的一个小程序,帮别人做的一个学业方面的设计:</p><p>//分为发送端和接收端,发射端P34上接了一个9012三极管,然后再在三极管上连接了一个光电二极管</p><p>//#当然三极管可以随便选取,只要可以驱动二极管即可,也不能烧坏了</p><p>//发射端程序:</p>
#include <reg52.h>
sbit P3_4 = P3^4;
static bit OP; //红外发射管的亮灭
static unsigned int ncount; //延时计数器
static unsigned int endncount; //终止延时计数
static unsigned char flag; //红外发送标志
char iraddr1; //十六位地址的第一个字节
char iraddr2; //十六位地址的第二个字节
void SendIRdata(char p_irdata);
void delay();
void main(void)
{
ncount = 0;
flag = 0;
OP = 0;
P3_4 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFF;
TL0 = 0xE8; //设定时值0为38K 也就是每隔26us中断一次
TR0 = 1;//开始计数
iraddr1=3;
iraddr2=252;
do{
//unsigned char i;
delay();
SendIRdata(12);
}while(1);
}
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFF;
TL0=0xE8; //设定时值为38K 也就是每隔26us中断一次
ncount++;
if (flag==1)
{
OP=~OP;
}
else
{
OP = 0;
}
P3_4 = OP;
}
void SendIRdata(char p_irdata)
{
int i;
char irdata=p_irdata;
//发送9ms的起始码
endncount=223;
flag=1;
ncount=0;
do{}while(ncount<endncount);
//发送4.5ms的结果码
endncount=117;
flag=0;
ncount=0;
do{}while(ncount<endncount);
//发送十六位地址的前八位
irdata=iraddr1;
for(i=0;i<8;i++)
{
//先发送0.56ms的38KHZ红外波(即编码中0.56ms的低电平)
endncount=10;
flag=1;
ncount=0;
do{}while(ncount<endncount);
//停止发送红外信号(即编码中的高电平)
if(irdata-(irdata/2)*2) //判断二进制数个位为1还是0
{
endncount=41; //1为宽的高电平
}
else
{
endncount=15; //0为窄的高电平
}
flag=0;
ncount=0;
do{}while(ncount<endncount);
irdata=irdata>>1;
}
//发送十六位地址的后八位
irdata=iraddr2;
for(i=0;i<8;i++)
{
endncount=10;
flag=1;
ncount=0;
do{}while(ncount<endncount);
if(irdata-(irdata/2)*2)
{
endncount=41;
}
else
{
endncount=15;
}
flag=0;
ncount=0;
do{}while(ncount<endncount);
irdata=irdata>>1;
}
//发送八位数据
irdata=p_irdata;
for(i=0;i<8;i++)
{
endncount=10;
flag=1;
ncount=0;
do{}while(ncount<endncount);
if(irdata-(irdata/2)*2)
{
endncount=41;
}
else
{
endncount=15;
}
flag=0;
ncount=0;
do{}while(ncount<endncount);
irdata=irdata>>1;
}
//发送八位数据的反码
irdata=~p_irdata;
for(i=0;i<8;i++)
{
endncount=10;
flag=1;
ncount=0;
do{}while(ncount<endncount);
if(irdata-(irdata/2)*2)
{
endncount=41;
}
else
{
endncount=15;
}
flag=0;
ncount=0;
do{}while(ncount<endncount);
irdata=irdata>>1;
}
endncount=10;
flag=1;
ncount=0;
do{}while(ncount<endncount);
flag=0;
}
void delay()
{
int i,j;
for(i = 0; i < 400; i++){
for(j = 0; j < 200; j++){
}
}
}
接收端程序:
mian.c
/*-----------------------------------------------
功能:红外解码并显示
------------------------------------------------*/
#include <reg52.h>
#include <intrins.h>
#include "delay.h"
#define uint unsigned int
#define uchar unsigned char
sbit IR=P3^3; //红外接口标志
char buff[10];
void DisplayListChar(uchar X,uchar Y, unsigned char *DData);
void initLCM(void);
void cheng(char disdata);
/*------------------------------------------------
全局变量声明
------------------------------------------------*/
unsigned char irtime;//红外用全局变量
bit irpro_ok,irok;
unsigned char IRcord[4];
unsigned char irdata[33];
unsigned char TempData[16];
/*------------------------------------------------
函数声明
------------------------------------------------*/
void Ir_work(void);
void Ircordpro(void);
/*------------------------------------------------
定时器0中断处理
------------------------------------------------*/
void tim0_isr (void) interrupt 1 using 1
{
irtime++; //用于计数2个下降沿之间的时间
}
/*------------------------------------------------
外部中断1中断处理
------------------------------------------------*/
void EX1_ISR (void) interrupt 2 //外部中断1服务函数
{
static unsigned char i; //接收红外信号处理
static bit startflag; //是否开始处理标志位
if(startflag)
{
if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
i=0;
irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
else
{
irtime=0;
startflag=1;
}
}
/*------------------------------------------------
定时器0初始化
------------------------------------------------*/
void TIM0init(void)//定时器0初始化
{
TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
TH0=0x00; //重载值
TL0=0x00; //初始化值
ET0=1; //开中断
TR0=1;
}
/*------------------------------------------------
外部中断1初始化
------------------------------------------------*/
void EX1init(void)
{
IT1 = 1; //指定外部中断1下降沿触发,INT1 (P3.3)
EX1 = 1; //使能外部中断
EA = 1; //开总中断
}
/*------------------------------------------------
键值处理
------------------------------------------------*/
void Ir_work(void)
{
cheng(IRcord[2]);
DisplayListChar(12,0,buff);
cheng(IRcord[1]);
DisplayListChar(12,1,buff);
irpro_ok=0;//处理完成标志
}
/*------------------------------------------------
红外码值处理
------------------------------------------------*/
void Ircordpro(void)//红外码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
cord=irdata[k];
if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
value|=0x80;
if(j<8)
{
value>>=1;
}
k++;
}
IRcord[i]=value;
value=0;
}
irpro_ok=1;//处理完毕标志位置1
}
/*------------------------------------------------
主程序
------------------------------------------------*/
void main(void)
{
EX1init(); //初始化外部中断1
TIM0init(); //
initLCM();
DisplayListChar(0, 0,"Temperature:");
DisplayListChar(0, 1,"Humidity:");
while(1)//主循环
{
if(irok) //如果接收好了进行红外处理
{
Ircordpro();
irok=0;
}
if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
{
Ir_work();
}
}
}
void cheng(char disdata)
{
buff[0]=disdata/1000+48;
buff[1]=disdata%1000/100+48;
buff[2]=disdata%100/10+48;
buff[3]=disdata%10+48;
}
lcd.c
#include <reg52.h>
#include <intrins.h>
#include <string.h>
#include <absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define BUSY 0x80 //lcd忙检测标志
#define DATAPORT P0 //定义P0口为LCD通讯端口
sbit light=P1^3;
sbit LCM_RS=P2^0; //数据/命令端
sbit LCM_RW=P2^1; //读/写选择端
sbit LCM_EN=P2^2;
void delay_LCM(uint); //LCD延时子程序
void lcd_wait(void); //LCD检测忙子程序
void WriteCommandLCM(uchar WCLCM,uchar BusyC); //写指令到ICM子函数
void WriteDataLCM(uchar WDLCM); //写数据到LCM子函数
void DisplayOneChar(uchar X,uchar Y,uchar DData); //显示指定坐标的一个字符子函数
void initLCM( void); //LCD初始化子程序
void DisplayListChar(uchar X,uchar Y, unsigned char *DData); //显示指定坐标的一串字符子函数
/*********延时K*1ms,12.000mhz**********/
void delay_LCM(uint k)
{
uint i,j;
for(i=0;i<k;i++)
{
for(j=0;j<60;j++)
{;}
}
}
/**********写指令到LCM子函数************/
void WriteCommandLCM(uchar WCLCM,uchar BusyC)
{
if(BusyC)lcd_wait();
DATAPORT=WCLCM;
LCM_RS=0; // 选中指令寄存器
LCM_RW=0; // 写模式
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
/**********写数据到LCM子函数************/
void WriteDataLCM(uchar WDLCM)
{
lcd_wait( ); //检测忙信号
DATAPORT=WDLCM;
LCM_RS=1; // 选中数据寄存器
LCM_RW=0; // 写模式
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
/***********lcm内部等待函数*************/
void lcd_wait(void)
{
DATAPORT=0xff;
LCM_EN=1;
LCM_RS=0;
LCM_RW=1;
_nop_();
while(DATAPORT&BUSY)
{ LCM_EN=0;
_nop_();
_nop_();
LCM_EN=1;
_nop_();
_nop_();
}
LCM_EN=0;
}
/**********LCM初始化子函数***********/
void initLCM( )
{
DATAPORT=0;
delay_LCM(15);
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
delay_LCM(5);
WriteCommandLCM(0x38,0);
delay_LCM(5);
WriteCommandLCM(0x38,0);
delay_LCM(5);
WriteCommandLCM(0x38,1); //8bit数据传送,2行显示,5*7字型,检测忙信号
WriteCommandLCM(0x08,1); //关闭显示,检测忙信号
WriteCommandLCM(0x01,1); //清屏,检测忙信号
WriteCommandLCM(0x06,1); //显示光标右移设置,检测忙信号
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
}
/****************显示指定坐标的一个字符子函数*************/
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
uchar mx,my;
my=Y&1;
mx=X&0xf;
if(my>0)mx+=0x40; //若y为1(显示第二行),地址码+0X40
mx+=0x80; //指令码为地址码+0X80
WriteCommandLCM(mx,0);
WriteDataLCM(DData);
}
/***********显示指定坐标的一串字符子函数***********/
void DisplayListChar(uchar X,uchar Y, unsigned char *DData)
{
uchar i=0,n;
Y&=0x01;
X&=0x0f;
n=strlen(DData);
while(i<n)
{
DisplayOneChar(X,Y,DData[i]);
i++;
X++;
}
}