单片机
返回首页

21_红外遥控

2025-09-05 来源:cnblogs

介绍

image-20231129190715228

硬件电路

image-20231129191035748

基本发送和接收

image-20231129201010474

NEC编码

image-20231129201127650

image-20231129201528564

遥控器键码

image-20231129201944042

51单片机的外部中断

image-20231129202009226

外部中断寄存器

image-20231129202114484


红外遥控 VOL-/VOL+

Timer0.c


#include


void Timer0_Init(void)

{

TMOD &= 0xF0; //设置定时器模式

TMOD |= 0x01; //设置定时器模式

TL0 = 0; //设置定时初始值

TH0 = 0; //设置定时初始值

TF0 = 0; //清除TF0标志

TR0 = 0; //定时器0不计时

}


void Timer0_SetCounter(unsigned int Value)

{

TH0=Value/256;

TL0=Value%256;

}


unsigned int Timer0_GetCounter()

{

return (TH0<<8)|TL0;

}


void Timer0_Run(unsigned char Flag)

{

TR0=Flag;

}

Timer0.h


#ifndef __TIMER0_H__

#define __TIMER0_H__


void Timer0_Init(void);


void Timer0_SetCounter(unsigned int Value);


unsigned int Timer0_GetCounter();


void Timer0_Run(unsigned char Flag);


#endif

IR.c


#include

#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;


/**

  * @brief  红外遥控初始化

  * @param  无

  * @retval 无

  */

void IR_Init(void)

{

Timer0_Init();

Int0_Init();

}


/**

  * @brief  红外遥控获取收到数据帧标志位

  * @param  无

  * @retval 是否收到数据帧,1为收到,0为未收到

  */

unsigned char IR_GetDataFlag(void)

{

if(IR_DataFlag)

{

IR_DataFlag=0;

return 1;

}

return 0;

}


/**

  * @brief  红外遥控获取收到连发帧标志位

  * @param  无

  * @retval 是否收到连发帧,1为收到,0为未收到

  */

unsigned char IR_GetRepeatFlag(void)

{

if(IR_RepeatFlag)

{

IR_RepeatFlag=0;

return 1;

}

return 0;

}


/**

  * @brief  红外遥控获取收到的地址数据

  * @param  无

  * @retval 收到的地址数据

  */

unsigned char IR_GetAddress(void)

{

return IR_Address;

}


/**

  * @brief  红外遥控获取收到的命令数据

  * @param  无

  * @retval 收到的命令数据

  */

unsigned char IR_GetCommand(void)

{

return IR_Command;

}


//外部中断0中断函数,下降沿触发执行

void Int0_Routine(void) interrupt 0

{

if(IR_State==0) //状态0,空闲状态

{

Timer0_SetCounter(0); //定时计数器清0

Timer0_Run(1); //定时器启动

IR_State=1; //置状态为1

}

else if(IR_State==1) //状态1,等待Start信号或Repeat信号

{

IR_Time=Timer0_GetCounter(); //获取上一次中断到此次中断的时间

Timer0_SetCounter(0); //定时计数器清0

//如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)

if(IR_Time>12442-500 && IR_Time<12442+500)

{

IR_State=2; //置状态为2

}

//如果计时为11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)

else if(IR_Time>10368-500 && IR_Time<10368+500)

{

IR_RepeatFlag=1; //置收到连发帧标志位为1

Timer0_Run(0); //定时器停止

IR_State=0; //置状态为0

}

else //接收出错

{

IR_State=1; //置状态为1

}

}

else if(IR_State==2) //状态2,接收数据

{

IR_Time=Timer0_GetCounter(); //获取上一次中断到此次中断的时间

Timer0_SetCounter(0); //定时计数器清0

//如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)

if(IR_Time>1032-500 && IR_Time<1032+500)

{

IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8)); //数据对应位清0

IR_pData++; //数据位置指针自增

}

//如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)

else if(IR_Time>2074-500 && IR_Time<2074+500)

{

IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8)); //数据对应位置1

IR_pData++; //数据位置指针自增

}

else //接收出错

{

IR_pData=0; //数据位置指针清0

IR_State=1; //置状态为1

}

if(IR_pData>=32) //如果接收到了32位数据

{

IR_pData=0; //数据位置指针清0

if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3])) //数据验证

{

IR_Address=IR_Data[0]; //转存数据

IR_Command=IR_Data[2];

IR_DataFlag=1; //置收到连发帧标志位为1

}

Timer0_Run(0); //定时器停止

IR_State=0; //置状态为0

}

}

}

