0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MM32F5270 TIM精准脉冲数量输出

灵动MM32MCU 来源:灵动MM32MCU 作者:灵动MM32MCU 2022-12-09 10:09 次阅读

脉冲信号用于设备控制是比较常见的,但在一些情况下,我们希望精准的控制脉冲的数量以实现对运动的精确控制,实现的方式也有多种多样。定时器是单片机内部最基础且常用的外设,有着非常丰富的功能,如输入功能(测量输入信号的脉冲宽度、频率,PWM 输入等),输出功能(PWM 输出、死区时间可编程的互补输出、 单脉冲模式输出等) ,容易想到使用定时器输出PWM来实现此类操作。

MM32F5270系列集成有丰富的外设模块,其中定时器部分包括 2 个 16 位高级定时器, 2 个 16 位通用定时器、 2 个 32 位通用定时器, 2 个 16 位基础定时器和1 个低功耗定时器。以TIM1为例,该模块主要由输入单元、输出单元、时基单元、捕获/比较模块、刹车单元等结构组成,功能框图如下:

7d80cbda-7709-11ed-8abf-dac502259ad0.png

这里以MM32F5270定时器应用为例,介绍几种常用的精准输出脉冲数量的方法:

1中断计数方式

定时器配置为PWM输出模式,在PWM中断程序中计数,判断PWM输出次数达到设定值时,停止PWM输出。

中断计数的方式实现起来简单,但也存在明显的缺点。当PWM频率较高时,频繁的中断将影响程序运行的效率,占用大量的MCU资源,这在大多数情况下是不可接受的。以下几种方式较为优化。

2定时器单脉冲重复计数

定时器单脉冲输出是定时器比较输出中的一种模式,在定时器比较输出模式的基础上进行配置。单脉冲模式(OPM)下,计数器响应一个激励,产生一个脉宽可调的脉冲。配置 TIMx_CR1 寄存器的OPM=1,选择单脉冲模式。

7daec9c2-7709-11ed-8abf-dac502259ad0.png

单脉冲模式可以使定时器输出1个脉冲,而重复计数器可以用来调整更新事件产生的频率。

边沿对齐模式下,向上计数时,重复计数器在计数器每次上溢时递减;向下计数时,重复计数器在计数器每次下溢时递减。中央对齐模式下,重复计数器在计数器上溢和下溢时皆递减。通过配置 TIMx_RCR 寄存器的 REP 来调整更新事件产生的频率,重复计数器在 REP+1 个计数周期后产生更新事件。

7dc99be4-7709-11ed-8abf-dac502259ad0.png

配置TIM1输出PWM,使能单脉冲模式,配置REP(重复计数器的值)为9,即TIM1在输出10个脉冲后发生更新事件,相关代码如下:

voidTIM1_Monopulse_Init(u16arr,u16psc)
{
TIM_TimeBaseInitTypeDefTIM_TimeBaseStruct;
TIM_OCInitTypeDefTIM_OCInitStruct;
TIM_ICInitTypeDefTIM_ICInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2ENR_TIM1,ENABLE);
TIM_DeInit(TIM1);
TIM_TimeBaseStructInit(&TIM_TimeBaseStruct);
TIM_TimeBaseStruct.TIM_Period=arr;
TIM_TimeBaseStruct.TIM_Prescaler=psc;
TIM_TimeBaseStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStruct.TIM_RepetitionCounter=9;
TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStruct);

TIM_OCStructInit(&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse=arr/2;
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_OCIdleState=TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1,&TIM_OCInitStruct);
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1,ENABLE);
TIM_SelectOnePulseMode(TIM1,TIM_OPMode_Single);
TIM_SetCounter(TIM1,0);
TIM_CtrlPWMOutputs(TIM1,ENABLE);

TIM_Cmd(TIM1,ENABLE);
}

逻辑分析仪接PA8(程序中配置PA8作为TIM1_CH1),观测输出波形如下:

7e1ae1c0-7709-11ed-8abf-dac502259ad0.png

