紅外遙控模塊(階段完結(jié))

此為B站up:江科大自動協(xié)課程的12-2程序,學(xué)習(xí)用
跟著老師敲出來

主函數(shù)

main.c

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"

unsigned char Num;
unsigned char Address;
unsigned char Command;

void main()
{
    LCD_Init();
    LCD_ShowString(1,1,"ADDR  CMD  NUM");
    LCD_ShowString(2,1,"00    00   000");
    
    IR_Init();
    
    while(1)
    {
        if(IR_GetDataFlag() || IR_GetRepeatFlag())  //如果收到數(shù)據(jù)幀或者收到連發(fā)幀
        {
            Address=IR_GetAddress();        
            Command=IR_GetCommand();        
            
            LCD_ShowHexNum(2,1,Address,2);  
            LCD_ShowHexNum(2,7,Command,2);  
            
            if(Command==IR_VOL_MINUS)       //如果遙控器VOL-按鍵按下
            {
                Num--;                      
            }
            if(Command==IR_VOL_ADD)         //如果遙控器VOL+按鍵按下
            {
                Num++;                      
            }
            
            LCD_ShowNum(2,12,Num,3);        
        }
    }
}

演示模塊

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

Delay.c

void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms--)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
    }
}

中斷模塊

Int0.h

#ifndef __INT0_H__
#define __INT0_H__

void Int0_Init(void);

#endif

Int0.c

#include <REGX52.H>

void Int0_Init(void)
{
    IT0=1;
    IE0=0;
    EX0=1;
    EA=1;
    PX0=1;
}

顯示模塊

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用戶調(diào)用函數(shù):
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

LCD1602.c

#include <REGX52.H>

//引腳配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函數(shù)定義:
/**
  * @brief  LCD1602延時函數(shù),12MHz調(diào)用可延時1ms
  * @param  無
  * @retval 無
  */
void LCD_Delay()
{
    unsigned char i, j;

    i = 2;
    j = 239;
    do
    {
        while (--j);
    } while (--i);
}

/**
  * @brief  LCD1602寫命令
  * @param  Command 要寫入的命令
  * @retval 無
  */
void LCD_WriteCommand(unsigned char Command)
{
    LCD_RS=0;
    LCD_RW=0;
    LCD_DataPort=Command;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602寫數(shù)據(jù)
  * @param  Data 要寫入的數(shù)據(jù)
  * @retval 無
  */
void LCD_WriteData(unsigned char Data)
{
    LCD_RS=1;
    LCD_RW=0;
    LCD_DataPort=Data;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602設(shè)置光標(biāo)位置
  * @param  Line 行位置,范圍:1~2
  * @param  Column 列位置,范圍:1~16
  * @retval 無
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
    if(Line==1)
    {
        LCD_WriteCommand(0x80|(Column-1));
    }
    else if(Line==2)
    {
        LCD_WriteCommand(0x80|(Column-1+0x40));
    }
}

/**
  * @brief  LCD1602初始化函數(shù)
  * @param  無
  * @retval 無
  */
void LCD_Init()
{
    LCD_WriteCommand(0x38);//八位數(shù)據(jù)接口,兩行顯示,5*7點(diǎn)陣
    LCD_WriteCommand(0x0c);//顯示開,光標(biāo)關(guān),閃爍關(guān)
    LCD_WriteCommand(0x06);//數(shù)據(jù)讀寫操作后,光標(biāo)自動加一,畫面不動
    LCD_WriteCommand(0x01);//光標(biāo)復(fù)位,清屏
}

/**
  * @brief  在LCD1602指定位置上顯示一個字符
  * @param  Line 行位置,范圍:1~2
  * @param  Column 列位置,范圍:1~16
  * @param  Char 要顯示的字符
  * @retval 無
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
    LCD_SetCursor(Line,Column);
    LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置開始顯示所給字符串
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  String 要顯示的字符串
  * @retval 無
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=0;String[i]!='\0';i++)
    {
        LCD_WriteData(String[i]);
    }
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
    unsigned char i;
    int Result=1;
    for(i=0;i<Y;i++)
    {
        Result*=X;
    }
    return Result;
}

/**
  * @brief  在LCD1602指定位置開始顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:0~65535
  * @param  Length 要顯示數(shù)字的長度,范圍:1~5
  * @retval 無
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
    }
}

/**
  * @brief  在LCD1602指定位置開始以有符號十進(jìn)制顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:-32768~32767
  * @param  Length 要顯示數(shù)字的長度,范圍:1~5
  * @retval 無
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
    unsigned char i;
    unsigned int Number1;
    LCD_SetCursor(Line,Column);
    if(Number>=0)
    {
        LCD_WriteData('+');
        Number1=Number;
    }
    else
    {
        LCD_WriteData('-');
        Number1=-Number;
    }
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
    }
}

/**
  * @brief  在LCD1602指定位置開始以十六進(jìn)制顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:0~0xFFFF
  * @param  Length 要顯示數(shù)字的長度,范圍:1~4
  * @retval 無
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i,SingleNumber;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        SingleNumber=Number/LCD_Pow(16,i-1)%16;
        if(SingleNumber<10)
        {
            LCD_WriteData(SingleNumber+'0');
        }
        else
        {
            LCD_WriteData(SingleNumber-10+'A');
        }
    }
}

/**
  * @brief  在LCD1602指定位置開始以二進(jìn)制顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:0~1111 1111 1111 1111
  * @param  Length 要顯示數(shù)字的長度,范圍:1~16
  * @retval 無
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
    }
}

定時器模塊

Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0_Init(void);
void Timer0_SetCounter(unsigned int Value);
unsigned int Timer0_GetCounter(void);
void Timer0_Run(unsigned char Flag);

#endif

Timer0.c

#include <REGX52.H>

/**
  * @brief  定時器0初始化
  * @param  無
  * @retval 無
  */
void Timer0_Init(void)
{
    TMOD &= 0xF0;       //設(shè)置定時器模式
    TMOD |= 0x01;       //設(shè)置定時器模式
    TL0 = 0;        //設(shè)置定時初值
    TH0 = 0;        //設(shè)置定時初值
    TF0 = 0;        //清除TF0標(biāo)志
    TR0 = 0;        //定時器0不計(jì)時
}

void Timer0_SetCounter(unsigned int Value)
{
    TH0=Value/256;
    TL0=Value%256;
}

unsigned int Timer0_GetCounter(void)
{
    return (TH0<<8)|TL0;
}

Run(unsigned char Flag)
{
    TR0=Flag;
}

紅外遙控模塊

IR.h

#ifndef __IR_H__
#define __IR_H__

#define IR_VOL_MINUS    0x15
#define IR_VOL_ADD      0x09


void IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);

