2017-03-14 11:10:07 shuguang1223 阅读数 750
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3402 人正在学习 去看看 朱有鹏

           第一次写博客,有不对或不好的地方欢迎指正。

        

              

                 程序过程很简单,就是系统上电后LED0-LED3亮,LED4-LED7灭;当第一次按下SW8后,LED4-LED7亮,LED0-LED3灭 ,再次按下SW8后,LED0-LED3亮,LED4-LED7灭。

            按钮在按下与弹起的过程中会出现一定的抖动,这有时会对应用过程产生影响,所以我想了一个办法,用switch来        判断按钮的状态

       

#include<iom16v.h>
#include<macros.h>

char B=0,choose1=1;
void SURE_key(int Key_Num);    //定义按键状态判断函数
//=============================
void delay_ms(int k)
{
    int i,j;			
    for(i=0;i<k;i++)
    {
       for(j=0;j<850;j++)
       ;
    }
}
//=============================
int main()	
{		
unsigned char i=0;		
DDRA=0xff;		    //初始化端口A全为输出
PORTA=~(0xf);		    //初始化端口A 0-3输出低电平;4-7输出高电平
DDRD=0x0;                   //初始化端口D全为输入
PORTD|=0xff;                //打开上拉电阻
   while(1)	
   {   
   
	    SURE_key(~PIND&(1<<4));       //判断按键状态,按下弹起后B++
	    if(B%2==1) PORTA=(0xf);
		else PORTA=~(0xf);
   
	}
   return 0;		
}

void SURE_key(int Key_Num)
{
      switch(choose1)
     {
      case 1:
       if(Key_Num!=0) choose1=2;     //按下了么?
	   else choose1=1;
       break;  
      case 2:
       if(Key_Num!=0) choose1=3;    //按下了么?
       else choose1=1;
       break;
      case 3:
      if(Key_Num!=0) choose1=3;       //按下了!松开了么?
      else choose1=4;
      break;
      case 4:                          //松开了
       B++;
       choose1=1;
       break;
      }
}

2013-05-04 17:55:10 learn_2 阅读数 1833
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3402 人正在学习 去看看 朱有鹏
key为按键,规定按下为低电平
if(key==0)
{
delay(50); //延时50ms,消抖
    if(key==0) //再判断是否按下
   {
      while(!key); 松手检测
··················································
该按键按下要实现的功能程序
··················································
     }
}
我的习惯是这样写
2019-06-26 15:42:55 weixin_38832162 阅读数 603
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3402 人正在学习 去看看 朱有鹏

第一次写博客。
今天碰到一个很小,但是很诡异的问题,用的是STC8F2K系列单片机,做的一个简单的驱动板。该板子需要根据按钮和传感器状态来驱动器件,共三个按钮,梳理了程序流程,我用两个外部下降沿中断来连接到按钮。然后呢,我不想在中断函数里写太多代码,便只在中断函数里放了一个全局变量,按下按钮进入中断时改变该变量的值,然后在主程序中判断该值,来执行接下来的程序,部分程序代码如下:

void main()
{   
	 

	//	PX0=3;                   // INT0优先级3
	//	PX1=0;                   // INT1优先级0
	IT0 = 1;                 // 使能INT0下降沿中断
    EX0 = 1;                 // 使能INT0中断
	 IT1 = 1;                 // 使能INT1下降沿中断
    EX1 = 1;                 // 使能INT1中断
    EA  = 1;
 
	
	while(a)
	{
			//Y1=ON; 
	
		
	if((SWL==0)&(a==1))
		{
			Delay3s();              
			while(~SWL&a)
			Y2=ON;         		      
			Y2=OFF;                 
			Delay3s();
			if(a==1)
		   J1=ON;                
		}	
		
	}
}

中断函数就很简单了,如下:

void INT0_Isr() interrupt 0 using 1
{
					a=1; 
				   	
}



