向高手请教:STM32F103RE_EXTI的问题

sofy231   2009-12-2 10:28 楼主
我在使用STM32F103RE的EXTI功能时遇到了一些问题:先说我的设置吧,倍频到72MHz,使用PC0~PC5作为外部中断触发输入,同时打开了USART1和TIM3,使用Ver3.0版本的库函数;
遇到的问题是:当我使用信号发生器分别给PC0~PC5输入1KHZ的方波时,PC3、 PC4、PC5端口可以使程序正常运行,而给PC0、PC1、PC2加载方波信号后程序无**常运行,进入调试模式后,发现程序停止在了static void SetSysClockTo72(void)函数最后的循环处;当我将输入频率降低到100HZ后,一切就都正常了;
这是为什么?希望有用过的朋友指导一下,万分感谢!!
源代码如下:
void F122M_Configuration(void)
{   
NVIC_InitTypeDef NVIC_InitStructure;      //NVIC variables
GPIO_InitTypeDef  GPIO_InitStructure;      //GPIO variables
EXTI_InitTypeDef EXTI_InitStructure;      //EXTI variables
/*--NVIC--*/
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;      //更新事件,外部通道0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //响应优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
NVIC_Init(&NVIC_InitStructure);                             //写入设置
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;      //更新事件,外部通道1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //响应优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
NVIC_Init(&NVIC_InitStructure);                             //写入设置
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;      //更新事件,外部通道2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //响应优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
NVIC_Init(&NVIC_InitStructure);                             //写入设置
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;      //更新事件,外部通道3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //响应优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
NVIC_Init(&NVIC_InitStructure);                             //写入设置
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;      //更新事件,外部通道4
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //响应优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
NVIC_Init(&NVIC_InitStructure);                             //写入设置
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;      //更新事件,外部通道5
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //响应优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
NVIC_Init(&NVIC_InitStructure);                             //写入设置
/*--GPIO--*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); //PC端口时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);       //配置外部中断线0~5 GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC,&GPIO_InitStructure);      //配置电源控制引脚 GPIO
/*--EXTI--*/
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource0); //将PC0口用于外部中断事件检测,  
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource1); //将PC1口用于外部中断事件检测,
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource2); //将PC2口用于外部中断事件检测,  
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource3); //将PC3口用于外部中断事件检测,
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource4); //将PC4口用于外部中断事件检测,
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); //将PC5口用于外部中断事件检测,
EXTI_ClearITPendingBit(EXTI_Line0);       //清除线路挂起位  
EXTI_ClearITPendingBit(EXTI_Line1);
EXTI_ClearITPendingBit(EXTI_Line2);
EXTI_ClearITPendingBit(EXTI_Line3);
EXTI_ClearITPendingBit(EXTI_Line4);
EXTI_ClearITPendingBit(EXTI_Line5);
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4 | EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;  //产生中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿检测
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
调用顺序:
  RCC_Configuration();
HW_Configuration();//配置USART,TIM3
  /* Add your application code here
     */
