打印

STM32F103R8T6的定时器使用问题

[复制链接]
5483|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
伟峰电子|  楼主 | 2013-2-23 17:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
现在在做一个定时器的测试程序,要用定时器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[1];//PCA9554D的端口
u8 act[5][10];//保存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单片机。希望版主、做过的朋友,帮我找找问题,看看怎么回事。十分感谢!
沙发
伟峰电子|  楼主 | 2013-2-23 17:04 | 只看该作者
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中断程序,但是根本就没有被执行。

使用特权

评论回复
板凳
uet_cache| | 2013-2-23 17:17 | 只看该作者
分段屏弊语句看是什么地方导致出错。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
伟峰电子 + 1 谢谢支持!
地板
cjhk| | 2013-2-23 17:48 | 只看该作者
呵呵   应该问题不大吧  看看中断是不是用错了  呵呵

使用特权

评论回复
评论
伟峰电子 2013-2-24 15:00 回复TA
老兄,这话怎么说?可以详细点吗?因为我也是第一次用这个芯片,不熟悉,资料也看了,上面的程序是摘来的,也参考了很多。没发现有错误的地方 
5
伟峰电子|  楼主 | 2013-2-24 14:58 | 只看该作者
uet_cache 发表于 2013-2-23 17:17
分段屏弊语句看是什么地方导致出错。

请好好看一下我的帖子,别灌水。因为问题已经指出了,是在定时器2的初始化里面,定时器2使能之后,返回出错了。   不过还是谢谢你的支持。

使用特权

评论回复
6
伟峰电子|  楼主 | 2013-2-24 15:06 | 只看该作者
哎,我人品估计真的太差劲了,搞了1天半了,还是那个问题,在定时器2使能计数之后,返回主程序出错,然后直接到硬件错误中断。谁能提供解决办法、建议、参考资料,感谢了!

使用特权

评论回复
7
uet_cache| | 2013-2-24 16:30 | 只看该作者
进入硬件故障,一般是非法操作。还是要分段屏蔽语句,看什么 位置出错,才好判断。

使用特权

评论回复
评论
伟峰电子 2013-2-25 11:06 回复TA
老兄这么坚持,能举个例子吗?你看看我的说法,是定时器2使能之后出错,还得找什么位置?请教了。 
伟峰电子 2013-2-25 09:36 回复TA
我分段屏蔽,已经发现问题出在定时器2的使能,定时器2一使能,就跳到硬件故障了。 
8
伟峰电子|  楼主 | 2013-2-25 11:27 | 只看该作者
本帖最后由 伟峰电子 于 2013-2-25 11:29 编辑

昨天下午测试的时候(之前已经发现问题出在定时器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之后。
请遇到过相同问题或由类似解决经验的大虾帮帮我这个初学者,十分感谢!

最新进展,将TIMER2的溢出中断屏蔽之后,程序运行正常。可以初始化,初始化之后,在主程序中,可以正常运行延时--打开指示灯----延时-----关闭指示灯。这个说明确实是定时器2的中断出问题了。

下面还是初始化,使能定时器2的计数,在主程序中,直接按照定时器2的定时1秒溢出标志位在打开关闭指示灯。
我会继续发帖显示后续进展。

使用特权

评论回复
9
伟峰电子|  楼主 | 2013-2-25 14:01 | 只看该作者
即使定时器2的问题放下不处理,用巡检标志位方法来处理,到下面有用到一个485通信的接收中断,估计还是会遇到这个问题。
这么常用到的两个功能,竟然基本没人碰到跟我一样的问题吗?

使用特权

评论回复
10
伟峰电子|  楼主 | 2013-2-25 17:32 | 只看该作者
问题解决:因为启动文件没有添加。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

24

帖子

0

粉丝