由于REP只有8位,所以它最大是255,当然也可以进行一些判断后再次赋值,目前只有高级定时器具有重复计数功能。

3DMA方式

使用DMA功能更新PWM的输出,DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。它允许不同速度的硬件装置来沟通,而不需要依赖于MPU的大量中断负载。该方式占用很少的MCU资源,实现脉冲发送的精确控制。

通过设置DMA传输数据的数量,可以控制发送的脉冲数。通过设置不同的装载值和顺序,可以使用不同频率和脉宽。

TIMx_DCR 和 TIMx_DMAR 寄存器跟 DMA 模式相关。DMA 控制器的目标是唯一的,必须指向TIMx_DMAR 寄存器。开启 DMA 使能后,在给定的 TIMx 事件发生时, TIMx 会给 DMA 发送请求。对TIMx_DMAR 寄存器的每次写操作都被重定向到一个 TIMx 寄存器。

TIMx_DMAR 连续模式 DMA 地址寄存器:

7e4013aa-7709-11ed-8abf-dac502259ad0.png

TIMx_DCR DMA 控制寄存器:

7e5cbc1c-7709-11ed-8abf-dac502259ad0.png

程序中配置TIM1的更新周期为10ms。

TIM1_PWM_Init(10000-1,SystemCoreClock/1000000-1);

定义一个数组,元素的数量表示可以控制发送的脉冲数,元素的值表示脉宽。

staticu16data[10]={1000,2000,3000,4000,5000,6000,7000,8000,9000,0};

配置TIM1输出PWM,相关代码同上,使能COM的DMA请求,配置DMA初始化,使能DMA传输完成中断,TIM1_CH1对应DMA1_Channel2。

voidTIM1_DMA_Init(void)
{
DMA_InitTypeDefDMA_InitStruct;
DMA_Channel_TypeDef*channel;
channel=DMA1_Channel2;
RCC_DMA_ClockCmd(DMA1,ENABLE);

DMA_DeInit(channel);
DMA_StructInit(&DMA_InitStruct);
//Transferregisteraddress
DMA_InitStruct.DMA_PeripheralBaseAddr=(u32)&(TIM1->CCR1);
//Transfermemoryaddress
DMA_InitStruct.DMA_MemoryBaseAddr=(u32)data;
//Transferdirection,frommemorytoregister
DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize=10;
DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
//Transfercompletedmemoryaddressincrement
DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_Mode=DMA_Mode_Normal;//DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority=DMA_Priority_High;
DMA_InitStruct.DMA_M2M=DMA_M2M_Disable;
DMA_InitStruct.DMA_Auto_reload=DMA_Auto_Reload_Disable;
DMA_Init(channel,&DMA_InitStruct);

DMA_ITConfig(channel,DMA_IT_TC,ENABLE);
DMA_Cmd(DMA1_Channel2,ENABLE);
}

DMA中断服务子程序:

voidDMA1_Channel2_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC2)){
DMA_ClearITPendingBit(DMA1_IT_TC2);
TIM_Cmd(TIM1,DISABLE);
}
}

逻辑分析仪接PA8(程序中配置PA8作为TIM1_CH1),观测输出波形如下:

7e78c6a0-7709-11ed-8abf-dac502259ad0.png

输出9个脉冲,脉宽分别为10%、20%、30%......90%。

DMA方式算是一个很确定的方式,不会丢失脉冲。当需要发送较多数量的脉冲时,则可以使用DMA传输完成中断中切换DMA传输的数据起始地址及发送数量。

4主从模式

定时器同步功能可以配置多个定时器在内部相连。

利用定时器的主从模式,即一个是主定时器,一个是从定时器,由主定时器输出脉冲信号,主定时器产生的更新触发传递给从定时器进行计数,溢出时触发从定时器的中断服务函数。通过主从定时器进行设定,不占用主程序时钟,且能精准控制。

主从关系要遵循参考手册中所提供的配置,TIMx之间的互联:

7ea82792-7709-11ed-8abf-dac502259ad0.png

