你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

请教版主和大神们,使用一个定时器作为另一个的预分器

[复制链接]
ypldz23 提问时间:2015-6-18 16:12 /
最近在研究用2个计数器串联计外部脉冲,采用主从模式,主计数器计(TIM1)低16位,从计数器(TIM2)计高16位,大概的配置如下:
        时钟、GPIO配置略
        //定时器TIM1初始化
        TIM_TimeBaseInitStruct.TIM_Period = 0xFFFF;         //自动重装载计数值
        TIM_TimeBaseInitStruct.TIM_Prescaler =0x0000;        //预分频系数0+1,不分频
        TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down; //向下计数        
        TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);               
        //CH2通道输入TI1,上升沿计数,无滤波器
        TIM_TIxExternalClockConfig(TIM1,TIM_TIxExternalCLK1Source_TI1,TIM_ICPolarity_Rising,0x0);        
        TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);
        //010:更新 – 更新事件被选为触发输入(TRGO)。
        //例如,一个主定时器的时钟可以被用作一个从定时器的预分频器。
        TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);        

        //定时器TIM2初始化
        TIM_TimeBaseInitStruct.TIM_Period = 0xFFFF;         //自动重装载计数值
        TIM_TimeBaseInitStruct.TIM_Prescaler =0x0000;        //预分频系数0+1,不分频
        TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down; //向下计数
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);        

        //连接定时器1的TRGO1输出至定时器2,设置TIM2_SMCR寄存器的TS=’000’,
        //配置定时器2为使用ITR1作为内部触发的从模式。
        TIM_SelectInputTrigger(TIM2,TIM_TS_ITR0);
        //然后把从模式控制器置于外部时钟模式1(TIM2_SMCR寄存器的SMS=111);
        //这样定时器2即可由定时器1周期性的上升沿(即定时器1的计数器溢出)信号驱动。
        TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_External1);
        TIM_Cmd(TIM1,ENABLE); //使能TIM1
        TIM_Cmd(TIM2,ENABLE); //使能TIM2

        大致的思路是外部脉冲接TIM1的CH1(PA8),当向下计数溢出时产生更新事件,输出TRGO至TIM2的ITR1,这个TIM1每溢出一次,TIM2计数器减1,在1s中断处理,用前1秒计数减去当前计数,可得出每秒计数即频率值。
       调试的时候,频率不对,然后分别输出TIM1和TIM2的计数器,发现TIM2计数值不对,比如我输入超过65535H在的频率,让TIM1每秒都溢出,但是结果是TIM2的计数值要过几秒以后才减1,感觉像是TIM2没计到似的,怀疑是不是配置有问题,然后各种看参考手册寄存器库函数,也没发现问题,后来想难道是TIM1没有产生更新中断,所以导致TIM2没计到?在TIM1加入更新中断配置,如下:
        //允许更新中断
        TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);        
        //中断优先级NVIC设置
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//0位抢占优先级,4位相应优先级        
        NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;         //
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//
        NVIC_Init(&NVIC_InitStructure);//

        在中断函数里清标志位,结果居然好使了!!!
       接着调试看看是哪的问题,只要我编译上面带//的红色代码的任意一行,都可以,即使没有中断函数。难道是加延迟?加延迟语句也是不行。不知道版主和大神们调没调过“使用一个定时器作为另一个的预分频器”,加一条语句就好使,这也太奇怪了!
收藏 2 评论16 发布时间:2015-6-18 16:12

举报

16个回答
ypldz23 回答时间:2015-6-25 20:40:46
安 发表于 2015-6-25 17:16
楼主你好,还没时间测试这个程序。你先做测试吧。

好的,今天和领导讨论脉冲计数方案,领导说用单片机的计数器做,会占用CPU大量的时间,领导说来一个脉冲计一次,CPU就要中断处理,即使你程序里没有中断,如果要是4路的话,可能会产生意想不到的问题,所以领导建议还是用82C54做,不过我的理解,单片机的计数器和CPU是各干各的吧,计数的时候还要CPU去参与?最终讨论结果是做试验板,两个方案一起验证
ypldz23 回答时间:2015-6-19 09:21:28
安 发表于 2015-6-18 16:32
NVIC在哪儿配置的?建议先配置NVIC,再开启中断。如果能把工程上传一下更好。 ...

