专门做娱乐场所的设计网站,蓝衫网站建设,网站制作手机端,网站代码是什么意思需要利用下面这个红外接收头#xff0c;OUT口会发出红外信号对应的高低电平#xff0c;由于发送的速度很快#xff0c;所以需要把OUT引脚接在外部中断引脚上#xff0c;当OUT一旦产生下降沿#xff0c;马上进中断#xff0c;这样响应会更及时。 外部中断引脚位于P3_2和P… 需要利用下面这个红外接收头OUT口会发出红外信号对应的高低电平由于发送的速度很快所以需要把OUT引脚接在外部中断引脚上当OUT一旦产生下降沿马上进中断这样响应会更及时。 外部中断引脚位于P3_2和P3_3我的开发板把OUT接在了P3_2利用的是下降沿触发。 外部中断比定时器中断和串口中断要简洁一些这里使用外部中断0Int0当IT01就是下降沿触发IT00就是低电平触发。 IE0为中断标志位EX0为此中断的使能EA为所有中断的使能PX0设置优先级。 外部中断1Int1也是同理。 图中红框框出的才是控制外部中断的。 首先来配置外部中断
void Int0_Init(void)
{//配置外部中断IT0 1; //选择下降沿触发IE0 0; //中断标志位EX0 1; //外部中断0使能EA 1; //中断使能PX0 1; //优先级
}/* brief 外部中断函数
void Int0_Routine(void) interrupt 0
{}
*/高低电平的组合、持续时长构成了NEC编码下面的波形就是OUT口会输出的波形。 Data中的反码可以进行数据验证。 在遥控器上按下一个按键之后先发送一个start波形然后发送Data如果按住按键一直不放手每过110ms就会发送一次repeat相当于连续按键功能。 这里遥控器按键的命令码如下 接下来编写红外解码的程序主要的思路是 建立一个IR.c红外解码模块这个模块中利用Int0.c和Timer0.c来进行解码。 具体的解码方式 首先定义一个变量表示当前的状态用0来表示空闲状态当收到下降沿时转为1状态1状态定义为分辨是start还是repeat并将定时器打开当1状态又收到一个下降沿时读出定时器的时长判断是start还是repeat。 如果判断为start转为2状态2状态定义为开始解码32bit的Data2状态会执行32次数据读完之后回到0状态 如果判断为repeat则把重发标志位的变量置1并转回0状态 所以首先要对之前写的Timer0模块进行一些改写。这次的目的不是让定时器计数进中断了而是让它单纯的计时下面就是改写后的Timer0.c可以设定计时器的初始值返回计时器的实时值以及控制计时器的开关计时器的返回值每多1就代表多走过了1us
#include REGX52.Hvoid Timer0_Init(void) //1毫秒11.0592MHz
{TMOD 0xF0; //设置定时器模式TMOD | 0x01; //设置定时器模式TL0 0x66; //设置定时初值TH0 0xFC; //设置定时初值TF0 0; //清除TF0标志TR0 0; //定时器0不计时
}//把16位值放入计数器
void Timer0_SetCounter(unsigned int Value)
{TH0 Value/256;TL0 Value%256;
}//返回计数器的值
unsigned int Timer0_GetCounter(void)
{return (TH08) | TL0;
}//选择计时器是否启动Flag为1则启动
void Timer0_Run(unsigned char Flag)
{TR0 Flag;
}接下来就可以编写IR.c了要注意IR.c中包含了Int0的外部中断函数 参考之前说的具体的解码方式 首先定义一个变量表示当前的状态用0来表示空闲状态当收到下降沿时转为1状态1状态定义为分辨是start还是repeat并将定时器打开当1状态又收到一个下降沿时读出定时器的时长判断是start还是repeat。 如果判断为start转为2状态2状态定义为开始解码32bit的Data2状态会执行32次数据读完之后回到0状态 如果判断为repeat则把重发标志位的变量置1并转回0状态
#include REGX52.H
#include Timer0.h
#include Int0.hunsigned int IR_Time; //计时时长
unsigned char IR_State; //状态unsigned char IR_Data[4]; //分别表示Data的四个字节
unsigned char IR_pData; //代表每个个字节的对应位 0~31unsigned 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;}else return 0;
}unsigned char IR_GetRepeatFlag(void)
{if(IR_RepeatFlag){IR_RepeatFlag 0;return 1;}else return 0;
}unsigned char IR_GetAddress(void)
{return IR_Address;
}unsigned char IR_GetCommand(void)
{return IR_Command;
}void Int0_Routine(void) interrupt 0
{if(IR_State 0) //空闲{Timer0_SetCounter(0);Timer0_Run(1);IR_State 1;}else if(IR_State 1) //判断是start/repeat{IR_Time Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time 13500-500 IR_Time 13500500){//startIR_State 2;}else if(IR_Time 11250-500 IR_Time 11250500){//repeatIR_RepeatFlag 1;Timer0_Run(0);IR_State 0;}}else if(IR_State 2) //读取Data{IR_Time Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time 1120-500 IR_Time 1120500){//对应位为0IR_Data[(IR_pData/8)] ~(0x01(IR_pData%8));IR_pData ;}else if(IR_Time 2250-500 IR_Time 2250500){//对应位为1IR_Data[IR_pData/8] | (0x01(IR_pData%8));IR_pData ;}else{//接收到错误信号则重新接收IR_pData 0;IR_State 1;}if(IR_pData 32){//Data已收完IR_pData 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;}Timer0_Run(0);IR_State 0;}}}Command和Address要想在main中调用就得封装成相应的Get函数然后对应红外遥控器按键的键码可以用宏定义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 0x4Avoid IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);#endif最后在main.c中调用这些函数即可
#include REGX52.H
#include Delay.h
#include LCD1602.h
#include IR.hunsigned char Num;
unsigned char Address, 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()){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);}}
}