找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4229|回复: 4
打印 上一主题 下一主题
收起左侧

红外使用单片机外部中断+定时器解码

[复制链接]
跳转到指定楼层
楼主
ID:61973 发表于 2018-8-5 21:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
包含了红外解码,自动根据波特率设置定时器溢出率以及使用定时器延时
串口部分:
void UART1_Init(u32 Boud)
{
        u16 Temp = (65536 - FOSC/Boud/4);
        SCON = 0x50;
    T2L = Temp;        
    T2H = Temp >> 8;
    AUXR |= 0x15;                                //启动定时器
    ES = 1;                                     //使能串口中断
}
char putchar(u8 c)
{
        SBUF = c;
        while(!TI);
        TI = 0;
        return c;
}
void UART1_ISR() interrupt 4 using 1
{
    if(RI)
    {
        RI = 0;                                 //清中断标志
    }
//        if(TI)
//        {
//                TI = 0;                                 //清中断标志
//        }
}

//定时器延时部分
#include "delay.h"
#define TICK_US                (FOSC/1000000/12)
volatile u16 told = 0;                                //计数器旧值               
volatile u16 tnow = 0;                                //计数器新值               
volatile u16 tick = 0;                                //计数值               
volatile u16 delay_tick = 0;                //延时计数值
void delay_init(void)
{
        T4L = 0;                                
    T4H = 0;
        T4T3M &= 0x0F;
        T4T3M |= B1000_0000;         //启动定时器 12T
        told = 0;                        
        tnow = 0;
        tick = 0;
        delay_tick = 0;
}
void delay(u16 us)
{
        told = T4H << 8 | T4L;                        
        tnow = 0;tick = 0;
        delay_tick = us * TICK_US;
        while(1)
        {
                tnow = T4H << 8 | T4L;
                if(tnow != told)
                {
                        if(tnow > told)
                        {
                                tick += tnow - told;
                        }
                        else                                //定时器溢出
                        {
                                tick += 65535 + tnow - told;
                        }
                        told = tnow;
                        if(tick >= delay_tick)
                                break;
                }
        }
}

//红外解码
#include "INT.h"
#include "USART.h"
u8 IR_Cnt = 0;
#define T51                                (FOSC/1000000/12)
#define REMOTE_ID                 0   
//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留        
//[4]:标记上升沿是否已经被捕获                                                                  
//[3:0]:溢出计时器
u8 IR_sta = 0;
u32 IR_Rec = 0;
sbit INT0 = P3^2;
void IR_Init(void)
{
        IT0 = 0;            //使能INT0上升沿和下降沿中断
    EX0 = 1;             //使能INT0中断
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TMOD |= 0x01;                //设置定时器模式
        TF0 = 0;                //清除TF0标志
        TL0 = 0;                //设置定时初值
        TH0 = 0;                //设置定时初值
        TR0 = 0;                //定时器0开始计时
        ET0 = 1;
}
//处理红外键盘
//返回值:
//         0,没有任何按键按下
//其他,按下的按键键值.
u8 IR_Scan(void)
{      
        u8 Key = 0;      
        if(IR_sta & (1<<6))//得到一个按键的所有信息了
        {  
                u8 TEMP[2];
            TEMP[0] = IR_Rec>>24;                        //得到地址码
            TEMP[1] = (IR_Rec>>16)&0xff;        //得到地址反码
             if((TEMP[0] == (u8)~TEMP[1]) && TEMP[0] == REMOTE_ID)//检验遥控识别码(ID)及地址
            {
                TEMP[0] = IR_Rec>>8;
                TEMP[1] = IR_Rec;         
                if(TEMP[0] == (u8)~TEMP[1])
                                Key = TEMP[0];//键值正确         
                }
                if(Key == 0||(IR_sta&0X80) == 0)//按键数据错误/遥控已经没有按下了
                {
                        IR_sta&=~(1<<6);//清除接收到有效按键标识
                        IR_Cnt = 0;                //清除按键次数计数器
                }
        }  
    return Key;
}

void INT0_ISR(void) interrupt 0 using 1
{
        if(INT0)//上升沿捕获
        {
                TL0 = 0;                //设置定时初值
                TH0 = 0;                //设置定时初值
                TR0 = 1;                //定时器0开始计时
                IR_sta |= 0X10;                                        //标记上升沿已经被捕获
        }
        else //下降沿捕获
        {
                u16 Count_Time = 0;
                Count_Time = TH0 << 8|TL0;                                
                TL0 = 0;                //设置定时初值
                TH0 = 0;                //设置定时初值
                if(IR_sta & 0X10)                                        //完成一次高电平捕获
                {
                        if(IR_sta & 0X80)//接收到了引导码
                        {
                                if(Count_Time > (300 * T51) && Count_Time < (800 * T51))                        //560为标准值,560us
                                {
                                        IR_Rec <<= 1;        //左移一位.
                                        IR_Rec |= 0;        //接收到0        
                                }
                                else if(Count_Time > (1400 * T51) && Count_Time < (1800 * T51))        //1680为标准值,1680us
                                {
                                        IR_Rec <<= 1;        //左移一位.
                                        IR_Rec |= 1;        //接收到1
                                }
                                else if(Count_Time > (2200 * T51) && Count_Time < (2600 * T51))        //得到按键键值增加的信息 2500为标准值2.5ms
                                {
                                        IR_Cnt++;                 //按键次数增加1次
                                        IR_sta&=0XF0;        //清空计时器        
                                }
                        }
                        else if(Count_Time > (4200 * T51) && Count_Time < (4700 * T51))                //4500为标准值4.5ms
                        {
                                IR_sta|=1<<7;        //标记成功接收到了引导码
                                IR_Cnt=0;                //清除按键次数计数器
                        }                                                
                }
                IR_sta &=~(1<<4);
        }               
}
void TIME0_ISR(void) interrupt 1 using 1
{
    TL0 = 0;                //设置定时初值
        TH0 = 0;                //设置定时初值
        if(IR_sta&0x80)//上次有数据被接收到了
        {        
                IR_sta &= ~0X10;                                                //取消上升沿已经被捕获标记
                if((IR_sta&0X0F) == 0X00)
                        IR_sta|=1<<6;//标记已经完成一次按键的键值信息采集        
                if((IR_sta&0X0F) < 14)
                        IR_sta++;
                else
                {
                        TR0 = 0;                //定时器0开始计时
                        IR_sta&=~(1<<7);//清空引导标识
                        IR_sta&=0XF0;        //清空计数器        
                }                        
        }        
}


STC8.rar

288.26 KB, 下载次数: 28, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:290576 发表于 2018-8-22 00:22 | 只看该作者
标记下  感谢楼主
回复

使用道具 举报

板凳
ID:337813 发表于 2018-10-21 23:22 | 只看该作者
感谢您的无私分享,谢谢你!!!
回复

使用道具 举报

地板
ID:298008 发表于 2018-10-22 15:39 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

5#
ID:615610 发表于 2020-6-24 20:10 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表