F122M_Configuration();
中断函数:
/*******************************************************************************
* Function Name  : EXTI0_IRQHandler
* Description    : This function handles External interrupt Line 0 request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{  
  EXTI_ClearITPendingBit(EXTI_Line0);
  count_0 = count_0 + 1;
}
}
/*******************************************************************************
* Function Name  : EXTI1_IRQHandler
* Description    : This function handles External interrupt Line 0 request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1) != RESET)
{  
  EXTI_ClearITPendingBit(EXTI_Line1);
  count_1 = count_1 + 1;
}
}
/*******************************************************************************
* Function Name  : EXTI2_IRQHandler
* Description    : This function handles External interrupt Line 0 request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EXTI2_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line2) != RESET)
{  
  EXTI_ClearITPendingBit(EXTI_Line2);
  count_2 = count_2 + 1;
}
}
/*******************************************************************************
* Function Name  : EXTI3_IRQHandler
* Description    : This function handles External interrupt Line 0 request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3) != RESET)
{  
  EXTI_ClearITPendingBit(EXTI_Line3);
  count_3 = count_3 + 1;
}
}
/*******************************************************************************
* Function Name  : EXTI4_IRQHandler
* Description    : This function handles External interrupt Line 0 request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EXTI4_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line4) != RESET)
{  
  EXTI_ClearITPendingBit(EXTI_Line4);
  count_4 = count_4 + 1;
}
}
/*******************************************************************************
* Function Name  : EXTI9_5_IRQHandler
* Description    : This function handles External interrupt Line 0 request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line5) != RESET)
{   
  EXTI_ClearITPendingBit(EXTI_Line5);
  count_5 = count_5 + 1;
}
}

回复评论 (17)

                                 请问你的PC0~PC5的引脚上是否又上拉电阻?
点赞  2009-12-2 10:56
                                 我觉得配置顺序应该是先GPIO,再EXTI,最后NVIC,不然会有误中断。
点赞  2009-12-2 11:43
回复2楼:没有加上拉电阻,是否必须要加呢?六个通道中为什么有3个正常,3个不正常?
回复3楼:这个顺序我也试过,但是效果是一样的。
点赞  2009-12-2 12:00


点赞  2009-12-2 12:01
点赞  2009-12-2 12:02
                                 调试时在PC0、PC1、PC2中断中设置断点,是什么结果?
点赞  2009-12-2 12:06

刚才飞了个4.7K的上拉电阻,没效果!!
点赞  2009-12-2 12:09

如果给PC0,PC1,PC2输入外部方波的话,进调试模式打断点后数据是正常的计数结果,如果给PC3,PC4,PC5输入1k的方波的话,连时钟都初始化不完,一直停在时钟函数最后的死循环中。
点赞  2009-12-2 12:12
我还是觉得是过早产生中断的问题。

不过你说停在时钟函数最后的死循环中,是指哪个函数阿?是"If HSE fails to start-up“那里?

首先配置一定要按3楼的顺序做,不然必然有误中断。

其次,你确认下给PC3,4,5输入方波做测试的时候,板子有没有断电复位阿?
点赞  2009-12-2 15:43
3楼的顺序也用过,但是效果是一样的;程序具体的停止位置为:“system_stm32f10x.c”文件的“SetSysClockTo72(void)”函数中static void SetSysClockTo72(void)
{

  /*!< Wait till HSE is ready and if Time out is reached exit */
  do
  {

  } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {

  }
  else
  {

  }  
  if (HSEStatus == (uint32_t)0x01)
  {
  }
  else
  { /*!< If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */   
    /*!< Go to infinite loop */
    while (1)
    {
//就是在这里停止了!!!!!!!!
    }
  }
}
给PC0到PC6输入方波的设置是一样的,但是只有PC3,PC4,PC5有问题。
点赞  2009-12-2 17:18
                                 这么长的代码,我是进来学习的
点赞  2009-12-2 19:07
程序太长没看,但感觉是HSE启动没有成功。
建议先改回HSI,如果成功了,说明是HSE的问题。
如果是HSE的问题,建议检查晶振的电容。
点赞  2009-12-3 15:12
                                 你用示波器查看晶振的引脚,看看有没有波形,可能是你的外部振荡器没有成功运行导致的。
点赞  2009-12-3 17:10
                                 一会看看,但是如果没有给IO引脚输入1KHZ的方波时为什么没有问题啊?
点赞  2009-12-7 08:03
                                 是晶振的问题吗
点赞  2009-12-7 10:50
                                 上午用示波器观察外部晶振的频率,发现没有任何问题,与平时一样;我的外部晶振使用的是12M的,外部连接2个20pF电容与一个1M的电阻;各位大侠还有什么解决办法吗?
点赞  2009-12-7 15:46
请将 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;改变为全局变量
当出现如下状况时
else
  { /*!< If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */   
    /*!< Go to infinite loop */
    while (1)
    {
//就是在这里停止了!!!!!!!!
    }
  }

HSEStatus = ?, StartUpCounter  = ?将这两个值贴出来。
点赞  2009-12-7 16:24
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复