按键去抖问题【结合 中断、串口通讯等】

2019-03-24 18:53发布

/******************************************************************************
XWWK-CC2530A模块外部中断测试程序+XWWK-CC2530A模块串口测试程序+IO测试程序
Filename:     CC2530EXINTest.c
Target:       cc2530
Revised:      2012年12月25日
Revision:     1.0
Description:
   通过按键P1.2中断方式,改变指示灯的状态。 按一下,LED等显示为方式二,再按一下为方式一,然后循环,但是有时按一下按键状态改变2次,不知是不是按键去抖没做好?

源程序只有串口通讯功能,中断按键什么的都是自己加的,估计是什么地方没有考虑到吧,请各位前辈多多指点【大家只要看蓝 {MOD}部分就行了,其他地方要是需要的话再看
******************************************************************************/

#include <ioCC2530.h>
#include <string.h>

#define uint  unsigned int
#define uchar unsigned char
//定义控制灯的端口
#define RLED   P1_0          //定义LED1为P10口控制
#define YLED   P1_1          //定义LED2为P11口控制
#define KEY1   P1_2       //定义按键为P01口控制
//函数声明
void Delay(uint);                //延时函数声明
void Initial(void);                //初始化函数声明
void InitKey(void);             //初始化按键函数声明
uchar KeyScan(void);            //按键扫描函数声明

uchar Keyvalue = 0 ;                //定义变量记录按键动作
uint  KeyTouchtimes = 0 ;           //定义变量记录按键次数
uint flag=1;


void initUARTSEND(void);
void UartTX_Send_String(char *Data,int len);

char Txdata[25]="按键控制串口测试-然 1 ";
/****************************
//延时
*****************************/
void Delay(uint n)
{
        uint i;
        for(i = 0;i<n;i++);
        for(i = 0;i<n;i++);
        for(i = 0;i<n;i++);
        for(i = 0;i<n;i++);
        for(i = 0;i<n;i++);
}
/****************************************************************
   串口初始化函数                                
****************************************************************/
void initUARTSEND(void)
{

    CLKCONCMD &= ~0x40;                          //设置系统时钟源为32MHZ晶振
    while(CLKCONSTA & 0x40);                     //等待晶振稳定
    CLKCONCMD &= ~0x47;                          //设置系统主时钟频率为32MHZ


    PERCFG = 0x00;                                //位置1 P0口
    P0SEL = 0x3c;                                //P0_2,P0_3,P0_4,P0_5用作串口
    P2DIR &= ~0XC0;                             //P0优先作为UART0

    U0CSR |= 0x80;                                //UART方式
    U0GCR |= 9;                                       
    U0BAUD |= 59;                                //波特率设为19200
    UTX0IF = 0;                                 //UART0 TX中断标志初始置位0
}
/****************************
//初始化按键为中断输入方式
*****************************/
void InitKeyINT(void)
{
  P1INP |= 0x04; //上拉   
  P1IEN |= 0X04;   //P12设置为中断方式
  PICTL |= 0X01;   //下降沿触发

  IEN2 |= 0X10;   // P1设置为中断方式;
  P1IFG |= 0x00;   //初始化中断标志位
  EA = 1; //使能总的中断
}
/****************************************************************
串口发送字符串函数                        
****************************************************************/
void UartTX_Send_String(char *Data,int len)
{
  int j;
  for(j=0;j<len;j++)
  {
    U0DBUF = *Data++;
    while(UTX0IF == 0);
    UTX0IF = 0;
  }
}
/****************************
//初始化程序,将P10、P11 定义为输出口,并将LED灯初始化为灭
*****************************/
void InitIO(void)
{
    P1DIR |= 0x03; //P10、P11、P14定义为输出
    RLED = 0;
    YLED = 0;        //LED灯初始化为灭
}
/****************************
//中断处理函数
*****************************/
#pragma vector = P1INT_VECTOR
__interrupt void P1_ISR(void)
{
   int i;

   if(P1IFG>0)            //按键中断 SFR(  P1IFG     ,  0x8A  )   /*  Port 1 Interrupt Status Flag                       */
   {
     P1IFG = 0;
     Delay(100);  
     if(P1IFG==0)         //按键中断
     {
       Delay(100);
       KeyTouchtimes=!KeyTouchtimes;
//       for(i=0;i<30;i++)Txdata=' ';   //【加上此句串口只显示“方式1”    】
       if(KeyTouchtimes)
       {

         strcpy(Txdata,"方式1 ");       //将UART0 TX test赋给Txdata;
         flag=2;
         UartTX_Send_String(Txdata,strlen(Txdata)); //串口发送数据
       }
       else
       {
       //  for(i=0;i<30;i++)Txdata=' ';
         strcpy(Txdata,"方式2 ");       //将UART0 TX test赋给Txdata;
         flag=1;  //每次中断发生时记录按键次数加1
         UartTX_Send_String(Txdata,strlen(Txdata)); //串口发送数据
       }
     }  
   }      
   P1IF = 0;             //清中断标志
}

/***************************
//主函数
***************************/
void main(void)
{
  uchar i;
  InitIO();        
  InitKeyINT();               //调用初始化函数
  initUARTSEND();
  UartTX_Send_String(Txdata,25);                //
  for(i=0;i<30;i++)Txdata=' ';
  while(1)
  {
    if(flag == 1)       //按键设置为 LED2,LED1流水闪烁  
使用flag做标志位
    {

      YLED = !YLED;           
      Delay(20000);            
      RLED = !RLED;           
      Delay(20000);
      //KeyTouchtimes++;        
    }
    if(2 == flag)
    {
      YLED = !YLED;           
      //Delay(20000);            
      RLED = !RLED;           
      Delay(20000);
            YLED = !YLED;           
      //Delay(20000);            
      RLED = !RLED;           
      Delay(20000);
            YLED = !YLED;           
      //Delay(20000);            
      RLED = !RLED;           
      Delay(20000);
     // KeyTouchtimes = 0;   
    }

  }
}


[ 本帖最后由 嘤鸣求友 于 2012-12-27 09:24 编辑 ] 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
Li_Lei
1楼-- · 2019-03-25 16:51
我的意思是说你在按键中断里放一个串口发送,如果按一下收到多个数据那肯定是消抖得问题了.翻转led也行.

     if(P1IFG==0)         //按键中断
     {
       Delay(100);
这段很糟,在中断服务里空等什么也做不了.

还是那句话delay消抖是个很菜的方法
lr2131
2楼-- · 2019-03-25 21:57
在中断中消耗过多甚至是无谓的时间实在不是一个好方法。

一周热门 更多>