void INT1_Isr() interrupt 2 using 1
{
                                     
       a=0;
		Y1=OFF;
		Y2=OFF;
		J1=OFF;
	//  while(~a);               

}`

下载程序到板子调试,死活也不行。用KEIL仿真了一下,竟然又是正常的。然后写了段测试程序,确认可以正常进中断,而且硬件也没问题,去网上搜了一圈,他们说最好要加volatile关键字,我加了,还是不行,又有人说,在中断中使用全局变量,要确保中断函数和声明变量的程序在同一文件,我想了一下,STC又不像STM32,中断向量表是单独放在一个文件里然后允许外部引用的,而且工程里只有一个“stc.h”的头文件,没有其他文件,至于链接和编译的时候,编译器如何把中断函数映射到中断向量,我等菜鸟就不得所知了,不过我觉得这个问题也可以深入研究一下。接下来,我又尝试了用指针的方法访问在中断函数中改变a的值,代码如下:

void INT0_Isr() interrupt 0 using 1
{
					int *b
					b=&a;
					*b=1;	
}

结果还是不行。到这时候,我已经想放弃这种方式了,但我就是很好奇,中断函数里肯定是可以改变全局变量的值的,为什么我这里就不行呢?型号的问题?
继续查找资料,看到了网友的一句话,他说,你可以在中断函数中改变全局变量的值,但你要确保该值没有在主程序中被占用。
我觉得这个可能是问题所在,于是重新写了简单的小程序验证了一下,代码如下:

void main()
{
	

	PX0=0;                                      // INT0优先级最低
    PX1=3;                               
    IT0 = 1;                                    //使能INT0下降沿中断
    EX0 = 1;  
	 IT1 = 1;                                    //使能INT1下降沿中断
    EX1 = 1;    		                          	//使能INT0中断
    EA = 1;

   while(1);
}

void INT1_Isr() interrupt 2 using 1
{
      a=1;
}

void INT0_Isr() interrupt 0 using 1
{
 
       
	    if(a==1)
				P10=0;

}

烧录程序,P10对应的小灯终于亮了! 看来这就是问题所在。
我有将上面的程序修改了一下,将主程序中的while(1)改成while(a),再烧录程序,就毫无反应了,为什么?因为主程序中的大循环一直在调用a的值,所以你在中断函数中,无法改变它。那么怎么解决呢?主程序中的循环改成这样:

while(1)
	 {
		 if(a==1)
			 P10=0;
	 }

这样就OK了。至于为什么这样就OK了,抱歉,我没有去深入探究,也希望了解的大神可以告知一下。

其实这是一个很小的问题,改下程序就可以绕过去,但可能是钻牛角尖的精神吧,自己想了一下,也算解决了一般。水平有限,仅供大家参考。

另外,我觉得写程序,如果需要在中断中使用全局变量,最好还是加上volatile,像我这种简单的程序可能还无所谓,但是复杂的程序,真的可以省去许多不必要的麻烦,尤其是,这种错误,你的编译器永远不会告诉你。

2019-05-15 11:00:36 Steele_Jun 阅读数 867
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3402 人正在学习 去看看 朱有鹏

独立按键的使用较为简单,一般需特别注意按键的抖动;因为按键的开关都有抖动,而如果在抖动时间内检测按键状态就会不准确,所以一般延时10ms~20ms检测,延时时间可能需要具体修改。
写程序之前先弄明白自己按键连接的引脚,以及按下按键后电平的改变状态。

  • 按键k1连接在P3.1口; 按下按键,按键电平变为低电平;
  • led1连接在P2.0口;led1低电平点亮;

按键控制LED亮灭

#include "reg52.h"	

typedef unsigned int u16;	

sbit k1=P3^1;	 //定义P31口是k1
sbit led=P2^0;	 //定义P20口是led


void delay(u16 i)    // 10*i us
{
	while(i--);	
}

void key()
{
	if(k1==0)		  //检测按键是否按下
	{	
		delay(1500);   //抖动延时15ms
		if(k1==0)	 //再次判断按键是否按下
		{
			led=~led;	  //按键按下,led状态取反
		}
		while(!k1);	 //检测按键是否松开,松开则退出;确保按键松开,不加这句控制不准确
	}		
}

void main()
{	
	while(1)
	{	
		key();  //按键
	}		
}
2016-09-11 09:05:54 best_fiends_zxh 阅读数 315
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3402 人正在学习 去看看 朱有鹏

矩阵键盘共有16个按键,如何通过按一个按键,能够将对应的引脚电位拉低,下面看一下电路图:


大概就是这样,扫描按键的程序如下:

unsigned char key_scan(void)//这是纵向扫描
{
        unsigned char keyvalue;
        KEYPORT = 0xf0;
      if(0xf0 != KEYPORT)
        {
                delay_ms(10);
              if(0xf0 != KEYPORT)
                {
                      KEYPORT = 0xfe;
                      if(0xfe != KEYPORT)//一组四个按键
                        {
                              keyvalue = KEYPORT;
                              keyvalue &= 0xf0;
                              keyvalue += 0x0e;
                              while(0xfe != KEYPORT);
                              delay_ms(10);
                              while(0xfe != KEYPORT);
                              return keyvalue;
                                
            }
                        KEYPORT = 0xfd;
                      if(0xfd != KEYPORT)//第二组四个按键
                        {
                              keyvalue = KEYPORT;
                              keyvalue &= 0xf0;
                              keyvalue += 0x0d;
                              while(0xfd != KEYPORT);
                              delay_ms(10);
                              while(0xfd != KEYPORT);
                              return keyvalue;
                                
            }
                        KEYPORT = 0xfb;
                      if(0xfb != KEYPORT)//第三组四个按键
                        {
                              keyvalue = KEYPORT;
                              keyvalue &= 0xf0;
                              keyvalue += 0x0b;
                              while(0xfb != KEYPORT);
                              delay_ms(10);
                              while(0xfb != KEYPORT);
                              return keyvalue;
                                
            }
                        KEYPORT = 0xf7;
                      if(0xf7 != KEYPORT)//第四组四个按键
                        {
                              keyvalue = KEYPORT;
                              keyvalue &= 0xf0;
                              keyvalue += 0x07;
                              while(0xf7 != KEYPORT);
                              delay_ms(10);
                              while(0xf7 != KEYPORT);
                              return keyvalue;
                                
            }
        }
    }
        return 0xff;
}


unsigned char key_pro()
{
      unsigned char keynum;
      keynum = key_scan();
      switch(keynum)
      {
              case 0x7e:return 1;break;
              case 0xbe:return 2;break;
              case 0xde:return 3;break;
              case 0xee:return 4;break;
              case 0x7d:return 5;break;
              case 0xbd:return 6;break;
              case 0xdd:return 7;break;
              case 0xed:return 8;break;
              case 0x7b:return 9;break;
              case 0xbb:return 10;break;
              case 0xdb:return 11;break;
              case 0xeb:return 12;break;
              case 0x77:return 13;break;
              case 0xb7:return 14;break;
              case 0xd7:return 15;break;
              case 0xe7:return 16;break;
              default:return 0xff;break;
    }
}

这是扫描按键的程序,反正就是横向扫一遍,纵向扫一遍,就能确保每一个按键都能扫到,希望能帮助到大家。


按钮分析

阅读数 162

没有更多推荐了,返回首页