5128|8

68

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

我写的tim计数器不准 [复制链接]

写了个精确延时的计时器,精度10us(因为定时器16位), 调用参数为1000000的结果是大概600ms, 差距很大啊,不知道是啥原因。

#define DELAY_TIMER        TIM1

static unsigned int loop;
static int    wait_init = 0;
    
void wait_us(unsigned int us)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    unsigned short wait;
    unsigned short old;
    unsigned short now, diff;
    unsigned int clk;

    if (wait_init == 0)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
        PLL_get_clock(NULL, NULL, &clk);
        TIM_TimeBaseStructure.TIM_Period = 60000-1;      
        TIM_TimeBaseStructure.TIM_Prescaler = clk/100000 - 1; //精度10us
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(DELAY_TIMER, &TIM_TimeBaseStructure);
        TIM_Cmd(DELAY_TIMER, ENABLE);
        
        loop      = 60000;
        wait_init = 1;
    }

    if (us >= 6000000)
        us = 5999999;

    wait = (unsigned short)(us/10);
    old = TIM_GetCounter(DELAY_TIMER);
    while(1)
    {
        now = TIM_GetCounter(DELAY_TIMER);
        
        if (now >= old)
            diff = now - old;
        else
            diff = loop - old + now;
            
        if (diff > wait)
            break;
    }
}
此帖出自stm32/stm8论坛

最新回复

                                 非常感谢香版,我的定时器的配置是100us计时一次,计数peried是60000,就是说6s环回计数,所以有可能发生后取的时钟比先取的时钟小的问题。现在下面这个代码定时基本准了void wait_us(unsigned int us){    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;    unsigned short wait;    unsigned short old;    unsigned short now, diff;    unsigned int clk;    if (wait_init == 0)    {        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);        PLL_get_clock(NULL, NULL, &clk);        TIM_TimeBaseStructure.TIM_Period = 60000-1;              TIM_TimeBaseStructure.TIM_Prescaler = clk/10000 - 1; //精度100us,这里改了        TIM_TimeBaseStructure.TIM_ClockDivision = 0;        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        TIM_TimeBaseInit(DELAY_TIMER, &TIM_TimeBaseStructure);        TIM_Cmd(DELAY_TIMER, ENABLE);                loop      = 60000;        wait_init = 1;    }    if (us >= 6000000)        us = 5999999;    wait = (unsigned short)(us/100);  //这里改了    old = TIM_GetCounter(DELAY_TIMER);    while(1)    {        now = TIM_GetCounter(DELAY_TIMER);                if (now >= old)            diff = now - old;        else            diff = loop - old + now;                    if (diff > wait)            break;    }}   详情 回复 发表于 2009-5-14 08:51
点赞 关注
 

回复
举报

81

帖子

0

TA的资源

一粒金砂(初级)

沙发
 

clk?????

                                  TIM_TimeBaseStructure.TIM_Prescaler = clk/100000 - 1; //精度10us
此帖出自stm32/stm8论坛
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

如果调用,我觉得不要用库函数了,直接寄存器操作吧。

                                 初始化用库还可以。。。。
此帖出自stm32/stm8论坛
 
 

回复

69

帖子

0

TA的资源

一粒金砂(中级)

4
 

clk大于100000吗?别出来0或负数了。。

                                  
此帖出自stm32/stm8论坛
 
 
 

回复

55

帖子

0

TA的资源

一粒金砂(初级)

5
 

我是按库中的例子定时的,发现很准。

                                  
此帖出自stm32/stm8论坛
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

6
 

...

       PLL_get_clock(NULL, NULL, &clk);
--------------
我自己写的函数,clk取出来是apb2 clk,数字是72000000,就是72M
此帖出自stm32/stm8论坛
 
 
 

回复

58

帖子

0

TA的资源

一粒金砂(初级)

7
 

学习

                                  
此帖出自stm32/stm8论坛
 
 
 

回复

89

帖子

0

TA的资源

一粒金砂(初级)

8
 

老兄啊,请解释一下你的程序,我怎么看不懂?

while 里面什么时候才能有 (diff > wait) 的时候?

变量old在循环里不会变化,可以假定它的值为0。

变量now始终是读出的当前计数器的内容,最大不会超过TIM_Period。

变量diff或者 = now - old,或者 = loop - old + now,最大不过60000 + 60000-1=115999;请你完成接下来的分析吧。
此帖出自stm32/stm8论坛
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

9
 

...

非常感谢香版,我的定时器的配置是100us计时一次,计数peried是60000,就是说6s环回计数,所以有可能发生后取的时钟比先取的时钟小的问题。现在下面这个代码定时基本准了

void wait_us(unsigned int us)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    unsigned short wait;
    unsigned short old;
    unsigned short now, diff;
    unsigned int clk;

    if (wait_init == 0)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
        PLL_get_clock(NULL, NULL, &clk);
        TIM_TimeBaseStructure.TIM_Period = 60000-1;      
        TIM_TimeBaseStructure.TIM_Prescaler = clk/10000 - 1; //精度100us,这里改了
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(DELAY_TIMER, &TIM_TimeBaseStructure);
        TIM_Cmd(DELAY_TIMER, ENABLE);
        
        loop      = 60000;
        wait_init = 1;
    }

    if (us >= 6000000)
        us = 5999999;

    wait = (unsigned short)(us/100);  //这里改了
    old = TIM_GetCounter(DELAY_TIMER);
    while(1)
    {
        now = TIM_GetCounter(DELAY_TIMER);
        
        if (now >= old)
            diff = now - old;
        else
            diff = loop - old + now;
            
        if (diff > wait)
            break;
    }
}
此帖出自stm32/stm8论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
立即报名 | 2025 瑞萨电子工业以太网技术日即将开启!
3月-4月 深圳、广州、北京、苏州、西安、上海 走进全国6城
2025瑞萨电子工业以太网技术巡回沙龙聚焦工业4.0核心需求,为工程师与企业决策者提供实时通信技术最佳解决方案。
预报从速,好礼等您拿~

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表