参考TIMx_CR2和TIMx_SMCR寄存器配置主从模式。

TIMx_CR2 控制寄存器 2:

7ecf52ae-7709-11ed-8abf-dac502259ad0.png

TIMx_SMCR 从模式控制寄存器:

7f04f512-7709-11ed-8abf-dac502259ad0.png7f2249fa-7709-11ed-8abf-dac502259ad0.png

配置TIM1为主模式,输出PWM:

voidTIM1_Master_Init(u16arr,u16psc)
{
TIM_TimeBaseInitTypeDefTIM_TimeBaseStruct;
TIM_OCInitTypeDefTIM_OCInitStruct;

RCC_APB2PeriphClockCmd(RCC_APB2ENR_TIM1,ENABLE);

TIM_TimeBaseStructInit(&TIM_TimeBaseStruct);
TIM_TimeBaseStruct.TIM_Period=arr;
TIM_TimeBaseStruct.TIM_Prescaler=psc;
TIM_TimeBaseStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStruct.TIM_RepetitionCounter=0;
TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStruct);

TIM_OCStructInit(&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse=499;
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OC1Init(TIM1,&TIM_OCInitStruct);

TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1,ENABLE);
TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);
TIM_SelectOutputTrigger(TIM1,TIM_TRIGSource_Update);

TIM_SetCounter(TIM1,0);
TIM_CtrlPWMOutputs(TIM1,ENABLE);
TIM_Cmd(TIM1,ENABLE);
}

配置TIM3为从模式,选择ITR0触发(对应内部触发源TIM1),使能更新中断:

voidTIM3_Slave_Init(u16arr,u16psc)
{
TIM_TimeBaseInitTypeDefTIM_TimeBaseStruct;
RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM3,ENABLE);

TIM_TimeBaseStructInit(&TIM_TimeBaseStruct);
TIM_TimeBaseStruct.TIM_Period=arr;
TIM_TimeBaseStruct.TIM_Prescaler=psc;
TIM_TimeBaseStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStruct.TIM_RepetitionCounter=0;
TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStruct);

TIM_ARRPreloadConfig(TIM3,DISABLE);

TIM_SelectInputTrigger(TIM3,TIM_TS_ITR0);
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_External1);
TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);

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

TIM_SetCounter(TIM3,0);
TIM_Cmd(TIM3,ENABLE);
}

TIM3控制脉冲数量,此处设置为10:

TIM3_Slave_Init(10,0);

TIM3中断服务子程序:

voidTIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET){
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
TIM_CtrlPWMOutputs(TIM1,DISABLE);
TIM_Cmd(TIM1,DISABLE);
TIM_Cmd(TIM3,DISABLE);
TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);
}
}

逻辑分析仪接PA8(程序中配置PA8作为TIM1_CH1),观测输出波形如下:

802da2cc-7709-11ed-8abf-dac502259ad0.png

TIM1输出10个脉冲后停止。

以上简要列举了几种控制脉冲数量输出的方式,以MM32F5270为例演示其实现的可行性。在实际应用中,几种方法各有优缺点,具体的方式还需要根据资源和需求进行综合考虑。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • PWM
    PWM
    +关注

    关注

    114

    文章

    5181

    浏览量

    213798
  • 定时器
    +关注

    关注

    23

    文章

    3246

    浏览量

    114719
  • Tim
    Tim
    +关注

    关注

    0

    文章

    81

    浏览量

    17893
  • 脉冲信号
    +关注

    关注

    6

    文章

    398

    浏览量

    36956

原文标题:灵动微课堂 (第239讲)|MM32F5270 TIM 精准脉冲数量输出

