微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机在下降沿来之前提前触发外部中断

51单片机在下降沿来之前提前触发外部中断

时间:10-02 整理:3721RD 点击:
   #include <reg52.h>
   #include <absacc.h>
   #include <intrins.h>
   #define u3 XBYTE[0xfdf3]   //通过A0、A1,写控制字
   #define wru3_y XBYTE[0xfdf0]   //通过A0、A1,确认读写计数器0
   #define wru3_j XBYTE[0xfdf1]   //通过A0、A1,确认读写计数器1
   void send2(void);
   void atc89c51_init(void);
   void AT82c54a_init(void);
   unsigned int caprute_jin();
   unsigned int caprute_yuan();
   sbit H=P1^1;
   sbit G=P1^2;
   sbit CT=P1^3;
   sbit gate0=P1^4;
   sbit gate1=P1^5;

///////////////////////////////////////////////////

/////////// ======M8254(U3)初始化
   void AT82c54a_init(void)
{
        u3=0x74;          //写控制字01110100,选计数器1,2次读写操作,方式2,2进制数
        wru3_j=0x00;     //赋初值
    _nop_();
        wru3_j=0x00;
        u3=0x34;          //写控制字00110100,选计数器0,2次读写操作,方式2,2进制数
        wru3_y=0x00;     //赋初值
    _nop_();
        wru3_y=0x00;

        u3=0xb4;       //写控制字10110100,选计数器2,2次读写操作,方式2,2进制数
        wrvr=0x00;       //赋初值
        _nop_();
        wrvr=0x00;
       
}

///////// ======M8254(U6)初始化
   void AT82c54b_init(void)
{
        u6=0x34;           //写控制字00110100,选计数器0,2次读写操作,方式2,2进制数
            _nop_();
        wrjw=0x00;           //赋初值
            _nop_();
        wrjw=0x00;           //赋初值
            _nop_();
        u6=0x74;           //写控制字01110100,选计数器1,2次读写操作,方式2,2进制数
            _nop_();
        wrxv=0x00;
            _nop_();
        wrxv=0x00;
            _nop_();
}
//////////////===89c51初始化
   void atc89c51_init(void)
{
TCON=0x05;
TMOD=0x21;
SCON=0x50;
PCON=0x00;
TH1=0xFD;
TR1=1;
ET1=0;
TR0=1;
ET0=1;
TH0=0xb8;
TL0=0x00;
ES=1;
   gate0=1;
   gate1=1;
  EA=1;
}


//======================
  unsigned int caprute_yuan()
{
  unsigned int dl;
  unsigned int dh;
  unsigned int a;
  u3=0x34;          //写控制字00110100,选计数器0,2次读写操作,方式2,2进制数
    _nop_();
  dl=wru3_y;
    _nop_();
  dh=wru3_y;
    _nop_();
  a=((dh&0x00ff)<<8)+(dl&0x00ff);        //16进制数
  a=65536-a;                        //递减计数需要求得最终值
        u3=0x34;          //写控制字00110100,选计数器0,2次读写操作,方式2,2进制数
        wru3_y=0x00;     //赋初值
    _nop_();
        wru3_y=0x00;
  return a;                                //a为caprute()_y的值
}

//==========================
  unsigned int caprute_jin()
{
  unsigned int dl;
  unsigned int dh;
  unsigned int a;
          u3=0x74;          //写控制字01110100,选计数器1,2次读写操作,方式2,2进制数
        dl=wru3_j;     //赋值
    _nop_();
        dh=wru3_j;
  a=((dh&0x00ff)<<8)+(dl&0x00ff);        //16进制数
  a=65536-a;                        //递减计数需要求得最终值
        u3=0x74;          //写控制字01110100,选计数器1,2次读写操作,方式2,2进制数
        wru3_j=0x00;     //赋值
    _nop_();
        wru3_j=0x00;
  return a;                                //a为caprute()_j的值
}

///////============外部中断0========
void ISR0(void) interrupt 0
{
  gate0=0;   /////关远接收门信号
  EX0=0;
  H=1;   ///远近接收外部触发中断完成标志
  IE0=0;
}

///////===============外部中断1========
void ISR1(void)interrupt 2
{
gate1=0;  //////关近接收门信号
EX1=0;          //近接收外部中断禁止
EX0=1;    //远接收外部中断允许
  delay10us();
  wru_sf=0x20;
  sf=wru_sf;
IE1=0;
}


///////////////////////////////////////////////
   void zhongduan(void) interrupt 1
   {
          bingo++;
  if (bingo==2)
  {

        CT=1;
        gate0=1;
        gate1=1;  //开门信号
        _nop_();

        CT=0;         //CT触发信号拉低
       
        delay50us();
        EX0=0;   //远接收中断禁止
    EX1=1;          //近接收中断允许
  }
        if (bingo==5)
        {
        c=1;
        bingo=0;
        }

   TL0= 0x00;
   TH0= 0xb8;                 //T0_20ms赋值
   }
                 
///////////////////////////////////////////////////
////////////////////////////////////////////
void main(void)
{
   atc89c51_init();
   AT82c54a_init();
   AT82c54b_init();
   delay1s();
//   H=0;                        //声波执行判定标志

while(1)
{


if (H==1)
{
count_yuan=caprute_yuan();
yuanh4=(count_yuan>>8);
yuanl8=(count_yuan&0xff);
count_jin=caprute_jin();
jinh4=(count_jin>>8);
jinl8=(count_jin&0xff);
shicha=(count_yuan-count_jin);
sch4=shicha>>8;
scl8=shicha&0xff;
H=0;
}
if (c==1)
{
avg_vr();
count_xv=caprute_xv();
xv_h4=(count_xv>>8);
xv_l8=(count_xv&0xff);
count_jw=caprute_jw();
jw_h4=(count_jw>>8);
jw_l8=(count_jw&0xff);

         send2();
  c=0;
}
}
}
从示波器上可以看到,我的关门信号gate0、gate1在外部中断触发下降沿到来之前几十微妙就自己置零了,我用的C52芯片,11.059M的晶振

再仔细看看数据手册的控制时序把,我是搭建外围电路实现的

我再补充说明下,首先,CT是个触发信号,然后,在50US以后的样子,外部INT0和INT1接收的信号才是能用的信号(当然,这俩信号都是用比较器处理后的方波信号,但用示波器可以看到,下降沿的先后顺序是一定是先INT1,后INT0),其次,硬件上应该没有问题,因为我师父用汇编写的程序已经求证通过了,最后,我这边,主要靠TO定时20ms,每5次即100ms采俩个外部中断信号分别一次。不知道各位大神有什么高见,我这次也是现学现卖,还有很多不大明白的地方,希望各位大神解惑,谢谢。

这个问题我找到了,在关中断的时候接收端仍然有抖动,在中断结束前手动关闭IE0和IE1就好了。

但是还有个问题想接着请教一下,为什么加上(读AD)
wru_sf=0x20;
  sf=wru_sf;
这么俩句后,我跟INT1中断有关的8254计数器被清零了?
我AD和8254的片选地址不一样啊,而且门信号gate1置零后,计数器计得的读数不是应该保存在里面吗?
AD那一块我是这么定义的#define wru_sf XBYTE[0xfeff]
AD和8254计数器的WR和RD我都挂在单片机上了,不明白为什么把这俩句丢在gate1=0前面我的计数器不清零(但是读数上肯定就有变化了)求解……

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top