微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 单片机中断问题30例

单片机中断问题30例

时间:05-07 来源:互联网 点击:

#include

sbit m=P2^0;

sbit b=P2^6;

sbit y=P2^7;

unsigned char count;

void main()

{

TMOD=0x01;

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

TR0=1;

count=0;

m=!0;

b=!1;

y=!0;

while(1) {

if(TF0==1) {

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

TF0=0;

count++;

if(count==20) {

m=0; b=1; y=0;

}

if(count==40) {

count=0; //加上这句.

m=!0; b=!1; y=!0;

}

}

}

}!

用T0定时50ms,溢出20次,溢出40次,分别代表了具体的时间。 溢出40次之后,应该从头开始统计溢出次数,所以,此处应该有count=0;。 楼主原来的程序,缺少count=0;,那么它就会继续增加,直到65536,才自动回到0。 这样,时间,就难以控制了。

11、求助关于51单片机外部中断的问题,小弟最近在学单片机,刚做了一个键盘扫描程序。发现如果外部中断为电平触发,程序能正常运行。但如果改为边沿触发,在将键值送给显示重开中断指令为EX0=1后,中断竟然还会被触发一次,这之后,再按键就不能触发中断了。如果将中断程序中关中断语句去掉,按键能被扫描,但引起中断的次数不好说了。请大侠们看看哪出问题了。谢谢

uchar keynum,//定义全局变量按键时的键值

dpnum,//显示值

time1,//延时计数值

topen,//延时计数控制

keyin;//外部中断0向主程序传递有中断标识,有键按下

keydeal;//按键程序调用标志

uchar keytable[4][4]={7,8,9,'/',4,5,6,'*',1,2,3,'-','c',0,'=','+'};//按实际键盘编值

uchar keyboard();//键盘扫描程序,负责键值扫描,判断键释放由主函数完成

void display(uchar,uchar);// 显示子程序,

sbit keysign=P3^2;//P3.2为中断0入口,此定义用于程序判断是否真有键按下及键是否释放

void main()

{uchar keybiao,keybiao1;//有键按下标志,键放开标志

IE=0x89;//开总中断,外部中断0,定时器中断1

IT0=1;//中断触发方式

PT1=1;//中断优先级

TMOD=0x90;//定时器1工作方式1

TH1=(65536-5000)/256;//定时器初值高8位(定时5ms)

TL1=(65536-5000)%256;

TR1=1;//开始计时

P2=0xf0;//给键盘列高电平,行低电平

keydeal=0x00;//让键处理初值为0,既未处理

while(1)

{if(keyin==1) //可能有键按下

{

if(time1>=2)//已延时10ms;计数2次,

{if(keysign==0keydeal==0)

{keynum=keyboard();

keybiao=1;

keydeal=1;

topen=0;//关延时计数

}//判断是否真有键按下,调用键盘扫描程序

else if(keybiao==0time1>=2keybiao1==0)

{EX0=1;

keyin=0;

topen=0;

}//如果没键按下,重开外部中断0,中断标志清0

}

if(keybiao==1keysign!=0)

{keybiao=0;

time1=0;

keybiao1=1;//为防止前一次time1的影响而设的标志

topen=1;

}

if(keybiao1==1time1>=2)

{keybiao1=0;

topen=0;

EX0=1;

keyin=0;//重开外部中断0,中断标志清0

keydeal=0;//重开键未处理,让程序可调用处理程序

dpnum=keynum;//将键值传给显示

}

}

}

}

void display(uchar x,uchar i)//中断控制显示,显示一直持续到下次中断到

uchar keyboard()

{uchar con1,con2,i,j;

con1=P2|0x0f;//只保留P2口高四位,便于switch

switch(con1)//通过cp可得到列为0的位

{case 0x7f:j=3;break;//j为列值

case 0xbf:j=2;break;

case 0xdf:j=1;break;

case 0xef:j=0;break;

}

for(i=0;i=3;i++)

{P2=_crol_(0xfe,i);//依次给行赋0

con2=P2|0x0f;// 只保留P2口高四位,便于比较

if(con2!=0xff) break;

}

P2=0xf0;//给键盘列高电平,行低电平

return(keytable[i][j]);

}

void T1_time()interrupt 3

{TH1=(65536-5000)/256;//定时器初值高8位(定时5ms)

TL1=(65536-5000)%256;

time1++;

if(topen!=1) time1=0;//如果延时标志不为1,不开始计时

display(dpnum,5);

}

void int0()interrupt 0

{EX0=1;

keyin=1;//向主程序传递键按下

topen=1;//10ms延时计数开始

}

由于字数有限,有部分程序给删了,显示等部分程序应该没问题,我在其它地方能正常运行。

答:

不需要每次在进入中断程序后开一次中断;EX0=1可以去掉。

实际上,外部中断工作在边沿触发方式的时候,第一次电平跳变触发后进入中断程序,然后硬件自动清除IE0中断标志位。但是在执行中断程序的过程中,如果中断引脚再次检测到电平跳变(负到高),那么IE0会被再次置1 。如果在退出中断程序之前没及时清0,那么就会再次引发一次中断。

而按键的过程,不包括按下和松开时的电平抖动,至少会产生两次电平跳转。

因此,只需在你中断程序里适当加一点延迟,再将EX=1, 改成IE0=0 。

12、我用的单片机是8051F的单片机,在程序中我用了两个中断。一个是定时计数器2产生的中断100MS一次的数据采集。另一个是向上位机发送采集来的数据,使用的串口来

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

网站地图

Top