51单片机 内部定时器中断

Tech沉思录 2018-01-21 02:26:01
想实现一个计数器,到某个时间点的时候蜂鸣器发声,LED开启流水灯,但是这个只是蜂鸣器可以,流水灯并不亮
求指教
#include <reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define led P2
uchar code TAB[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

uchar DAT[]={0,0,0,0};
uchar MIN=0,SECOND=0;
uchar t;
uchar i=0; //定义计数

sbit LSA=P2^2; //138译码器的ABC管脚
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit BUZZER=P1^5; //蜂鸣器P1.5管脚
//LED为P2口

void delay(int n); //延时子程序说明
void sound(); // 蜂鸣器子程序说明
void light(); //流水灯子程序 说明

/*-----------------------------------------------------------------------------------*/
void main() //主函数
{
EA=1; //初始化设置
ET0=1;
TMOD=0x01;
TH0=-50000/256;
TL0=-50000%256;
TR0=1;

/*-----------------------------------------------------------------------------------*/
EX0=1; //初始化中断
EX1=1;
IT0=1;
IT1=1;


/*-----------------------------------------------------------------------------------*/
while(1) //一直循环
{

for(t=0;t<=3;t++)
{
switch(t) //位选,选择点亮的数码管,
{

case(3):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(2):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(1):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(0):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
P0=TAB[DAT[t]]; //查表送到P0口
delay(250); //每一位延时一会
// P0=0x00; //消隐
}
}
}
/*-----------------------------------------------------------------------------------*/
void intserv1 (void) interrupt 1 using 1 //定时计数器T0中断服务子程序
{
TH0=-50000/256;
TL0=-50000%256;
i++;
if(i==20)
{ i=0;
SECOND++;
if(SECOND==60)
{ MIN++;
SECOND=0;
if(MIN==60)
MIN=0;
}



// DAT[0]=MIN/10; //能放在for的外面吗? 可以!
// DAT[1]=MIN%10;
// DAT[2]=SECOND/10;
// DAT[3]=SECOND%10;
}
if(MIN==0&&SECOND==11) //5MIN到了 蜂鸣器叫 流水灯发光
{ MIN=0;
SECOND=11;
sound(); //蜂鸣器发声函数
light(); //流水灯函数
TR0=0; //关定时器
}

DAT[0]=MIN/10; //能放在for的外面吗?
DAT[1]=MIN%10;
DAT[2]=SECOND/10;
DAT[3]=SECOND%10;
}
/*-----------------------------------------------------------------------------------*/
void intserv2 (void) interrupt 0 using 1 //int0中断
{MIN++;
if(MIN==60)
MIN=0;
DAT[0]=MIN/10;
DAT[1]=MIN%10;
}
/*-----------------------------------------------------------------------------------*/
void intserv3 (void) interrupt 2 using 1 //int1中断
{SECOND++;
if(SECOND==60)
{MIN++;
SECOND=0;}
DAT[2]=SECOND/10;
DAT[3]=SECOND%10;
}
/*-----------------------------------------------------------------------------------*/
void delay(int n) //延时程序
{
int i;
for(i=0;i<=n;i++);
}
/*-----------------------------------------------------------------------------------*/
void sound() //蜂鸣器子程序
{
uchar i;
while(1)
{ BUZZER=1;
for(i=0;i<=20;i++);
BUZZER=~BUZZER;
for(i=0;i<=20;i++);
}
}
/*-----------------------------------------------------------------------------------*/
void light() //流水灯子程序
{ uchar i;

led=0xfe;
delay(300);
while(1)
{
for(i=0;i<7;i++)
{
led=_crol_(led,1);
delay(300);
}
led=0xfe;
delay(300);
}
}







...全文
1014 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tech沉思录 2018-01-27
  • 打赏
  • 举报
回复
引用 15 楼 ruanle9456 的回复:
楼主问题解决了吗
你说的是哪个问题 两个都算是解决了吧
Tech沉思录 2018-01-27
  • 打赏
  • 举报
回复
引用 14 楼 LJDTJ 的回复:
引用 13 楼 suyunzzz 的回复:
[quote=引用 10 楼 LJDTJ 的回复:] 你定义的STORE[]数组的实际长度为3,而数组索引j在每次执行KEY_PRESS()函数时都会++,因此,会出现数组索引j大于3的情况,即越界访问。需要考虑对j重新计数。
这样也会影响我前三次按键吗
如果你保留对STORE[]数组的原定义,增加 if ( j >= 3 ) j = 0; 则STORE[]数组会保存你的三次按键值。 你的前三次按键显示都是错的?[/quote]对啊对啊 前三次都不对 但是我加上一个置j的语句后就可以啦
wfy1008 2018-01-27
  • 打赏
  • 举报
回复
你这个有个非常严重的问题,中断处理程序怎么都用同一个寄存器组,如果是不同中断优先级,那高优先级的中断会把低优先级中断的寄存器组里的值改写,其他的我没仔细看,这个一定要注意。51系列有4组寄存器,main()函数默认用0,其他的如果中断优先级不同的话,那么高和低优先级一定要分到两个组上,否则一定有问题。
ruanle9456 2018-01-26
  • 打赏
  • 举报
回复
楼主问题解决了吗
Tech沉思录 2018-01-24
  • 打赏
  • 举报
回复
引用 10 楼 LJDTJ 的回复:
你定义的STORE[]数组的实际长度为3,而数组索引j在每次执行KEY_PRESS()函数时都会++,因此,会出现数组索引j大于3的情况,即越界访问。需要考虑对j重新计数。
这样也会影响我前三次按键吗
Tech沉思录 2018-01-24
  • 打赏
  • 举报
回复
引用 11 楼 faihung 的回复:
楼主你上面两个函数是两个死循环,这个又不是多线程的,肯定只会跑在一个地方啊
谢谢 那个已经改正了
LJDTJ 2018-01-24
  • 打赏
  • 举报
回复
引用 13 楼 suyunzzz 的回复:
引用 10 楼 LJDTJ 的回复:
你定义的STORE[]数组的实际长度为3,而数组索引j在每次执行KEY_PRESS()函数时都会++,因此,会出现数组索引j大于3的情况,即越界访问。需要考虑对j重新计数。
这样也会影响我前三次按键吗
如果你保留对STORE[]数组的原定义,增加 if ( j >= 3 ) j = 0; 则STORE[]数组会保存你的三次按键值。 你的前三次按键显示都是错的?
Tech沉思录 2018-01-23
  • 打赏
  • 举报
回复
引用 5 楼 worldy 的回复:
void light() //流水灯子程序 { uchar i; led=0xfe; delay(300); while(1)//这里会死循环,主程序只能在这里跑 { for(i=0;i<7;i++) { led=_crol_(led,1); delay(300); } led=0xfe; delay(300); } }
谢谢!已经改正 有办法使灯和蜂鸣器同时工作吗
faihung 2018-01-23
  • 打赏
  • 举报
回复
楼主你上面两个函数是两个死循环,这个又不是多线程的,肯定只会跑在一个地方啊
LJDTJ 2018-01-23
  • 打赏
  • 举报
回复
你定义的STORE[]数组的实际长度为3,而数组索引j在每次执行KEY_PRESS()函数时都会++,因此,会出现数组索引j大于3的情况,即越界访问。需要考虑对j重新计数。
worldy 2018-01-23
  • 打赏
  • 举报
回复
定时器用于生成一个tick比如0.5ms间隔 定时器代码 一个标志 bTick=~bTick;//取反 主程序while循环里 一个主控标志 bOn 、一个亮灯计数器count if(bOn) { beepPin=bTick;//蜂鸣器的引脚和bTick同步即可 conut++; if(count>=2000) { lightPin=~lightPin;//灯引脚1s亮1秒灭灯 count=0 } } 大概思路就是这样,你自己扩展
Tech沉思录 2018-01-22
  • 打赏
  • 举报
回复
/*********
*  矩阵键盘 55 56行的不遮起来就不对
*  可以变为计算器
********************************************************************************/    


#include<reg52.h>
#define KEY_VALUE P1
#define uchar unsigned char
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
uchar KEY_NUM;
char code TAB[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,'+','-','*','='};//显示0~F的值
char STORE[]={0,0,0};
uchar j=0;			 //数组的下标
uchar RES;			//运算结果
/*******************************************************************************************/                        		   
void delay(int i)		   //延时
    {
       while(i--);
    }

/*******************************************************************************************/  
void KEY_PRESS()                 //按键子程序
{    uchar a;
     KEY_VALUE=0xf0;              //先判断哪一行按下
     if(KEY_VALUE!=0xf0)
     {
        delay(1000);
	if(KEY_VALUE!=0xf0)	  //判断是否真正按下去
	{
	    switch(KEY_VALUE)
	    {
	       case(0x70):KEY_NUM=0;break;     //先判断哪一行按下
	       case(0xB0):KEY_NUM=4;break;
	       case(0xD0):KEY_NUM=8;break;
	       case(0xE0):KEY_NUM=12;break;
	    }
	 KEY_VALUE=0x0f;					    //判断哪一列按下
	 switch(KEY_VALUE)
	    {
	       case(0x07):KEY_NUM=KEY_NUM;break;	     
	       case(0x0B):KEY_NUM=KEY_NUM+1;break;
	       case(0x0D):KEY_NUM=KEY_NUM+2;break;   
	       case(0x0E):KEY_NUM=KEY_NUM+3;break;
	    }
	    while(a<50&&KEY_VALUE!=0x0f)
	    {
	       delay(1000);
	       a++;
	    }
	}
     }
//     STORE[j]=KEY_NUM;             //先保存下来放在数组中
//     j++;
     
     
}
/*******************************************************************************************/
void WATCH()	      //显示函数
{
//   if(TAB[KEY_NUM]=='=')	   //=时显示RES里面的
//     {P0=TAB[RES];  
//     }
//    else if(TAB[KEY_NUM]=='+'||'-'||'*'); //+-*时无变化
//    else   
        P0=TAB[KEY_NUM];	   //其他时显示数字
}

/*******************************************************************************************/
//void RESULT()				   //求结果函数   全部为0-9的显示
//{ 
//   if(TAB[KEY_NUM]=='=')
//  {
//    if(TAB[STORE[1]]=='+')
//    RES=STORE[0]+STORE[2];
//    if(TAB[STORE[1]]=='-') 
//    RES=STORE[0]-STORE[2];
//    if(TAB[STORE[1]]=='*')		  
//    RES=STORE[0]*STORE[2]; 
//   }
//
//
//}
/*******************************************************************************************/
void main()
{ 
 LSA=1;LSB=1;LSC=1;
 while(1)			    //此处一直执行注意将显示函数全放在while里面
  {
  KEY_PRESS();
//  RESULT();
  WATCH();
  
  }
}
这样的话就可以实现键盘了 但是55 56行不遮起来的话矩阵键盘5之后的都不能正常显示了
Tech沉思录 2018-01-22
  • 打赏
  • 举报
回复
#include<reg52.h>
#define KEY_VALUE P1
#define uchar unsigned char
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
uchar KEY_NUM;
char code TAB[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,'+','-','*','='};//显示0~F的值
char STORE[]={0,0,0};
uchar j=0;			 //数组的下标
uchar RES;			//运算结果
/*******************************************************************************************/                        		   
void delay(int i)		   //延时
    {
       while(i--);
    }

/*******************************************************************************************/  
void KEY_PRESS()                 //按键子程序
{    uchar a;
     KEY_VALUE=0xf0;              //先判断哪一行按下
     if(KEY_VALUE!=0xf0)
     {
        delay(1000);
	if(KEY_VALUE!=0xf0)	  //判断是否真正按下去
	{
	    switch(KEY_VALUE)
	    {
	       case(0x70):KEY_NUM=0;break;     //先判断哪一行按下
	       case(0xB0):KEY_NUM=4;break;
	       case(0xD0):KEY_NUM=8;break;
	       case(0xE0):KEY_NUM=12;break;
	    }
	 KEY_VALUE=0x0f;					    //判断哪一列按下
	 switch(KEY_VALUE)
	    {
	       case(0x07):KEY_NUM=KEY_NUM;break;	     
	       case(0x0B):KEY_NUM=KEY_NUM+1;break;
	       case(0x0D):KEY_NUM=KEY_NUM+2;break;   
	       case(0x0E):KEY_NUM=KEY_NUM+3;break;
	    }
	    while(a<50&&KEY_VALUE!=0x0f)
	    {
	       delay(1000);
	       a++;
	    }
	}
     }
     STORE[j]=KEY_NUM;             //先保存下来放在数组中
     j++;
     
     
}
/*******************************************************************************************/
void WATCH()	      //显示函数
{
   if(TAB[KEY_NUM]=='=')	   //=时显示RES里面的
     {P0=TAB[RES];  
     }
    else if(TAB[KEY_NUM]=='+'||'-'||'*'); //+-*时无变化
    else   
        P0=TAB[KEY_NUM];	   //其他时显示数字
}

/*******************************************************************************************/
void RESULT()				   //求结果函数   全部为0-9的显示
{ 
   if(TAB[KEY_NUM]=='=')
  {
    if(TAB[STORE[1]]=='+')
    RES=STORE[0]+STORE[2];
    if(TAB[STORE[1]]=='-') 
    RES=STORE[0]-STORE[2];
    if(TAB[STORE[1]]=='*')		  
    RES=STORE[0]*STORE[2]; 
   }


}
/*******************************************************************************************/
void main()
{ 
 LSA=1;LSB=1;LSC=1;
 while(1)			    //此处一直执行注意将显示函数全放在while里面
  {
  KEY_PRESS();
  RESULT();
  WATCH();
  
  }
}
自己写了一个使用矩阵键盘和一个八段数码管的极其简单计算器,但是烧进去以后按键没有作用,数码管只显示8. ,这个是在我之前一个按键显示0到F的代码修改的,之前的那个是可以正常显示的,但是在这个里面把后来增加的去掉只留一个49 50行的那个保存键盘显示就在5之后不正常了,,
worldy 2018-01-22
  • 打赏
  • 举报
回复
void light() //流水灯子程序 { uchar i; led=0xfe; delay(300); while(1)//这里会死循环,主程序只能在这里跑 { for(i=0;i<7;i++) { led=_crol_(led,1); delay(300); } led=0xfe; delay(300); } }
Tech沉思录 2018-01-22
  • 打赏
  • 举报
回复
引用 3 楼 LJDTJ 的回复:
你的sound()函数和light()函数中都有while(1)循环,但没有跳出循环的控制,因此结果就变成只进入排在前面的函数中一直执行,而无法跳出该函数去执行下一个函数。去掉这两个函数中的while(1)就可以了。
谢谢! 试了一下确实这样,但是有办法实现sound 和light同时起作用吗
LJDTJ 2018-01-22
  • 打赏
  • 举报
回复
你的sound()函数和light()函数中都有while(1)循环,但没有跳出循环的控制,因此结果就变成只进入排在前面的函数中一直执行,而无法跳出该函数去执行下一个函数。去掉这两个函数中的while(1)就可以了。
Tech沉思录 2018-01-21
  • 打赏
  • 举报
回复

sound()和light()哪个靠上面哪个就执行,另一个就不执行了
Tech沉思录 2018-01-21
  • 打赏
  • 举报
回复
求指教这是管脚图

27,370

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