51单片机模拟红外遥控发射传输温湿度数据

<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++;
    }
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值