#include "tim1clktim2.h"
#include "misc.h"
#include "stm32f10x_tim.h"
#define  TIM_TRGOSource_Update   ((uint16_t)0x0020)
#define  TIM_SlaveMode_External1   ((uint16_t)0x0007)
void TIM1clkTIM2_Int_Init(void)
{
        //定义定时器初始化结构体变量
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);       
       
        //TIM1 CH1(PA8)外部时钟1输入引脚配置
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        //定时器TIM1初始化
        TIM_TimeBaseInitStruct.TIM_Period = 0xFFFF;         //自动重装载计数值
        TIM_TimeBaseInitStruct.TIM_Prescaler =0x0000;        //预分频系数0+1,不分频
        TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//定义在定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分//频比例。,00:tDTS = tCK_INT,不分频
        TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down; //向下计数
       
        //初始化TIM1
        TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);       
       
        //CH2通道输入TI1,上升沿计数,无滤波器
        TIM_TIxExternalClockConfig(TIM1,TIM_TIxExternalCLK1Source_TI1,TIM_ICPolarity_Rising,0x0);       
        TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);
        //010:更新 – 更新事件被选为触发输入(TRGO)。
        //例如,一个主定时器的时钟可以被用作一个从定时器的预分频器。
        TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);
               
//        TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);        //允许更新中断
        //中断优先级NVIC设置
//        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//0位抢占优先级,4位相应优先级       
//        NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;         //-_-
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//-_-
//        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//-_-
//        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//-_-
//        NVIC_Init(&NVIC_InitStructure);//-_-       
          

        //定时器TIM2初始化
        TIM_TimeBaseInitStruct.TIM_Period = 0xFFFF;         //自动重装载计数值
        TIM_TimeBaseInitStruct.TIM_Prescaler =0x0000;        //预分频系数0+1,不分频
        TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//定义在定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分频比例。,00:tDTS = tCK_INT,不分频
        TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down; //向下计数

        //初始化TIM2
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);       
        //连接定时器1的TRGO1输出至定时器2,设置TIM2_SMCR寄存器的TS=’000’,
        //配置定时器2为使用ITR1作为内部触发的从模式。
        TIM_SelectInputTrigger(TIM2,TIM_TS_ITR0);
        //然后把从模式控制器置于外部时钟模式1(TIM2_SMCR寄存器的SMS=111);
        //这样定时器2即可由定时器1周期性的上升沿(即定时器1的计数器溢出)信号驱动。
        TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_External1);

        TIM_Cmd(TIM1,ENABLE); //使能TIM1
        TIM_Cmd(TIM2,ENABLE); //使能TIM2
}
红色代码部分,只要编译其中任意一行,例如第2行,即使在没有开启更新中断的情况下,计数都正常
另外请问版主,输入26MHz,显示25997218Hz,输入27MHz,误差就很大了,难道这是外部输入脉冲的上限?

废鱼 回答时间:2015-6-18 16:32:25
NVIC在哪儿配置的?建议先配置NVIC,再开启中断。如果能把工程上传一下更好。
废鱼 回答时间:2015-6-19 10:03:56
按照手册写两个定时器的时钟频率都是由预分频器对CK_INT除以3(fCK_CNT=fCK_INT/3)。这样TIM1应是24M,TIM2应该是12M。我没有用过这种触发方式,希望和楼主一块探讨一下。我再找个板子一块测试一下。
为什么是EEFOCUS小白 回答时间:2015-6-19 11:09:17
谢谢分享
ypldz23 回答时间:2015-6-23 09:05:29
安 发表于 2015-6-19 10:03
按照手册写两个定时器的时钟频率都是由预分频器对CK_INT除以3(fCK_CNT=fCK_INT/3)。这样TIM1应是24M,TIM2 ...

版主,试验了没?
stary666 回答时间:2015-6-23 10:01:36
位置不重要的
逍遥李 回答时间:2015-6-23 10:09:21
独特的想法
废鱼 回答时间:2015-6-23 10:49:41
ypldz23 发表于 2015-6-23 09:05
版主,试验了没?

不好意思,放假有事。我这有107的板子,你最好把工程上传一下。
ypldz23 回答时间:2015-6-23 14:02:43
安 发表于 2015-6-23 10:49
不好意思,放假有事。我这有107的板子,你最好把工程上传一下。

麻烦版主啦

定时器读脉冲计数.rar

下载

4.7 MB, 下载次数: 242, 下载积分: ST金币 -1

废鱼 回答时间:2015-6-23 14:37:18
如果未能及时回复请见谅。我也是利用业余时间去测试,可能工具还不全。
另外,楼主你看我说的他们的频率了吗?是不是24M的时候比较准确?
ypldz23 回答时间:2015-6-23 15:48:09
安 发表于 2015-6-23 14:37
如果未能及时回复请见谅。我也是利用业余时间去测试,可能工具还不全。
另外,楼主你看我说的他们的频率了 ...

版主客气哈,您说的“手册写两个定时器的时钟频率都是由预分频器对CK_INT除以3(fCK_CNT=fCK_INT/3)。这样TIM1应是24M,TIM2应该是12M”,没找到。。。是在参考手册上吗?刚才又测试了一下,输入22M,比较准确,大概在21997668~21997718
废鱼 回答时间:2015-6-23 16:00:59
使用一个定时器作为另一个定时器的预分频器,第278页。
废鱼 回答时间:2015-6-25 17:16:30
楼主你好,还没时间测试这个程序。你先做测试吧。
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版