FENGFENG-414671 发表于 2013-2-25 10:05:40

STM32F103R8T6的定时器使用问题

现在在做一个定时器的测试程序,要用定时器2定时1秒,中断中翻转IO口,改变指示灯状态。下面是我的程序:
#define ENCODER_TIM_PERIOD (u16) 13999   
#define TIMx_Channel  TIM2_IRQn
#define TIMx_PRE_EMPTION_PRIORITY 0
#define TIMx_SUB_PRIORITY 1
///////////////////////////////
//u8 Port;//PCA9554D的端口
u8 act;//保存A,B,C,共补的电容器投切状态。
u8 counter;//临时程序试验用计数变量。
GPIO_InitTypeDef GPIO_InitStructure;
/* Private function prototypes -----------------------------------------------*/
void Switch_Twel(u8 flag );//正负12V输出电压转换及关闭prototypes
u8 Relay_Drive(u8 X,u8 Z);
void Relay_ALL_Leave(void);//切掉全部电容器。
/////////////////////////////////////////////////////////////

/* Private functions ---------------------------------------------------------*/
void Delay100ms(void)
{
    u32 cnt=0x00020000;
    while(cnt--);//延时105ms
}
void GPIO_Ini(void)
{
  /* GPIOA/GPIOB Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  __NOP();
  /* Configure PA8,PA0 ,PA12 in output pushpull mode *///指示灯控制
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_0|GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  __NOP();
  /* Configure PB11,PB10 in output pushpull mode ,正负12V的电源转换
  */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_10;
  //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_10;//positive and negive 12voltage output
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  __NOP();
  GPIO_ResetBits(GPIOA,GPIO_Pin_12);//双向可控硅的所有驱动输入皆为低电平。
  GPIO_SetBits(GPIOA,GPIO_Pin_8);//关闭指示灯。
}
void timer2_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  /* TIM2clock source enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  NVIC_InitStructure.NVIC_IRQChannel = TIMx_Channel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  /* Timer configuration in Encoder mode */
  TIM_DeInit(TIM2);
  TIM_TimeBaseStructure.TIM_Prescaler = 1999;  // APB2=72M 72M/(71+1)=1M
  TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD;  //count 100 reset to 0
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;   
  TIM_TimeBaseInit(TIM2 , &TIM_TimeBaseStructure);
   //使能预装载
  TIM_ARRPreloadConfig(TIM2, ENABLE);
  //TIM_GenerateEvent(TIM1, TIM_EventSource_Update);
      // Clear all pending interrupts
  TIM_ClearFlag(TIM2 , TIM_FLAG_Update);
  TIM_ClearITPendingBit(TIM2 , TIM_IT_Update);
  //enable interrupt
  TIM_ITConfig(TIM2 , TIM_IT_Update, ENABLE);
  //TIM_Cmd(TIM1, ENABLE);
  TIM_Cmd(TIM2,ENABLE);
  //TIM_CtrlPWMOutputs(TIM1, ENABLE);  
}
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */     
  SystemInit(); // 使用外部8MHZ的晶振,系统时钟改为56MHZ,高速外围56,低俗28MHZ。   
  GPIO_Ini();
  //I2C_EE_Init();
  //PCA9554D_Init();//initialize the PCA9554D as the output ,and all output hign level.
  timer2_Init();
  //u32 cnt=0x0009ffff;
  while (1)
  {;}
}
现在的问题是,一运行程序,就进入中断文件里面的硬件出错部分:
void HardFault_Handler(void)
{
    __IO u32 ReturnAddr;
    ReturnAddr = __get_MSP();
    ReturnAddr = *(u32 *)(ReturnAddr+32);
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}
单步执行,发现在timer2_Init();里面执行TIM_Cmd(TIM2,ENABLE);之后,在
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the TIM Counter */
    TIMx->CR1 |= TIM_CR1_CEN;  }
  else
  {
    /* Disable the TIM Counter */
    TIMx->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN));
  }
}
当返回主程序的时候出错。不知道是为什么。
我是刚开始学习STM32F103R8T6,也是第一次接触STM单片机。希望版主、做过的朋友,帮我找找问题,看看怎么回事。十分感谢!
void TIM2_IRQHandler(void)
{  
   if(TIM_GetFlagStatus(TIM2,TIM_IT_Update)!=RESET)
    {
     // __NOP();
     // GPIO_ResetBits(GPIOA,GPIO_Pin_8);
      //GPIOA->BRR  = 0x00000100;
     // __NOP();
      //IO翻转
      GPIO_WriteBit(GPIOA,GPIO_Pin_8,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_8)));
      //Clear the interrupt pending flag  
      // TIM_ClearFlag(TIM2, TIM_FLAG_Update);
      // TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
      TIM_ClearFlag(TIM2 , TIM_FLAG_Update);
      TIM_ClearITPendingBit(TIM2 , TIM_IT_Update);
    }
}
上面是我的定时器2的定时1S中断程序,但是根本就没有被执行。
                                    昨天下午测试的时候(之前已经发现问题出在定时器2上,使能之后就出硬件故障的错误),在下载仿真里,直接GO,发现程序还能运行一小会。
            网上查找资料,看CM3的权威指南,有以下几种说法:
            1,数组访问越界;
            2,非法硬件操作;
            解决方法有以下几种:
            A,断掉仿真器给目标板供电的;
            B,加大堆栈空间的;
            C,调整优先级的;
            D,添加.S启动文件;
            E,初始化之前,要先关闭全局总中断,初始化之后,再打开。
            要说明的是,我的仿真器是STM32F051的探索套件上自带的STLINK仿真器,没有给目标板供电,因此A不成立;
            加大堆栈空间我测试过了,没有效果,并且看RAM空间和.MAP文件,显示堆栈空间使用地址是0-4,没有超出范围;
            第三个,我的程序里面只有一个中断,没有优先级的问题冲突;
            第四个,我确实没有添加。s文件,但是我认为这个。s文件是自动调用的,理由是在不初始化定时器2时,其他的程序可以正常执行;
            第五个,这个有点可能,可能是我没有使能全局中断,但是这个还没找到在哪里,我再去查查看看。但是看库里自带的例程,里面同样没有打开全局中断这句话。所以说只是可能。
            补充一下,我仿真调试之后,在RAM的堆栈空间里面,看到要执行的语句地址是
            0x20000A74,里面是值也是这个值;这个地址附近有个值是0x00000001;SR值为正常,但是LR却指向0xFFFFFFF1.
            补充:我的向量表在系统初始化里面,映射到了0x08000000FLASH之后。
            请遇到过相同问题或由类似解决经验的大虾帮帮我这个初学者,十分感谢!
                     

FENGFENG-414671 发表于 2013-2-25 13:59:29

RE:STM32F103R8T6的定时器使用问题

下面还有一个485通信接收中断要处理,麻烦各位网友帮我看看。
页: [1]
查看完整版本: STM32F103R8T6的定时器使用问题