1,使用定时中断、外部中断,解码红外;
2,红外接收管正对着发射管时,程序正常;
3,红外接收管偏离发射管时(临界状态),CPU会自动复位重启,串口检测到“s”字符、pass_lamp = 0亮(已按按钮,进入while循环);
4,看门狗已关闭;
5,各位请帮忙看看,是怎么回事???(外部频繁触发中断会导至CPU复位????)
文件1:
#include <reg52.h>
#include <absacc.h>
#include <math.h>
#include "system.h"
#include "command.h"
#include "delay.h"
#define Uchar unsigned char
#define Uint unsigned int
#define Ulong unsigned long
sfr WDT_CONTR = 0xE1;
Uchar Uart_Buffer[8]; //串口接收数据缓存
Uchar RI_NUM = 0; //接收字符计数器
bit Uart_Receive_Flag = 0; //串口接收到数据标志
bit RI_String_Start = 0;
bit Dispose_String_End = 0;
bit RI_Start = 0;
#define char_Start 64 //'@' 40H
#define char_End 10 //'LF' 0AH
Uint
timer_1 = 0;
Uint timer_2 = 0;
char irtime = 0;
unsigned char irpro_ok,irok = 0;
unsigned char irdata[33]; //33个高低电平的时间数据
unsigned char IRcord[4]; //处理后的红外码,分别是 客户码,客户码,数据码,数据码反码
bit timerout_enable = 0;
bit flag_0 = 0;
bit flag_1 = 0;
bit flag_2 = 0;
bit flag_3 = 0;
bit flag_4 = 0;
void sys_init(void)
{
//WDT_CONTR = 0x3C; //11.0592M,溢出时间1.1377S,开启看门狗、使能重新计数、使能空闲计时模式、32预分频,使能看门狗,看门狗溢出时间11.38ms
PCON = 0x80; //串口通讯波特率加倍,为定时器1溢出率/16
SCON = 0x50; //串口工作方式1 ( 1位起始位0,8位数据位,1位停止位1 ),使能接收允许
//波特率=2^smod*定时器1的溢出率/32
TMOD = 0x21; //T1为定时器方式2,8位自动重装,T0为定时器方式1,16位定时,定时/计数器工作于定时方式
TH1 = BAUD_9600;//256 - (OSC_FREQ/192L)/9600L //256-Fosc(SMOD+1)/(384*baud)
TL1 = TH1; //定时器1计数初值
TR1 = 1; //波特率发生器,定时器1开启
ET0 = 1; //定时器0中断使能
// TH0 = 0xFF;
// TL0 = 0xA4; //(100us)定时器0初值=65535+1-计数值 //计数值=(定时时间*晶振*1000*1000)/12
// TH0 = 0xFF;
// TL0 = 0x48; //200us
TH0 = 0xFF;
TL0 = 0x1A; //250us定时
//TH0 = Timer0_Reload / 256;
//TL0 = Timer0_Reload % 256;
TR0 = 1; //定时器0开启
TI = 0; //串口发送中断请求标志位
RI = 0; //串口接收中断标志
//ES = 1; //串口中断使能
//PS = 1; //串口中断设置为高优先级
EA = 1; //CPU中断使能开启
//EX0 = 1; //外部中断0使能
IT0 = 1; //下降沿触发外部中断0
}
void Ircordpro(void)//红外码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;
k=1; //(me:屏蔽引导码时间,从用户码开始)
for(i=0;i<1;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
cord=irdata[k];
if(cord>7) //大于某值(1.8ms)为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
{
value=value|0x01;
}
else
{
value=value;
}
if(j<8)
{
value=value<<1;
}
k++;
}
IRcord[i]=value; //IRcord[i]为波形值(me)
value=0;
} irpro_ok = 1;//处理完毕标志位置1
}
void main()
{
sys_init();
send_char('s');
pass_lamp = 0;
//WDT_CONTR = 0x3C;
while(1) //主循环
{
out_3 = 1;
if( !start_SW ) //启动按钮
{
pass_lamp = 1;
fail_lamp = 0;
}
}
}
文件2:
#include <string.h>
#include <stdio.h>
#include <absacc.h>
#include <intrins.h>
#include <reg52.h>
#include "reg52.h"
#include "command.h"
#include "delay.h"
#include "absacc.h"
#define Uchar unsigned char
#define Uint unsigned int
#define Ulong unsigned long
//sfr WDT_CONTR = 0xE1;
//send_char:直接发送字符函数
void send_char ( char s_data )
{
SBUF = s_data;
while( TI==0 )
;
TI=0;
}
extern bit timerout_enable;
extern Uint timer_1;
extern Uint timer_2;
#define ONE_SEC 4000
unsigned int run_timer = 0;
extern Uint timer_1;
extern Uint timer_2;
extern char irtime;
extern char irok;
extern unsigned char irdata[33]; //33个高低电平的时间数据
void TimeOut_ISR (void) interrupt 1 using 3 //12*(0xFFFF+1-0xFFA4)/11059200=250us
{
//TR0 = 0; //关闭Timer0
// TH0 = Timer0_Reload / 256;
// TL0 = Timer0_Reload % 256;
TH0 = 0xFF;
TL0 = 0x1A;
//TR0 = 1; //开启Timer0
//WDT_CONTR = 0x3C; //11.0592M,568.6ms溢出
run_timer ++;
timer_1 ++;
timer_2 ++;
irtime ++;
if( run_timer >= ONE_SEC ) //1秒闭烁
{
run_timer = 0;
LED_RUN = !LED_RUN;
}
EX0 = 1; //外部中断0使能
}
void Ext0(void) interrupt 0
{
static unsigned char i; //接收红外信号处理
EX0 = 0; //外部中断0关闭
out_3 = 0;
if(irtime<60&&irtime>=44) //引导码 TC9012的头码,9ms+4.5ms //(me:检测两次中断触发的时间250us)
i = 0;
irdata[i]=irtime; //存储每个电平的持续时间,用于以后判断是0还是1
irtime = 0;
i++;
if( i==9 ) //(me:引导码+用户码+用户码+数据码+数据码)
{
irok=1;
}
}
其它头文件:
#ifndef __SYSTEM_H__
#define __SYSTEM_H__
#ifdef __cplusplus //如果是C++编译器,就使用该定义
extern "C" //强制使用C方式编译以下函数
{
#endif
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define MAIN_Fosc 11059200L //晶振
#define Timer_0 250 //定时器0定时时间,us
#define freq_base (MAIN_Fosc / 1200)
#define Timer0_Reload ( 65536 - (Timer_0 * freq_base / 10000)) //定时器0计数初值
sbit LED_RUN = P2^7; //CPU运行指示灯
sbit start_SW = P1^0; //IN0
sbit switch_1 = P1^1; //IN1
sbit switch_2 = P1^2; //IN2
sbit switch_3 = P1^3; //IN3
sbit pass_lamp = P2^5; //OUT0
sbit fail_lamp = P2^4; //OUT1
sbit buzzer = P3^5; //OUT2
sbit out_3 = P3^4; //OUT3
一周热门 更多>