CC2530按键长按和短按控制LED

其中部分内容为本人自我认知,仅供参考,如有不足请补充。
。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。 --------------------- 第一步---------------------。。。。
。。。。 ——————介绍相关寄存器——————。。。
。。。。 --------------------- 第二步---------------------。。。。
。。。。 ——介绍由整体代码拆分后的部分内容——。。。
。。。。 --------------------- 第三步---------------------。。。。
。。。。 ——————呈现整体代码——————。。。。
。。。。 --------------------- 第四步---------------------。。。。
。。。。 ————————总结————————。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。

————直接上案例来解释中断————

任务:用按键1长按或短按控制LED6与LED4(使用端口1中断和定时器1中断来实现)

有关LED的相关寄存器

P1SEL(Port 1 set level)——端口1功能寄存器

PxSEL-端口功能寄存器

P1DIR(Port 1 direction register)——端口1方向寄存器

PxDIR-端口方向寄存器

P1(Port 1)——端口1

存储P1_0到P1_7的状态信息。

有关端口1中断的相关寄存器

PICTL(Port input communication trigger level)——端口输入信号

PICTL-端口输入信号

P1IFG (Port 1 interrupt flag group)——P1端口状态标志寄存器

P1IFG-P1端口状态标志寄存器

P1IEN (Port 1 interrupt enable)——P1端口中断使能

P1IEN-P1端口中断使能

IEN0 (Interrupt enable 0)——中断使能寄存器0

IEN0-中断使能寄存器0

IEN2 (Interrupt enable 2)——中断使能寄存器2

IEN2-中断使能寄存器2

有关定时器1中断的相关寄存器

T1CCTLx(Time1 Capture Control)——端口输入信号

使用通道0作为定时器通道
T1CCTLx定时器1通道捕获控制寄存器

IEN1 (Interrupt enable 1)——中断使能寄存器1

IEN1-中断使能寄存器1

T1STAT (Time1 State Thoroughfare)——P1端口状态标志寄存器

使用通道0作为定时器通道
T1STAT-定时器状态寄存器

简易延迟部分

由于CPU执行一条指令需要时间,所以让CPU堆满指令条可做到视觉上的延迟

void HAL_Delay(uint32_t num)
{
    
    
  for(uint32_t x=0;x<=num;x++)
    for(uint32_t y=0;y<=535;y++);  
}

初始化LED部分

引脚的对应物件
P1_1 ==> 灯4
P1_4 ==> 灯6

void Init_Port()
{
    
    
 	 P1SEL &=~ 0x1b;	//设置P1_0、P1_1、P1_3、P1_4为通用I/O功能。
 	 P1DIR |=  0x1b; 	//设置P1_0、P1_1、P1_3、P1_4的传输方向为输出。
	 P1    &=~ 0x1b;	//设置P1_0、P1_1、P1_3、P1_4为0(D3、D4、D5、D6关闭)
}

初始化端口1中断的部分

void Init_P1INT()
{
    
    
  IEN2 |= 0x10;       //设置端口1中断使能为1 
  P1IEN |= 0x04;      //设置端口P1_2中断使能
  PICTL |= 0x02;      //设置端口P1_3到P1_0中断触发方式为下降沿触发
}

初始化定时器1中断的部分

void Init_T1()
{
    
    
  EA = 1;
  T1IE = 1;
  T1CCTL0 |= 0x04;    //设置通道0为定时器1的
  T1CC0L = 0xd4;      //设置T1CC0的初始值
  T1CC0H = 0x30;
}

定时器中断服务函数部分

#pragma vector = T1_VECTOR    //定义中断向量
__interrupt void T1_Serivce(void) //设置中断服务函数名
{
    
    
  if((P1_Flag == 1) && (count != 65535))   //防止count溢出
    count++;
}

定时器中断服务函数部分

