求义隆单片机c语言红外解码程序,只用一个单片机定时器的红外接收解码程序...

/****************《51单片机轻松入门-基于STC15W4K系列》配套例程 *************

★★★★★★★★★★★★★★★★★★★★★★★★

《51单片机轻松入门-基于STC15W4K系列》 一书已经由北航出版社正式出版发行。

作者亲手创作的与教材配套的51双核实验板(2个MCU)对程序下载、调试、仿真方便,不需要外部

仿真器与编程器,这种设计方式彻底解决了系统中多个最高优先级谁也不能让谁的中断竞争问题。

QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。

验证信息:STC15单片机

邮箱:xgliyouquan@126.com

★★★★★★★★★★★★★★★★★★★★★★★★*/

///*************        功能说明        **************

//红外接收程序。适用于市场上用量最大的HT6121/6122及其兼容IC的编码。

//当遥控器用户码与程序定义的用户码不同时,程序会将遥控器的用户码一起从串口输出。

//使用模拟串口发送用户码与键码,波特率9600,接收端要求使用字符格式显示。

/******************************************/

#include        "STC15W4K.H"

#define MAIN_Fosc                22.1184        // 定义主时钟, 红外接收会自动适应,5~36MHZ,但模拟串口输出部分不能自动适应。

#define        User_code                0xFD02                // 定义红外接收用户码

sbit        Ir_Pin = P3^6;                        // 定义红外接收输入端口

sbit        TXD1 = P3^1;                          // 定义模拟串口发送脚

/*************        用户系统配置        **************/

#define TIME                125                              // 选择定时器时间125us, 红外接收要求在60us~250us之间

/*************        以下宏定义用户请勿修改        **************/

#define Timer0_Reload (unsigned int)(65536 - (TIME * MAIN_Fosc /12.0))  // 定时器初值

/*************        本地变量声明        **************/

unsigned char        IR_SampleCnt;                // 采样次数计数器,通用定时器对红外口检测次数累加记录

unsigned char        IR_BitCnt;                        // 记录位数

unsigned char        IR_UserH;                        // 用户码(地址)高字节

unsigned char        IR_UserL;                        // 用户码(地址)低字节

unsigned char        IR_data;                        // 键原码

unsigned char        IR_DataShit;                // 键反码

unsigned char        IR_code;                        // 红外键码

bit                Ir_Pin_temp;                        // 记录红外引脚电平的临时变量

bit                IR_Sync;                                // 同步标志(1——已收到同步信号,0——没收到)

bit                IrUserErr;                            // 用户码错误标志

bit                IR_OK;                        // 完成一帧红外数据接收的标志(0,未收到,1,收到一帧完整数据)

/******************** 红外采样时间宏定义, 用户不要随意修改        *******************/

//数据格式: Synchro,AddressH,AddressL,data,/data, (total 32 bit).

#if ((TIME <= 250) && (TIME >= 60))                        // TIME决定测量误差,TIME太大防错能力降低,TIME太小会干扰其它中断函数执行。

#define        IR_sample                        TIME                // 定义采样时间,在60us~250us之间,

#endif

#define IR_SYNC_MAX                (15000/IR_sample)        // 同步信号SYNC 最大时间 15ms(标准值9+4.5=13.5ms)

#define IR_SYNC_MIN                (9700 /IR_sample)        // 同步信号SYNC 最小时间 9.5ms,(连发信号标准值9+2.25=11.25ms)

#define IR_SYNC_DIVIDE        (12375/IR_sample)        // 区分13.5ms同步信号与11.25ms连发信号,11.25+(13.5-11.25)/2=12.375ms

#define IR_DATA_MAX                (3000 /IR_sample)        // 数据最大时间3ms    (标准值2.25 ms)

#define IR_DATA_MIN                (600  /IR_sample)        // 数据最小时,0.6ms   (标准值1.12 ms)

#define IR_DATA_DIVIDE        (1687 /IR_sample)        // 区分数据 0与1,1.12+ (2.25-1.12)/2 =1.685ms

#define IR_BIT_NUMBER                32                                // 32位数据

//****************************  红外接收模块  ********************************************

// 信号第1个下降沿时刻清零计数器并让计数器从0开始计数,第2个下降沿时刻计算计数器运行时间

// 因此检测的是每个信号从低电平开始到高电平结束这段时间,也就是脉冲周期。

void IR_RX_HT6121(void)

