单片机实例---红外与lcd1602

main.c

/*******************************************************************************
*                       LCD1602显示红外遥控键值
    
*******************************************************************************/ 
#include 
#include "lcd.h"

sbit IRIN=P3^2;

unsigned char code CDIS1[13]={" Red Control "};
unsigned char code CDIS2[13]={" IR-CODE:--H "};
unsigned char IrValue[6];
unsigned char Time;
void IrInit();
void DelayMs(unsigned int );
/*******************************************************************************
* 函数名         : main
* 函数功能         : 主函数
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void main()
{
    unsigned char i;
    IrInit();  //外部中断0初始化   
    LcdInit();  //lcd初始化
    LcdWriteCom(0x80);  //写入数据显示地址(第一行第一位)

    for(i=0;i<13;i++)  //数据写入后不会消失,除非在那个位置重新写入
    {
        LcdWriteData(CDIS1[i]); 
    }
    LcdWriteCom(0x80+0x40);
    for(i=0;i<13;i++)
    {
        LcdWriteData(CDIS2[i]); 
    }

    while(1)  //将16进制数据转变为ASC码并显示,16进制是0~F,分开是0~9,和A~F.
    {
        IrValue[4]=IrValue[2]>>4;           //数据高位
        IrValue[5]=IrValue[2]&0x0f;     //数据低位  

        if(IrValue[4]>9)   //表示数据是A~F,此时16进制变为ASC需要加上0x37
        {
            LcdWriteCom(0xc0+0x09);         //设置显示位置 ,在第二行,0xc0 = 0x80+0x40
            LcdWriteData(0x37+IrValue[4]);  //将数值转换为该显示的ASCII码
        }
        else
        {
            LcdWriteCom(0xc0+0x09);
            LcdWriteData(IrValue[4]+0x30);  //将数值转换为该显示的ASCII码,此时是0~9,加上是0x30
        }   
        if(IrValue[5]>9)
        {
            LcdWriteCom(0xc0+0x0a);
            LcdWriteData(IrValue[5]+0x37);      //将数值转换为该显示的ASCII码
        }
        else
        {
            LcdWriteCom(0xc0+0x0a);
            LcdWriteData(IrValue[5]+0x30);      //将数值转换为该显示的ASCII码
        }   
    }
}                                    
/*******************************************************************************
* 函数名         : DelayMs()
* 函数功能         : 延时
* 输入           : x
* 输出             : 无
*******************************************************************************/

void DelayMs(unsigned int x)   //0.14ms误差 0us
{
 unsigned char i;
  while(x--)
 {
  for (i = 0; i<13; i++)
 {}
 }
}
/*******************************************************************************
* 函数名         : IrInit()
* 函数功能         : 初始化红外线接收
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void IrInit()
{
    IT0=1;//下降沿触发
    EX0=1;//打开中断0允许
    EA=1;   //打开总中断

    IRIN=1;//初始化端口
}
/*******************************************************************************
* 函数名         : ReadIr()
* 函数功能         : 读取红外数值的中断函数
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void ReadIr() interrupt 0
{
    unsigned char j,k;
    unsigned int err;
    Time=0;                  
    DelayMs(70);

    if(IRIN==0)     //确认是否真的接收到正确的信号
    {    
        
        err=1000;               //1000*10us=10ms,超过说明接收到错误的信号
        /*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
        侯,程序死在这里*/  
        while((IRIN==0)&&(err>0))   //等待前面9ms的低电平过去         
        {           
            DelayMs(1);
            err--;
        } 
        if(IRIN==1)         //如果正确等到9ms低电平
        {
            err=500;
            while((IRIN==1)&&(err>0))        //等待4.5ms的起始高电平过去
            {
                DelayMs(1);
                err--;
            }
            for(k=0;k<4;k++)        //共有4组数据
            {               
                for(j=0;j<8;j++)    //接收一组数据
                {

                    err=60;     
                    while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
//                  while (!IRIN)
                    {
                        DelayMs(1);
                        err--;
                    }
                    err=500;
                    while((IRIN==1)&&(err>0))    //计算高电平的时间长度。
                    {
                        DelayMs(1);//0.14ms
                        Time++;
                        err--;
                        if(Time>30)
                        {
                            EX0=1;
                            return;
                        }
                    }
                    IrValue[k]>>=1;  //k表示第几组数据
                    if(Time>=8)         //如果高电平出现大于565us,那么是1
                    {
                        IrValue[k]|=0x80;
                    }
                    Time=0;     //用完时间要重新赋值                         
                }
            }
        }
        if(IrValue[2]!=~IrValue[3])
        {
            return;
        }
    }           
}

lcd.c

#include "lcd.h"

/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能         : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar a,b;
    for (; c>0; c--)
    {
         for (b=199;b>0;b--)
         {
            for(a=1;a>0;a--);
         }      
    }
        
}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能         : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
#ifndef     LCD1602_4PINS    //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com)   //写入命令
{
    LCD1602_E = 0;     //使能
    LCD1602_RS = 0;    //选择发送命令
    LCD1602_RW = 0;    //选择写入
    
    LCD1602_DATAPINS = com;     //放入命令
    Lcd1602_Delay1ms(1);        //等待数据稳定

    LCD1602_E = 1;            //写入时序
    Lcd1602_Delay1ms(5);      //保持时间
    LCD1602_E = 0;
}
#else 
void LcdWriteCom(uchar com)   //写入命令
{
    LCD1602_E = 0;   //使能清零
    LCD1602_RS = 0;  //选择写入命令
    LCD1602_RW = 0;  //选择写入

    LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;   //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;

//  Lcd1602_Delay1ms(1);
    LCD1602_DATAPINS = com << 4; //发送低四位
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;   //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能         : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/           
#ifndef     LCD1602_4PINS          
void LcdWriteData(uchar dat)            //写入数据
{
    LCD1602_E = 0;  //使能清零
    LCD1602_RS = 1; //选择输入数据
    LCD1602_RW = 0; //选择写入

    LCD1602_DATAPINS = dat; //写入数据
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;   //写入时序
    Lcd1602_Delay1ms(5);   //保持时间
    LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)            //写入数据
{
    LCD1602_E = 0;    //使能清零
    LCD1602_RS = 1;   //选择写入数据
    LCD1602_RW = 0;   //选择写入

    LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;    //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;

    LCD1602_DATAPINS = dat << 4; //写入低四位
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;    //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能       : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/           
#ifndef     LCD1602_4PINS
void LcdInit()                        //LCD初始化子程序
{
    LcdWriteCom(0x38);  //开显示
    LcdWriteCom(0x0c);  //开显示不显示光标
    LcdWriteCom(0x06);  //写一个指针加1
    LcdWriteCom(0x01);  //清屏
    LcdWriteCom(0x80);  //设置数据指针起点
}
#else
void LcdInit()                        //LCD初始化子程序
{
    LcdWriteCom(0x32);   //将8位总线转为4位总线
    LcdWriteCom(0x28);   //在四位线下的初始化
    LcdWriteCom(0x0c);   //开显示不显示光标
    LcdWriteCom(0x06);   //写一个指针加1
    LcdWriteCom(0x01);   //清屏
    LcdWriteCom(0x80);   //设置数据指针起点
}
#endif


lcd.h

#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif

/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;

/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c);   //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/    
void LcdWriteData(uchar dat)    ;
/*LCD1602初始化子程序*/       
void LcdInit();                       

#endif

你可能感兴趣的:(单片机实例---红外与lcd1602)