OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9166|回复: 13

STM32F103 定时器计数问题,求大神指教!

[复制链接]

18

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2015-10-24
在线时间
38 小时
发表于 2016-2-26 12:16:50 | 显示全部楼层 |阅读模式
3金钱
本帖最后由 db520136 于 2016-2-26 12:49 编辑

定时器当前的计数器是72MHz(72*10^6)/预分频值,当计数器值 = 自动重装载寄存器值时,就产生一个溢出事件!   那么问题是比如计数器值最大是1000,向上计数,装载寄存器的值是5000,计数器的值是到达1000后,是应该为0,重新计数,那么就不能达到装载寄存器的值了。
   这里运行的机制是计数器计数1000 5次,累计计数到了5000,再产生一个溢出事件吗?求大神指点~!~!

最佳答案

查看完整内容[请看2#楼]

不是的, ARR的值是你设置的要记数的总次数 CNT 的值是用由你设置的计数方向决定初始值, 是系统初始化后自动设置的, 比如, 计数方向是向上, ARR 的值你设为5000, 哪初始化后定时器CNT的值一般都是零, 起动定时器后, 从0开始计数到5000-1后溢出中断,CNT 的值自动变化零
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2016-2-26 12:16:51 | 显示全部楼层
db520136 发表于 2016-2-26 15:39
一直计数到65535最大值后,重新重0开始计数,这时候计数到1000然后才算真正产生一个溢出时间,然后计数器 ...

不是的, ARR的值是你设置的要记数的总次数
CNT 的值是用由你设置的计数方向决定初始值, 是系统初始化后自动设置的,

比如, 计数方向是向上, ARR 的值你设为5000, 哪初始化后定时器CNT的值一般都是零,
起动定时器后, 从0开始计数到5000-1后溢出中断,CNT 的值自动变化零
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1606
金钱
1606
注册时间
2015-6-10
在线时间
223 小时
发表于 2016-2-26 12:30:01 | 显示全部楼层
计算器是什么


回复

使用道具 举报

18

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2015-10-24
在线时间
38 小时
 楼主| 发表于 2016-2-26 12:48:10 | 显示全部楼层

我打错字了,是计数器,这个计数器寄存器和重装载值寄存器的关系是怎么一回事,我想搞明白点。
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1606
金钱
1606
注册时间
2015-6-10
在线时间
223 小时
发表于 2016-2-26 13:09:16 | 显示全部楼层
比如说重装载寄存器是5000

计数器记到5000时就会从新装载
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2016-2-26 13:13:56 | 显示全部楼层
db520136 发表于 2016-2-26 12:48
我打错字了,是计数器,这个计数器寄存器和重装载值寄存器的关系是怎么一回事,我想搞明白点。

意思就是,根据计数方向, 向上, 计数器的值从0记数到重装载值-1溢出一次,计数器的值又变回零,从新开始,向下,从重装载值寄存器的值开始减到0溢出,然后计数的值双自动变为重装载值寄存器的值双从新开始。
回复

使用道具 举报

18

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2015-10-24
在线时间
38 小时
 楼主| 发表于 2016-2-26 13:30:54 | 显示全部楼层
likunxue 发表于 2016-2-26 13:13
意思就是,根据计数方向, 向上, 计数器的值从0记数到重装载值-1溢出一次,计数器的值又变回零,从新开 ...

问题是计数器的值就只有1000,重装载寄存器的值是5000,计数器到达1000就重新变成0,重新开始计数,到达不了5000
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2016-2-26 13:32:28 | 显示全部楼层
本帖最后由 likunxue 于 2016-2-26 13:34 编辑
db520136 发表于 2016-2-26 13:30
问题是计数器的值就只有1000,重装载寄存器的值是5000,计数器到达1000就重新变成0,重新开始计数,到达 ...

计数器的值是你设置的还是自动计数的?你是设置为计数模式还是定时方法,时钟源是内部或是外部? 你要说清楚
回复

使用道具 举报

18

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2015-10-24
在线时间
38 小时
 楼主| 发表于 2016-2-26 13:51:23 | 显示全部楼层
likunxue 发表于 2016-2-26 13:32
计数器的值是你设置的还是自动计数的?你是设置为计数模式还是定时方法,时钟源是内部或是外部? 你要说 ...

我打算设置个计算时间功能的,大神能否私聊指教,QQ:736228515   万分感谢
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-2-26 14:27:03 | 显示全部楼层
计数器若配置为向上计数,当CNT计数到ARR后会归零并产生一个事件

CNT的最大值为65535,

你说的情况,若ARR=1000,CNT初始值为5000(比ARR大),
那么CNT会从5000往上继续计数:5000,5001,5002,......,65534,65535,0,1,2...
这期间不会产生任何事件,然后CNT就“正常了”
坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

18

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2015-10-24
在线时间
38 小时
 楼主| 发表于 2016-2-26 15:39:54 | 显示全部楼层
xkwy 发表于 2016-2-26 14:27
计数器若配置为向上计数,当CNT计数到ARR后会归零并产生一个事件

CNT的最大值为65535,

一直计数到65535最大值后,重新重0开始计数,这时候计数到1000然后才算真正产生一个溢出时间,然后计数器又重新变为0,再次计数,是这个意思吗?
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2016-2-26 17:37:34 | 显示全部楼层
本帖最后由 likunxue 于 2016-2-26 17:49 编辑
xkwy 发表于 2016-2-26 14:27
计数器若配置为向上计数,当CNT计数到ARR后会归零并产生一个事件

CNT的最大值为65535,

如你ARR的值是1000 , CNT的初始值, 根据计数方向,只能是 0或1000, 不可能是5000的

/********************************************************************************************
函数名: 设置TIM6初始化函数
调  用: TIM6_int();
参  数: 无
********************************************************************************************/
void MOTOR_TIM6_int(void)
     {
     RCC->APB1ENR|=1<<4;                     //TIM6时钟使能   
     TIM6->ARR = 10000-1;                        //设定计数器自动重装值(10ms中断一次)
     TIM6->PSC = 36;                             //预分频器36,得到1MHZ的计数时钟         
     TIM6->DIER|=1<<0;                        //允许更新中断         
     MY_NVIC_Init(3,0,TIM6_IRQn,4);       //抢占2,子优先级0,组4
     BIT_ADDR((u32)& TIM6->SR,0) = 0;     //清除中断标志  
     BIT_ADDR((u32)& TIM6->CR1,0)= 1;     //开定时器   
     }  


/********************************************************************************************
函 数 名: 定时器中断函数
调    用: 无
参    数: 无
返 回 值: 无           
********************************************************************************************/
void TIM6_IRQHandler(void)
     {
     static u8 led_stut = 50;    //LED 500ms变化一次
     if(TIM6->SR & 0x0001)  //检查是否是溢出中断以经发生过
       {  
       BIT_ADDR((u32)& TIM6->SR,0) = 0;      //清除中断标志  

      if(led_stut -- ==0)
        {
        led_stut = 50;
       LED = ~ LED;
        }
       }
  }

回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-2-26 18:24:36 | 显示全部楼层
likunxue 发表于 2016-2-26 17:37
如你ARR的值是1000 , CNT的初始值, 根据计数方向,只能是 0或1000, 不可能是5000的

/************* ...

刚用了如下代码测试了一下(STM32F103,主频设置为24MHz):

[mw_shl_code=c,true]
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
   
    TIM1->PSC = 60000;
   
    TIM1->ARR = 1000;
   
    TIM1->CR1 = TIM_CR1_CEN;
   
    TIM1->CNT = 2000;
   
    while (1)
    {
    i = TIM1->CNT;
    printf("%d ", i);
    }
    [/mw_shl_code]






得到了如下的运行结果:




2.png




据图看来,似乎当CNT超过ARR后,STM32会迅速地往后走,直到归零,计数频率才正常。

为了验证我的猜想,我又写了如下程序:

[mw_shl_code=c,true]    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
   
    TIM1->PSC = 60000;
   
    TIM1->ARR = 1000;
   
    TIM1->CR1 = TIM_CR1_CEN;
   
    TIM1->CNT = 2000;
   
    for (i = 0; i < 800; i++) arr = TIM1->CNT;
   
    for (i = 0; i < 800; i++) printf("%d ", arr);
   
    printf("\r\n -- \r\n");
   
    while (1)
    {
    i = TIM1->CNT;
    printf("%d ", i);
    }[/mw_shl_code]

这段代码是设置好CNT的初值后,便拼命地将CNT的值实时地存入数组,
然后再统一发送出来,这样就可以避免读一个值,发送一次的延时了
由于芯片RAM有限,只能采集800个样本点,不过结果已经非常明显了:

x.png

可以看出,CNT的值是在向上加的,
即便是直接连续地往RAM搬数据,CNT的值加的也是非常快,
这里猜测,CNT若大于ARR,定时器会全速地递加,直到小于ARR(加到65535溢出)。


-------分割线--------

之前做过飞思卡尔的单片机,它在CNT大于ARR时的处理在手册上明确地写着,就如我前面说的那样;

而STM32对这种情形似乎并没有做介绍,所以我按照之前的想法肆意推断,果然不靠谱。。。
看来以后言行要以实践为准,妄加揣测要不得啊,感谢@likunxue指出错误!


坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2016-2-26 22:06:54 | 显示全部楼层
xkwy 发表于 2016-2-26 18:24
刚用了如下代码测试了一下(STM32F103,主频设置为24MHz):

[mw_shl_code=c,true]

我还真没这样测式过,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-21 04:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表