一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

STM32中斷配置

 心不留意外塵 2016-05-07

http://blog.sina.com.cn/s/blog_60cf05130100wrnb.html

2011

今天用按鍵中斷來控制LED燈閃爍。當(dāng)時有時候經(jīng)常會出現(xiàn)自己設(shè)置的LED閃爍是4下,但是結(jié)果卻是雙倍次數(shù),8下。很不解。源代碼如下。

Test3_Led1(void)
{
 int K;
 for(K=0;K<4;K++)
  {
  GPIO_SetBits(GPIOF,GPIO_Pin_6);
  Mydelay_ms(1000);
  GPIO_ResetBits(GPIOF, GPIO_Pin_6);
  Mydelay_ms(1000);
 }

經(jīng)過研究,發(fā)現(xiàn)應(yīng)該是按鍵中斷沒做好,每次都產(chǎn)生2次的中斷。這是為什么?

中斷服務(wù)函數(shù)如下:

 void EXTI0_IRQHandler(void)
  {
  //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
     if (EXTI_GetITStatus( EXTI_Line0)!= RESET)
      {

       EXTI_ClearITPendingBit(EXTI_Line0);  //0
   Led1_Flag++;//做測試用,發(fā)現(xiàn)每次都加了2.
   Test3_Led1();
   //EXTI_ClearITPendingBit(EXTI_Line0); //最好放在后面以免造成一清0后,因為按鍵延時又變1。
      }
  }

于是我繼續(xù)研究。發(fā)現(xiàn)原來是這樣的。

每次按鍵按下是一定有抖動的,抖動應(yīng)該會有很多下,5下以上是很正常的。按理論上將每次抖動都會長生一個脈沖,也就是一個中斷。應(yīng)該會有不下于5次中斷,為什么只響應(yīng)2次呢。

其實這個很簡單。因為相同管腳每次中斷都是相同優(yōu)先級的,所以即使產(chǎn)生中斷也不會響應(yīng)。只有在第一個中斷函數(shù)結(jié)束之后再來中斷才會響應(yīng)。雖然不響應(yīng),但是卻會改變中斷標志位。一定還有有人問,不是服務(wù)函數(shù)中把標志位清0了嗎?但是由于單片機執(zhí)行代碼速度很快,你請0之后,抖動如果還在那么就還會產(chǎn)生中斷號(雖然不響應(yīng))。只有在第一次中斷結(jié)束之后,再次去查看中斷號的時候才響應(yīng)。(注:響應(yīng)中斷首先是直接給總線發(fā)命令,不需要單片機查詢。因此采用中斷比采用查詢方式要好的多,減少了CPU的工作量。一旦中斷標志位變1,而且沒有優(yōu)先級更高的中斷在執(zhí)行,那么就會響應(yīng)中斷服務(wù)函數(shù))現(xiàn)在我們就是每次按鍵按下以后,雖然中斷標志經(jīng)過清0,但是由于抖動的存在,清0后很有可能再變1。當(dāng)時不會立刻執(zhí)行。只有當(dāng)這個中斷服務(wù)函數(shù)執(zhí)行完畢才執(zhí)行。所以每次都有可能調(diào)用2次中斷服務(wù)函數(shù)。

那么我們應(yīng)該怎么改變呢?

其實很簡單,最好在中斷服務(wù)函數(shù)開頭和結(jié)尾都把中斷標志位清0,那么即使第一次清0后再變1,但是第二次清0是一定會成功的?;蛘呤且淮吻?,但是在清0之前先延時,確保已經(jīng)沒有抖動。

我是選用第一種方案。

代碼如下:

 void EXTI0_IRQHandler(void)
  {
  //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
     if (EXTI_GetITStatus( EXTI_Line0)!= RESET)
      {

Mydelay_ms(1000);

       EXTI_ClearITPendingBit(EXTI_Line0);  //0
   Led1_Flag++;//做測試用,發(fā)現(xiàn)每次都加了2.
   Test3_Led1();
   //EXTI_ClearITPendingBit(EXTI_Line0); //最好放在后面以免造成一清0后,因為按鍵延時又變1。
      }
  }

這樣即使有抖動每次也只會調(diào)用一次中斷服務(wù)函數(shù)。

 

全部代碼如下:


#include "stm32f10x.h"
//#include "stm32f10x_conf.h"
#include <stdio.h>



void delay(void)
{
  __IO uint32_t i = 0;
 
   for(i = 0xFF; i != 0; i--)
   {
   }
 
}
Mydelay_ms(u16 a)
{
 u16 i,j;
 for(j=0;j<a;j++)
 for(i=0;i<6000;i++); 
}

Test1_GPIO(void)
{
 GPIO_Write(GPIOC, 0xfc4f);
 Mydelay_ms(1);
 //delay();

 GPIO_Write(GPIOC, 0xfd8f);
 Mydelay_ms(1000);
 GPIO_Write(GPIOC, 0xfd0f);
 Mydelay_ms(1000);
 GPIO_Write(GPIOC, 0xfe0f);
 Mydelay_ms(1000);
}
Test2_GPIO(void)
{
 GPIO_SetBits(GPIOF,GPIO_Pin_6);
 Mydelay_ms(1000);
 GPIO_ResetBits(GPIOF, GPIO_Pin_6) ;
 Mydelay_ms(1000);
 

}
Test3_Led1(void)
{
 int K;
 for(K=0;K<4;K++)
  {
  GPIO_SetBits(GPIOF,GPIO_Pin_6);
  Mydelay_ms(1000);
  GPIO_ResetBits(GPIOF, GPIO_Pin_6);
  Mydelay_ms(1000);
 }
 

}
Test3_Led2(void)
 {
 int t;
 for(t=0;t<4;t++)
  {
  GPIO_SetBits(GPIOF,GPIO_Pin_7);
  Mydelay_ms(1000);
  GPIO_ResetBits(GPIOF, GPIO_Pin_7);
  Mydelay_ms(1000);
 }
 


  }
void GPIO_Configuration(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;
 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;
 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
 //GPIO_Init(GPIOA,&GPIO_InitStructure);
 //GPIO_Init(GPIOB,&GPIO_InitStructure);
 //GPIO_Init(GPIOC,&GPIO_InitStructure);
 //GPIO_Init(GPIOD,&GPIO_InitStructure);
 //GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
 GPIO_Init(GPIOF,&GPIO_InitStructure);
 
}







 
//定時函數(shù)有有問題



  void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;                   //中斷管理恢復(fù)默認參數(shù)

#ifdef   VECT_TAB_RAM   //如果C/C++ Compiler\Preprocessor\Defined symbols中的定義了VECT_TAB_RAM(見程序庫更改內(nèi)容的表格)

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //則在RAM調(diào)試

#else                                                                   //如果沒有定義VECT_TAB_RAM

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//則在Flash里調(diào)試

#endif                                                                   //結(jié)束判斷語句

//以下為中斷的開啟過程,不是所有程序必須的。

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

//設(shè)置NVIC優(yōu)先級分組,方式。

//注:一共16個優(yōu)先級,分為搶占式和響應(yīng)式。兩種優(yōu)先級所占的數(shù)量由此代碼確定,NVIC_PriorityGroup_x可以是0、1、2、3、4,分別代表搶占優(yōu)先級有1、2、4、8、16個和響應(yīng)優(yōu)先級有16、8、4、2、1個。規(guī)定兩種優(yōu)先級的數(shù)量后,所有的中斷級別必須在其中選擇,搶占級別高的會打斷其他中斷優(yōu)先執(zhí)行,而響應(yīng)級別高的會在其他中斷執(zhí)行完優(yōu)先執(zhí)行。

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//中斷通道名; //開中斷,中斷名稱見函數(shù)庫

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //搶占優(yōu)先級

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;         //響應(yīng)優(yōu)先級

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動此通道的中斷

NVIC_Init(&NVIC_InitStructure);                                     //中斷初始化
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;//中斷通道名; //開中斷,中斷名稱見函數(shù)庫

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占優(yōu)先級

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         //響應(yīng)優(yōu)先級

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動此通道的中斷

NVIC_Init(&NVIC_InitStructure); 
}



