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的晶振
#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前面我的计数器不清零(但是读数上肯定就有变化了)求解……