发 帖  
原厂入驻New
[问答] STC单片机使用外部中断解码红外,为什么CPU会自动复位重启?
785 单片机 cpu
分享
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
0
2019-1-9 08:00:00   评论 分享淘帖 邀请回答

相关问题

3个回答
2019-1-9 10:49:42 评论

举报

2019-1-9 11:20:29 评论

举报

2019-1-9 11:21:06 评论

举报

撰写答案

你正在撰写答案

如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。

高级模式
您需要登录后才可以回帖 登录 | 注册

我要提问
关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表