文章出处:【微信号:MindMotion-MMCU,微信公众号:灵动MM32MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    MM32F5270平台ADC注入通道的单周期采样的实现

    MM32F5270的ADC可配置4个注入通道来扩展转换通道,那么可进行转换的通道最多可达20个。
    的头像 发表于 06-01 17:25 1497次阅读
    <b class='flag-5'>MM32F5270</b>平台ADC注入通道的单周期采样的实现

    一文解析MM32F5270开发板+PWM测试与调制

    1、MM32F5270开发板+ PWM测试与调制  PWM接口引脚  MM32F5270开发板有引出PWM引脚给我们,我们可以直接使用就行。  主要代码部分如下  2.1 hal_tim
    发表于 09-06 11:24

    MM32F5270是如何通过MindSwitch和CLU实现可任意编程外设间互联系统的

    支持 OR-OR 逻辑操作。下表整理了 MM32F5270 中的所有源和目标的数量和类别,具体列表可参考芯片的用户手册。组合逻辑单元 CLU上文已经提到过 MindSwitch 中内置了 4 个
    发表于 09-06 15:13

    介绍几种MM32F5270定时器常用的精准输出脉冲数量的方法

    单元、输出单元、时基单元、捕获/比较模块、刹车单元等结构组成,功能框图如下:这里以MM32F5270定时器应用为例,介绍几种常用的精准输出脉冲数量
    发表于 12-30 16:28

    MM32F5270总线架构设计

    本文介绍了MM32F5270 中所采用的多并发总线架构,并通过带显示的音频播放器的实例说明了该架构在实际应用中所能达到的吞吐率提升效果。
    的头像 发表于 05-11 11:15 2170次阅读
    <b class='flag-5'>MM32F5270</b>总线架构设计

    基于MM32F5270控制器的I2S音频播放

    MM32F5270 系列控制器支持 I2S 总线接口,本章节在接下来会对 MM32F5270 I2S进行介绍,并使用 MM32F5270 和 CS4344 芯片进行 I2S 通信来演示播放一段声音。
    的头像 发表于 09-16 10:39 2353次阅读

    MM32F5270】Keil开发环境搭建

    本文是对MM32F5270相关的灵动官网资料和社区现有几篇环境搭建帖的整理和总结。详细且完整的记录了——如何从零搭建MM32F5270 Keil开发环境以及如何编译运行MM32F5270 SDK中
    的头像 发表于 11-06 16:14 2748次阅读
    【<b class='flag-5'>MM32F5270</b>】Keil开发环境搭建

    MM32F5270 产品手册(中文版)

    MM32F5270 产品手册(中文版)
    发表于 02-23 18:45 0次下载
    <b class='flag-5'>MM32F5270</b> 产品手册(中文版)

    MM32F5270 产品手册(英文版)

    MM32F5270 产品手册(英文版)
    发表于 02-23 18:45 0次下载
    <b class='flag-5'>MM32F5270</b> 产品手册(英文版)

    MM32F5270 用户手册(中文版)

    MM32F5270 用户手册(中文版)
    发表于 02-23 18:46 0次下载
    <b class='flag-5'>MM32F5270</b> 用户手册(中文版)

    MM32F5270 用户手册(英文版)

    MM32F5270 用户手册(英文版)
    发表于 02-23 18:46 0次下载
    <b class='flag-5'>MM32F5270</b> 用户手册(英文版)

    MM32F5270 勘误表(中文版)

    MM32F5270 勘误表(中文版)
    发表于 02-23 18:47 0次下载
    <b class='flag-5'>MM32F5270</b> 勘误表(中文版)

    MM32F5270 勘误表(英文版)

    MM32F5270 勘误表(英文版)
    发表于 02-23 18:48 0次下载
    <b class='flag-5'>MM32F5270</b> 勘误表(英文版)

    MM32F5270平台ADC注入通道的单周期采样的实现

    MM32F5270的ADC可配置4个注入通道来扩展转换通道,那么可进行转换的通道最多可达20个。
    的头像 发表于 05-26 09:32 919次阅读
    <b class='flag-5'>MM32F5270</b>平台ADC注入通道的单周期采样的实现

    基于MM32F5270的I2S音频播放

    基于MM32F5270的I2S音频播放
    的头像 发表于 10-30 17:13 1183次阅读
    基于<b class='flag-5'>MM32F5270</b>的I2S音频播放