一直用的STM8S003的单片机,后来价格涨到三块多不得不换。拿上新塘N76E003芯片,资源中规中矩,相比用习惯Cortex® M 内核微控制器和STM8,用这个芯片资源就有些少了,先来个简单的红外遥控解码。(打算用外部IO中断来触发解码的,调试时发现会无规律的触发IO中断,只得用IO扫描方式去解红外遥控信号。)
以日本NEC的编码协议组成: 引导码,16bit用户码(地址码),8bit命令码(功能码)及其反码
1、引导码由一个9ms的载波波形和4.5ms的关断时间构成(9ms低电平+4.5ms高电平)。
2、地址码共16bit(8位系统码和8位系统反码),低位在前,高位在后。
遥控码特征:
采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”。0与1前端的低电平持续都是0.56ms,那么就是后面的高电平持续时间不同,0为0.56ms,1为1.685ms。
程序有个问题:数据接收方向当时搞反了,接收回来的数据刚好是高低位位置互换,不影响使用就没去改。
//-----------------my_IR.c------------------------------------------------------------
#include "my_IR.h"
/*------------------------------------------------------
NEC协议红外遥控解码
计数使用资源:Timer0
由于设定Timer0定时值,计算出来的值不正确,
超时在Timer3中断里处理
--------------------------------------------------------*/
#define REMOTE_ID 0x0
sbit IR_IO=P0^0;
bit bIR_scan=0;
bit bIR=0;
UINT8 IR_cont=0;
UINT8 IR_code=0; //遥控按键值
//-----------------------------------------------
UINT16 Dval; //计数器的值
unsigned long RmtRec=0; //接收到的数据
uint16_t TIM0_GetCounter(void)
{
uint16_t tmpcntr = 0;
tmpcntr = ((uint16_t)TH0 << 8);
tmpcntr = tmpcntr| (uint16_t)(TL0);
return ((uint16_t)tmpcntr*0.75);
}
UINT8 IR_SCAN(void)
{
UINT8 i=0;
UINT8 t1,t2;
if(bIR_scan==0) return 0;
bIR_scan=0;
RmtRec=0;
if(IR_IO==0)
{
clr_TR0;
clr_TF0;
TL0 =0;
TH0 =0;
set_TR0; //Start Timer0
bIR=0;IR_cont=0;
while ((IR_IO==0)&&(bIR != 1)); //Check Timer0 Time-Out Flag
clr_TR0; //Stop Timer0
clr_TF0;
Dval=TIM0_GetCounter();
if(Dval>8600&&Dval<9300) //9ms
{
TL0 =0;
TH0 =0;
set_TR0; //Start Timer0
bIR=0;IR_cont=0;
while ((IR_IO==1)&&(bIR != 1)); //Check Timer0 Time-Out Flag
clr_TR0; //Stop Timer0
clr_TF0;
Dval=TIM0_GetCounter();
if(Dval>4200&&Dval<4700) //4.5ms
{
//----------------------------------------------------------
do{
TL0 =0;
TH0 =0;
set_TR0; //Start Timer0
bIR=0;IR_cont=0;
while ((IR_IO==0)&&(bIR != 1)); //Check Timer0 Time-Out Flag
clr_TR0; //Stop Timer0
clr_TF0;
Dval=TIM0_GetCounter();
if(Dval<300&&Dval>800) //560us
{
return 0;
}
TL0 =0;
TH0 =0;
set_TR0; //Start Timer0
bIR=0;IR_cont=0;
while ((IR_IO==1)&&(bIR != 1)); //Check Timer0 Time-Out Flag
clr_TR0; //Stop Timer0
clr_TF0;
Dval=TIM0_GetCounter();
if(Dval>300&&Dval<800) //560为标准值,560us
{
RmtRec<<=1;
RmtRec|=0; //接收到0
i++;
}else if(Dval>1400&&Dval<1800) //1680为标准值,1680us
{
RmtRec<<=1;
RmtRec|=1; //接收到1
i++;
}
else if(Dval>2200&&Dval<2600) //得到按键键值增加的信息 2500为标准值2.5ms
{
}
}while(i<32);
//--------------------------------------------------------------------
t1=RmtRec>>24; //得到地址码
t2=(RmtRec>>16)&0xff; //得到地址反码
if((t1==(UINT8)~t2)&&t1==REMOTE_ID)//检验遥控识别码(ID)及地址
{
t1=RmtRec>>8;
t2=RmtRec;
IR_code=t1;
if(t1==(UINT8)~t2)return 1;//键值正确
}
//---------------------------------------------------------------------
}
}
}
return 0;
}
void my_IR_Init(void)
{
P00_Input_Mode;
clr_T0M; //T0M=0, Timer0 Clock = Fsys/12
TMOD |= 0x01; //Timer0 is 16-bit mode
set_TR0; //Start Timer0
TL0 =LOBYTE(TIMER_DIV12_VALUE_40ms); //Find define in "Function_define.h" "TIMER VALUE"
TH0 =HIBYTE(TIMER_DIV12_VALUE_40ms);
//clr_TR0; //Stop Timer0
}
//-----------------my_IR.c------------------------------------------------------------
#ifndef __MY_IR_H
#define __MY_IR_H
#include "n76e003.h"
//
extern bit bIR_scan;
extern bit bIR;
extern UINT8 IR_cont;
extern UINT8 IR_code;
void my_IR_Init(void);
UINT8 IR_SCAN(void);
#endif /*__MY_IR_H*/
上一篇:单片机 温度调控 大功率设备调整PWM输出
下一篇:ZigBee-CC2530单片机 - LED呼吸灯
推荐阅读最新更新时间:2024-11-01 21:45