文档库 最新最全的文档下载
当前位置:文档库 › STM8例程—红外解码(使用16位定时器)

STM8例程—红外解码(使用16位定时器)

/************************广东工业大学电子科技协会******************** *
* 名称:红外解码 *
作者:宇辰_hong *
* 内容:红外解码,采用16位定时器 *
---------------------------------------------------------------*/
#include
#define uchar unsigned char
#define uint unsigned int
#define IR_IN PD_IDR_IDR3

uchar IR_Start=0,IR_Num,Sign_Data_Ok=0;
unsigned long IR_data;
uint IR_Time;
uchar disp[8];
uchar table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

void delay(uchar a);
void STM8_Init(void);
void Time3_Init(void);
void Display(void);
void main( void )
{
STM8_Init();
Time3_Init();
asm("RIM");
while(1)
{
Display();
}
}

void delay(uchar a)
{
uchar i;
while(a--)
for(i=0;i<120;i++);

}

void Display(void)
{
uchar i;
uint IR_data_H16,IR_data_L16;

if(Sign_Data_Ok==1) //为了保证显示的数据的有效性,等到数据转换完毕标志置位后才进行数据转换
{
IR_data_H16=IR_data>>16; //分离数据低16位
IR_data_L16=(IR_data<<16)>>16; //分离数据高16位

disp[0]=(IR_data_L16&0x00ff)%16;
disp[1]=(IR_data_L16&0x00ff)/16;

disp[2]=(IR_data_L16>>8)%16;
disp[3]=IR_data_L16>>12;

disp[4]=(IR_data_H16&0x00ff)%16;
disp[5]=(IR_data_H16&0x00ff)/16;

disp[6]=(IR_data_H16>>8)%16;
disp[7]=IR_data_H16>>12; //以上语句进行数据转换
Sign_Data_Ok=0; //转换结束后将数据接收完成标志清零
}
for(i=0;i<8;i++) //显示
{
PB_ODR=table[disp[i]];
PD_ODR=i;
delay(1);
}
}

void STM8_Init(void)
{
PD_DDR_DDR3=0;
PD_CR1|=0x08;
PD_CR2|=0x08; //带中断的浮空输入

PB_DDR=0xff;
PB_CR1=0xff;
PB_CR2=0x00;

PD_DDR|=0x07;
PD_CR1|=0x07;
PD_CR2|=0x00;

EXTI_CR1_PDIS=2; //下降沿触发
}

void Time3_Init(void)
{
TIM3_PSCR_PSC=1; //1MHz,计数器为1时定时时间约1us
TIM3_ARRH=0xff;
TIM3_ARRL=0xff; //自动重装为10000保证正常接收过程中不会溢出
TIM3_EGR_UG=1; //重新初始化寄存器
}


#pragma vector=8
__interrupt void EXTI3_IR_Handle(void)
{
uchar IR_Time_H,IR_Time_L;
uint IR_Time;
TIM3_CR1_CEN=0; //读数据之前先停止计数器
IR_Time_H=TIM3_CNTRH;
IR_Time_L=TIM3_CNTRL; //读计数器的值
IR_Time=IR_Time_H*256+IR_Time_L; //数据转换


TIM3_CNTRH=0;
TIM3_CNTRL=0; //清零计数器,以计算两次进入中断的时间
TIM3_CR1_CEN=1; //启动计数器

if(IR_Time>11000) //如果时间间隔大于11ms,说明接收到启动码
{
IR_Start=1; //启动标志置一
IR_Num=0; //清零IR_Num,保证数据的准确性,该语句可以保证不会因为接收到部分数据而
} //导致数据不准确,原理是启动后必须接收到全部数据,数据才有效
if(IR_Time<1050) //数据时间间隔大余1.05ms,故不在这个范围则说明不是数据,则返回
return;
if((IR_Start==1)&&IR_Time<2600) //如果已经收到启动代码,且数据在有效范围内
{
IR_data<<=1; //因为先发地址高位,所以要向右移动
if(IR_Time>1700) //如果数据间隔大于数据0和数据1中间数值,则认为收到数据1
IR_data|=1;
IR_Num++; //收到一位后IR_Num加1
if(IR_Num>31) //如果IR_Num>31,即等于32(为保证可靠,用大于)时,说明数据已经收完
{
Sign_Data_Ok=1; //数据收完后接收结束标志置位
IR_Start=0; //启动标志清零 //
TIM3_CR1_CEN=0; //收到全部数据后关闭定时器,可节能,也避免出错
}
}
}

相关文档