{

unsigned char        SampleTime;                                // 信号周期

IR_SampleCnt++;                                                        // 定时器对红外口检测次数

F0 = Ir_Pin_temp;                                                // 保存前一次此程序扫描到的红外端口电平

Ir_Pin_temp = Ir_Pin;                                        // 读取当前红外接收输入端口电平

if(F0 && !Ir_Pin_temp)                                        // 前一次采样高电平并且当前采样低电平,说明出现了下降沿

{

SampleTime = IR_SampleCnt;                        // 脉冲周期

IR_SampleCnt = 0;                                        // 出现了下降沿则清零计数器

//******************* 接收同步信号 **********************************

if(SampleTime > IR_SYNC_MAX)                IR_Sync = 0;        // 超出最大同步时间, 错误信息。

else if(SampleTime >= IR_SYNC_MIN)                // SYNC

{

if(SampleTime >= IR_SYNC_DIVIDE)    // 区分13.5ms同步信号与11.25ms连发信号

{

IR_Sync = 1;                                    // 收到同步信号 SYNC

IR_BitCnt = IR_BIT_NUMBER;          // 赋值32(32位有用信号)

}

}

//********************************************************************

else if(IR_Sync)                                                // 已收到同步信号 SYNC

{

if((SampleTime < IR_DATA_MIN)|(SampleTime > IR_DATA_MAX)) IR_Sync=0;        // 数据周期过短或过长,错误

else

{

IR_DataShit >>= 1;                                        // 键反码右移1位(发送端是低位在前,高位在后的格式)

if(SampleTime >= IR_DATA_DIVIDE)        IR_DataShit |= 0x80;        // 区别是数据 0还是1

//***********************  32位数据接收完毕 ****************************************

if(--IR_BitCnt == 0)

{

IR_Sync = 0;                                        // 清除同步信号标志

if(~IR_DataShit == IR_data)                // 判断数据正反码

{

if((IR_UserH == (User_code / 256)) && IR_UserL == (User_code % 256))

{

IrUserErr = 0;            // 用户码正确

}

else        IrUserErr = 1;            // 用户码错误

IR_code      = IR_data;                // 键码值

IR_OK   = 1;                            // 数据有效

}

}

// 格式:  用户码L —— 用户码H —— 键码 —— 键反码

// 功能:  将 “用户码L —— 用户码H —— 键码”通过3次接收交换后存入对应字节,

//         这样写代码可以节省内存RAM占用,但是不如用数组保存好理解。

//         键反码前面部分代码已保存好了        :IR_DataShit |= 0x80;

//**************************** 将接收的************************************************

else if((IR_BitCnt & 7)== 0)                // 1个字节接收完成

{

IR_UserL = IR_UserH;                        // 保存用户码高字节

IR_UserH = IR_data;                                // 保存用户码低字节

IR_data  = IR_DataShit;                        // 保存当前红外字节

}

}

}

}

}

/**************** Timer0初始化函数 ******************************/

void InitTimer0(void)

{

TMOD = 0x01;                         // 16位计数方式.

TH0 = Timer0_Reload / 256;

TL0 = Timer0_Reload % 256;

ET0 = 1;

TR0 = 1;

EA  = 1;

}

/********************** Timer0中断函数************************/

void timer0 (void) interrupt 1

{

IR_RX_HT6121();

TH0 = Timer0_Reload / 256;           // 重装定时器初值

TL0 = Timer0_Reload % 256;           // 重装定时器初值

}

/********************** 模拟串口相关函数************************/

void delay104us(void)

{

unsigned char i,j,k;

for(i=1;i>0;i--)       // 注意后面没分号

for(j=3;j>0;j--)       // 注意后面没分号

for(k=189;k>0;k--);    // 注意后面有分号        101

}

//模拟串口发送

void Tx1Send(unsigned char dat)                //9600,N,8,1                发送一个字节

{

unsigned char        i;

EA = 0;

TXD1 = 0;

delay104us();

for(i=0; i<8; i++)

{

if(dat & 1)                TXD1 = 1;

else                        TXD1 = 0;

dat >>= 1;

delay104us();

}

TXD1 = 1;

EA = 1;

delay104us();

delay104us();

}

void PrintString(unsigned char code *puts)                    // 发送一串字符串

{

for (; *puts != 0;        puts++)  Tx1Send(*puts);         // 遇到停止符0结束

}

/********************* 十六进制转ASCII函数 *************************/

unsigned char        HEX2ASCII(unsigned char dat)

{

dat &= 0x0f;

if(dat <= 9)        return (dat + '0');        //数字0~9

return (dat - 10 + 'A');                        //字母A~F

}

/********************* 主函数 *************************/

void main(void)

{

InitTimer0();                                    // 初始化Timer0

PrintString("定时器0初始化完毕\r\n");        // 上电后串口发送一条提示信息

while(1)

{

if(IR_OK)                                     // 接收到一帧完整的红外数据

{

PrintString("红外键码: 0x");                // 提示红外键码

Tx1Send(HEX2ASCII(IR_code >> 4));        // 键码高半字节

Tx1Send(HEX2ASCII(IR_code));                // 键码低半字节

if(IrUserErr)                                                // 用户码错误,则发送用户码

{

Tx1Send(' ');                                        // 发空格

Tx1Send(' ');                                        // 发空格

PrintString("用户码: 0x");                // 提示用户码

Tx1Send(HEX2ASCII(IR_UserH >> 4));        // 用户码高字节的高半字节

Tx1Send(HEX2ASCII(IR_UserH));                // 用户码高字节的低半字节

Tx1Send(HEX2ASCII(IR_UserL >> 4));        // 用户码低字节的高半字节

Tx1Send(HEX2ASCII(IR_UserL));                // 用户码低字节的低半字节

}

Tx1Send(0x0d);                          // 发回车

Tx1Send(0x0a);                          // 发回车

IR_OK = 0;                              // 清除IR键按下标志

}

}

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值