IR.h


#ifndef __IR_H__

#define __IR_H__


#define IR_POWER 0x45

#define IR_MODE 0x46

#define IR_MUTE 0x47

#define IR_START_STOP 0x44

#define IR_PREVIOUS 0x40

#define IR_NEXT 0x43

#define IR_EQ 0x07

#define IR_VOL_MINUS 0x15

#define IR_VOL_ADD 0x09

#define IR_0 0x16

#define IR_RPT 0x19

#define IR_USD 0x0D

#define IR_1 0x0C

#define IR_2 0x18

#define IR_3 0x5E

#define IR_4 0x08

#define IR_5 0x1C

#define IR_6 0x5A

#define IR_7 0x42

#define IR_8 0x52

#define IR_9 0x4A


void IR_Init();


unsigned char IR_GetDataFlag();


unsigned char IR_GetRepeatFlag();


unsigned char IR_GetAddress();


unsigned char IR_GetCommand();


#endif

main.c


#include

#include 'Delay.h'

#include 'LCD1602.h'

#include 'Timer0.h'

#include 'IR.h'


unsigned char Num;

unsigned char Address;

unsigned char Command;


void main()

{

LCD_Init();

IR_Init();

LCD_ShowString(1,1,'ADDR  CMD  NUM');

LCD_ShowString(2,1,'00    00   00');

P2=0xFF;

while(1)

{

if(IR_GetDataFlag() || IR_GetRepeatFlag())

{

Address=IR_GetAddress();

Command=IR_GetCommand();

LCD_ShowHexNum(2,1,Address,2);

LCD_ShowHexNum(2,7,Command,2);

if(Command==IR_VOL_MINUS)

{

Num--;

}

if(Command==IR_VOL_ADD)

{

Num++;

}

LCD_ShowNum(2,12,Num,3);

}

}

}


运行效果

VID_20231130_142656

红外遥控电机调速

Motor.c


#include

#include 'Timer1.h'


sbit Motor=P1^0;


unsigned char Counter,Compare;


void Motor_Init()

{

Timer1_Init();

}


void Motor_SetSpeed(unsigned char Speed)

{

Compare=Speed;

}


void Timer1_Routine() interrupt 3

{

TL1 = 0x9C; //设置定时初始值

TH1 = 0xFF; //设置定时初始值

Counter++;

Counter%=100;

if(Counter {

Motor=1;

}

else

{

Motor=0;

}

}

Motor.h


#ifndef __MOTOR_H__

#define __MOTOR_H__


void Motor_Init();

void Motor_SetSpeed(unsigned char Speed);


#endif

Timer1.c


#include


/**

* @brief 定时器1初始化,100微秒@12.000MHz

  * @param 无

  * @retval 无

  */

void Timer1_Init(void)

{

TMOD &= 0x0F; //设置定时器模式

TMOD |= 0x10; //设置定时器模式

TL1 = 0x9C; //设置定时初始值

TH1 = 0xFF; //设置定时初始值

TF1 = 0; //清除TF0标志

TR1 = 1; //定时器0开始计时

ET1=1;

EA=1;

PT1=0;

}


/* 定时器中断函数模板

void Timer1_Routine() interrupt 3

{

static unsigned int T1Count;

TL1 = 0x9C; //设置定时初始值

TH1 = 0xFF; //设置定时初始值

T1Count++;

if(T1Count>=1000)

{

T1Count=0;

}

}

*/

Timer1.h


#ifndef __TIMER1_H__

#define __TIMER1_H__


void Timer1_Init(void);


#endif

main.c


#include

#include 'Delay.h'

#include 'Nixie.h'

#include 'Motor.h'

#include 'IR.h'


unsigned char Command,Speed;


void main()

{

Motor_Init();

IR_Init();

while(1)

{

if(IR_GetDataFlag())

{

Command=IR_GetCommand();

switch(Command)

{

case IR_0:Motor_SetSpeed(0);Speed=0;break;

case IR_1:Motor_SetSpeed(50);Speed=1;break;

case IR_2:Motor_SetSpeed(75);Speed=2;break;

case IR_3:Motor_SetSpeed(100);Speed=3;break;

}

}

Nixie(1,Speed);

}

}


进入单片机查看更多内容>>

上一篇:20_ADDA

下一篇:51单片机编程模块

相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 设计汽车集群电源

  • 6晶体管H桥

  • 温度控制风扇

  • USB LED调光器

  • AVR PC步进电机驱动器

  • AVR温度计TCN75

    相关电子头条文章