单片机中断问题30例
#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一次的数据采集。另一个是向上位机发送采集来的数据,使用的串口来
- FPGA的DSP性能揭秘(06-16)
- 基于单片机通用引脚的软件UART设计(10-16)
- 分时操作系统思想在单片机中的具体应用 (10-30)
- 基于AT89C51+DSP的双CPU伺服运动控制器的研究(05-26)
- 关于RTX51 TINY的分析与探讨(05-30)
- 基于MC9S12DGl28单片机的智能寻迹车设计(04-03)