#pragma vector = P1INT_VECTOR    //定义中断向量
__interrupt void P1INT_Serivce(void) //设置中断服务函数名
{
    
    
  if((P1IFG & 0x04) == 0x04)   //是否检测到下降沿产生的中断标志
  {
    
    
    P1IFG = 0;
    P1IF = 0;
    
    IP0 |= 0x02;     //提高定时器1优先级
    T1CTL |= 0x0e;   //开启定时器1
    PICTL &= ~0x02;  //切换端口1为上升沿触发
    
    P1_Flag = 1;
    
    while((P1IFG & 0x04) != 0x04);  //等待按键松开
    P1IFG = 0;
    P1IF = 0;
    
    P1_Flag = 0;
    
    PICTL |= 0x02;   //切换端口1为下降沿触发
    T1CTL = 0;       //关闭定时器1
    
    if(count <= 5)
      D4 = ~D4;
    else
      D6 = ~D6;
    count = 0;
    
  }
}

整体代码

#include<iocc2530.h>
#define uint32_t unsigned int
#define uint8_t unsigned char
#define D4 P1_1
#define D5 P1_3
#define D6 P1_4
 
/**************************************************************
函数名称:HAL_Delay
功    能:软件延时
入口参数:延时循环执行次数
出口参数:无
返 回 值:无
**************************************************************/
void HAL_Delay(uint32_t num)
{
    
    
  for(uint32_t x=0;x<=num;x++)
    for(uint32_t y=0;y<=535;y++);  
}
 
/**************************************************************
函数名称:Init_Port
功    能:初始化端口
入口参数:无
出口参数:无
返 回 值:无
**************************************************************/
void Init_Port()
{
    
    
  P1SEL &= ~0x1b;
  P1DIR |= 0x1b;
  P1 &= ~0x1b;
}

/**************************************************************
函数名称:Init_T1
功    能:定时器初始化,不启动定时器
入口参数:无
出口参数:无
返 回 值:无
**************************************************************/
void Init_T1()
{
    
    
  EA = 1;
  T1IE = 1;
  T1CCTL0 |= 0x04;
  T1CC0L = 0xd4;
  T1CC0H = 0x30;
}

/**************************************************************
函数名称:Init_P1INT()
功    能:端口1中断初始化
入口参数:无
出口参数:无
返 回 值:无
**************************************************************/
void Init_P1INT()
{
    
    
  IEN2 |= 0x10;
  P1IEN |= 0x04;
  PICTL |= 0x02;
}


/**************************************************************
函数名称:main  
功    能:程序主函数
入口参数:无
出口参数:无
返 回 值:无
**************************************************************/
void main()
{
    
    
  Init_Port();
  Init_T1();
  Init_P1INT();
  while(1)
  {
    
    }
}

uint8_t P1_Flag = 0;   //按键当前状态
uint32_t count = 0;    //定时器计数

/**************************************************************
函数名称:P1INT_Serivce
功    能:中断服务函数,切换LED状态
入口参数:无
出口参数:无
返 回 值:无
**************************************************************/
#pragma vector = P1INT_VECTOR
__interrupt void P1INT_Serivce(void)
{
    
    
  if((P1IFG & 0x04) == 0x04)
  {
    
    
    P1IFG = 0;
    P1IF = 0;
    
    IP0 |= 0x02;     //提高定时器优先级
    T1CTL |= 0x0e;   //开启定时器
    PICTL &= ~0x02;  //切换端口1为上升沿触发
    
    P1_Flag = 1;
    
    while((P1IFG & 0x04) != 0x04);  //等待按键松开
    P1IFG = 0;
    P1IF = 0;
    
    P1_Flag = 0;
    
    PICTL |= 0x02;   //切换端口1为下降沿触发
    T1CTL = 0;       //关闭定时器
    
    if(count <= 5)
      D4 = ~D4;
    else
      D6 = ~D6;
    count = 0;
    
  }
}

/**************************************************************
函数名称:T1_Serivce
功    能:0.1s计时
入口参数:无
出口参数:无
返 回 值:无
**************************************************************/
#pragma vector = T1_VECTOR
__interrupt void T1_Serivce(void)
{
    
    
  if((P1_Flag == 1) && (count != 65535)) 
    count++;
}
 

总结

难点为进入端口1中断后在按键按下时需要提高优先级才可进入定时器1中断

猜你喜欢

转载自blog.csdn.net/weixin_44222591/article/details/114999263