#endif

IR.c

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"

unsigned int IR_Time;
unsigned char IR_State;

unsigned char IR_Data[4];
unsigned char IR_pData;

unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;

void IR_Init(void)
{
    Timer0_Init();
    Int0_Init();
}


unsigned char IR_GetDataFlag(void)
{
    if(IR_DataFlag)
    {
        IR_DataFlag=0;
        return 1;
    }
    return 0;
}

unsigned char IR_GetRepeatFlag(void)
{
    if(IR_RepeatFlag)
    {
        IR_RepeatFlag=0;
        return 1;
    }
    return 0;
}

unsigned char IR_GetAddress(void)
{
    return IR_Address;
}

unsigned char IR_GetCommand(void)
{
    return IR_Command;
}

//外部中斷0中斷函數(shù),下降沿觸發(fā)執(zhí)行
void Int0_Routine(void) interrupt 0
{
    if(IR_State==0)         
        Timer0_SetCounter(0);   
        Timer0_Run(1);          //定時器啟動
        IR_State=1;             
    }
    else if(IR_State==1)    
    {
        IR_Time=Timer0_GetCounter();    
        Timer0_SetCounter(0);   //定時計(jì)數(shù)器清0
        if(IR_Time>12442-500 && IR_Time<12442+500)
        {
            IR_State=2;         
        }
        else if(IR_Time>10368-500 && IR_Time<10368+500)
        {
            IR_RepeatFlag=1;    
            Timer0_Run(0);      //定時器停止
            IR_State=0;         
        }
        else                
        {
            IR_State=1;     
        }
    }
    else if(IR_State==2)        
    {
        IR_Time=Timer0_GetCounter();    
        Timer0_SetCounter(0);   //定時計(jì)數(shù)器清0
        //如果計(jì)時為1120us,
        if(IR_Time>1032-500 && IR_Time<1032+500)
        {
            IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8)); 
            IR_pData++;     
        }
        else if(IR_Time>2074-500 && IR_Time<2074+500)
        {
            IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));  
            IR_pData++;         
        }
        else                    
        {
            IR_pData=0;         
            IR_State=1;         
        }
        if(IR_pData>=32)        //如果接收到了32位數(shù)據(jù)
        {
            IR_pData=0;         //數(shù)據(jù)位置指針清0
            if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))  
            {
                IR_Address=IR_Data[0];  //轉(zhuǎn)存數(shù)據(jù)
                IR_Command=IR_Data[2];
                IR_DataFlag=1;  
            }
            Timer0_Run(0);  
            IR_State=0;     
        }
    }
}

效果

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容