void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;


// RCC_DeInit();


RCC_HSEConfig(RCC_HSE_ON);


HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS)
{
   
    RCC_HCLKConfig(RCC_SYSCLK_Div1);

   
    RCC_PCLK2Config(RCC_HCLK_Div1);

   
    RCC_PCLK1Config(RCC_HCLK_Div2);

   
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

   
    FLASH_SetLatency(FLASH_Latency_2);

   
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

   
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);//Pll在最后設(shè)置

   
    RCC_PLLCmd(ENABLE);

   
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

   
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

   
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
}
////注:AHB主要負責(zé)外部存儲器時鐘。APB2負責(zé)AD,I/O,高級TIM,串口1。APB1負責(zé)DA,USB,SPI,I2C,CAN,串口2345,普通TIM?

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
         | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE| RCC_APB2Periph_GPIOF| RCC_APB2Periph_AFIO, ENABLE);


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


//RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);
}



void GPIO_Configuration1(void)

{

GPIO_InitTypeDef GPIO_InitStructure;                      //GPIO狀態(tài)恢復(fù)默認參數(shù)

//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_標號 | GPIO_Pin_標號 ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//輸出速度2MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

GPIO_Init(GPIOF, &GPIO_InitStructure); //C組GPIO初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);

}

 


void EXTI_Configuration(void)

