天天看點

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

其中部分内容為本人自我認知,僅供參考,如有不足請補充。

。。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。 --------------------- 第一步---------------------。。。。

。。。。 ——————介紹相關寄存器——————。。。

。。。。 --------------------- 第二步---------------------。。。。

。。。。 ——介紹由整體代碼拆分後的部分内容——。。。

。。。。 --------------------- 第三步---------------------。。。。

。。。。 ——————呈現整體代碼——————。。。。

。。。。 --------------------- 第四步---------------------。。。。

。。。。 ————————總結————————。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。

————直接上案例來解釋中斷————

任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)

有關LED的相關寄存器

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

P1(Port 1)——端口1

存儲P1_0到P1_7的狀态資訊。

有關端口1中斷的相關寄存器

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

有關定時器1中斷的相關寄存器

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

使用通道0作為定時器通道

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

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

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

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

使用通道0作為定時器通道

CC2530按鍵長按和短按控制LED任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)整體代碼總結

簡易延遲部分

由于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中斷

繼續閱讀