我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 1078|回复: 3

[产品新知] 定时器的使用方法 MM32主/从定时器同步与精准定时操作实例

[复制链接]

该用户从未签到

478

主题

243

回帖

1385

积分

二级逆天

积分
1385

终身成就奖特殊贡献奖

发表于 2021-1-18 09:25:34 | 显示全部楼层 |阅读模式
定时器同步
在MM32L073一个定时器有4通道PWM输出,有客户在应用中需要使用两个定时器控制6路PWM输出,为了使两个定时器的PWM输出相同的波形,所以需要两个定时器实现同步功能。
所有TIMx定时器在内部相连,用于定时器同步或链接。当一个定时器处于主模式时,它可以对另一个处于从模式的定时器的计数器进行复位、启动、停止或提供时钟等操作。
MM32L073的每个定时器都可以由另一个定时器触发启动定时器一般是通过软件设置而启动,MM32L073的每个定时器也可以通过外部信号触发而启动,还可以通过另外一个定时器的某一个条件被触发而启动。这里所谓某一个条件可以是定时到时、定时器超时、比较成功等许多条件。这种通过一个定时器触发另一个定时器的工作方式称为定时器的同步,发出触发信号的定时器工作于主模式,接受触发信号而启动的定时器工作于从模式。
主/从定时器的例子
为了实现两个定时器完全同步,使用一个定时器作为另一个定时器的预分频器。可以配置定时器1作为定时器3的预分频器。
参考上图,进行下述操作:
配置定时器1为主模式,它可以在每一个更新事件UEV时输出一个周期性的触发信号。在TIM1_CR2寄存器的MMS=‗010时,每当产生一个更新事件时在TRGO1上输出一个上升沿信号。
连接定时器1的TRGO1输出至定时器3,设置TIM3_SMCR寄存器的TS=‗000,配置定时器3为使用ITR1作为内部触发的从模式。
然后把从模式控制器置于外部时钟模式1(TIM3_SMCR寄存器的SMS=111);这样定时器3即可由定时器1周期性的上升沿(即定时器1的计数器溢出)信号驱动。
最后,必须设置相应(TIMx_CR1寄存器)的CEN位分别启动两个定时器。

注:如果OCx已被选中为定时器1的触发输出(MMS=1xx),它的上升沿用于驱动定时器3的计数器。
voidTim1_Init(u16Prescaler,u16Period)
{
TIM_TimeBaseInitTypeDefTIM_StructInit;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
TIM_StructInit.TIM_Period=Period;
TIM_StructInit.TIM_Prescaler=Prescaler;
TIM_StructInit.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_StructInit.TIM_CounterMode=TIM_CounterMode_Up;
TIM_StructInit.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM1,&TIM_StructInit);

TIM_ClearFlag(TIM1,TIM_FLAG_Update);
}

voidTIM3_Init(u16psc,u16arr)
{
TIM_TimeBaseInitTypeDefTIM_StructInit;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_StructInit.TIM_Period=arr;
TIM_StructInit.TIM_Prescaler=psc;
TIM_StructInit.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_StructInit.TIM_CounterMode=TIM_CounterMode_Up;
TIM_StructInit.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_StructInit);

TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Enable);
TIM_SelectInputTrigger(TIM1,TIM_TS_ITR2);
TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Gated);
TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);

TIM3->CNT=0;
TIM1->CNT=0;

TIM_Cmd(TIM1,ENABLE);
delay_ms(300);

TIM_Cmd(TIM3,ENABLE);
delay_ms(300);
}

2、定时器精准延时
在应用中,有的需要精准的定时功能,在客户支持过程中,发现有的客户对定时器的基本定时功能的理解有些偏差,今天将与大家一起使用定时器的基本定时功能。
我们把定时器设置自动重装载寄存器ARR的值为1000,设置时钟预分频器为47,则驱动计数器的时钟:CK_CNT=CK_INT/(47+1)=1M,则计数器计数一次的时间等于:1/CK_CNT=1us,当计数器计数到ARR的值1000时,产生一次中断,则中断一次的时间为:1/CK_CNT*ARR=1ms。
voidTim2_UPCount_test(void)
{
TIM_TimeBaseInitTypeDefTIM_StructInit;
NVIC_InitTypeDefNVIC_StructInit;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_StructInit.TIM_Period=1000;
TIM_StructInit.TIM_Prescaler=47;
TIM_StructInit.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_StructInit.TIM_CounterMode=TIM_CounterMode_Up;
TIM_StructInit.TIM_RepetitionCounter=0;

TIM_TimeBaseInit(TIM2,&TIM_StructInit);
NVIC_StructInit.NVIC_IRQChannel=TIM2_IRQn;
NVIC_StructInit.NVIC_IRQChannelPriority=1;
NVIC_StructInit.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_StructInit);

TIM_ClearFlag(TIM2,TIM_FLAG_Update);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

TIM_Cmd(TIM2,ENABLE);
}

定时器中断一次的时间是1ms,我们定义一个全局变量ucTim2Flag,每当进一次中断的时候,让ucTim2Flag来记录进入中断的次数。如果我们想实现一个1s的定时,我们只需要判断time是否等于1000即可,1000个1ms就是1s。然后把ucTim2Flag清0,重新计数,以此循环往复。

voidTIM2_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
ucTim2Flag++;
}
回复

使用道具 举报

该用户从未签到

5

主题

675

回帖

41

积分

二级逆天

积分
41

社区居民忠实会员终身成就奖

QQ
发表于 2021-1-18 09:56:14 | 显示全部楼层
回复

使用道具 举报

  • TA的每日心情

    6 天前
  • 签到天数: 70 天

    [LV.6]常住居民II

    50

    主题

    2241

    回帖

    2801

    积分

    二级逆天

    积分
    2801

    终身成就奖优秀斑竹奖

    QQ
    发表于 2021-1-18 10:06:38 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    160

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖原创先锋奖

    发表于 2021-1-18 10:46:45 | 显示全部楼层
    回复

    使用道具 举报

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

    本版积分规则

    论坛开启做任务可以
    额外奖励金币快速赚
    积分升级了


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    平平安安
    TOP
    快速回复 返回顶部 返回列表