{
EXTI_InitTypeDef EXTI_InitStructure;

EXTI_ClearITPendingBit(EXTI_Line0);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource8);
//GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);
//GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;  


EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
EXTI_InitStructure.EXTI_LineCmd = ENABLE;    
EXTI_Init(&EXTI_InitStructure);     
EXTI_InitStructure.EXTI_Line = EXTI_Line8;
EXTI_Init(&EXTI_InitStructure); 

}


                                                                                                                            


//下面這段是標準,一定要先配置中斷線,也就是管教選擇,才能進行線路選擇。




      

 

 

u16 Led1_Flag=0,Led2_Flag=0;
void EXTI0_IRQHandler(void);
int main(void)
{
  
 
   SystemInit();
   RCC_Configuration();
   GPIO_Configuration1();
 EXTI_Configuration();
 NVIC_Configuration();  

         
 
 
 
 

 

 

 
GPIO_SetBits(GPIOF,GPIO_Pin_6);
  GPIO_SetBits(GPIOF,GPIO_Pin_7);
  while (1)
  {
   //Mydelay_ms(1000);
  //if(Led_Flag==1)
  //{
  //Mydelay_ms(1000);
 
//} 
  //GPIO_ResetBits(GPIOF,GPIO_Pin_6);
 
  //Test2_GPIO();
 
  }
}

 void EXTI0_IRQHandler(void)
  {
  //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
     if (EXTI_GetITStatus( EXTI_Line0)!= RESET)
      {

       EXTI_ClearITPendingBit(EXTI_Line0);  //0
   Led1_Flag++;
  
   Test3_Led1();
   EXTI_ClearITPendingBit(EXTI_Line0); //最好放在后面以免造成一清0后,因為按鍵延時又變1。
    
      }
    
   
  }
  void EXTI9_5_IRQHandler(void)
  {
  //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
     if (EXTI_GetITStatus( EXTI_Line8)!= RESET)
      {

       EXTI_ClearITPendingBit(EXTI_Line8);  //0
   Led2_Flag++;
  
   Test3_Led2();
   EXTI_ClearITPendingBit(EXTI_Line8); //最好放在后面以免造成一清0后,因為按鍵延時又變1。
    
      }
    
   
  }

//#ifdef  USE_FULL_ASSERT


//void assert_failed(uint8_t* file, uint32_t line)
//{
 

 
 // while (1)
  //{
 // }
//}
//#endif



 

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    丝袜破了有美女肉体免费观看| 精品欧美日韩一二三区| 五月婷婷六月丁香亚洲| 国产乱人伦精品一区二区三区四区 | 国产综合一区二区三区av| 日韩女优精品一区二区三区| 亚洲专区中文字幕视频| 黄色片一区二区三区高清| 日韩人妻中文字幕精品| 久久国产亚洲精品成人| 欧美午夜视频免费观看| 国产精品成人又粗又长又爽| 香蕉久久夜色精品国产尤物 | 成人免费观看视频免费| 不卡一区二区在线视频| 激情爱爱一区二区三区| 国产又粗又猛又爽色噜噜| av一区二区三区天堂| 亚洲一区二区三区一区| 特黄大片性高水多欧美一级| 欧美精品激情视频一区| 亚洲一区二区三区精选| 中文字幕亚洲视频一区二区| 成人午夜视频在线播放| 欧美日韩国产欧美日韩| 日本午夜免费啪视频在线| 精产国品一二三区麻豆| 日韩高清毛片免费观看| 老熟女露脸一二三四区| 国产精品福利一级久久| 黄片美女在线免费观看| 亚洲一区二区三区免费的视频| 不卡一区二区在线视频| 99久久国产精品免费| 99国产精品国产精品九九| 国产精品一区二区三区欧美| 亚洲精品高清国产一线久久| 欧美日韩精品人妻二区三区| 成年人视频日本大香蕉久久| 一区二区三区亚洲天堂| 少妇福利视频一区二区|