zero99 发表于 2017-11-28 10:05:17

(已公布)狂欢节答题(附加题)

附加题:
自行选型一个STM32的单片机,要求输出4路可控制脉冲数的高速脉冲,必须要尽可能的节省CPU时间,而且不能频繁的进入中断(只需提供解决方案,不用代码)


虽然是附加题,还是希望大家能参与进来。或者,你最认同哪三位的答案呢?



答案如下:
利用主从定时器协助的方式来进行对STM32外设的极致使用,答DMA是要扣分的。(采用DMA方式,在高速的时候会过多的占用总线时间,不符合题目中的尽可能的节省CPU时间的目地)
1、自行选型一款STM32单片机,考得选型能力,根据项目要求选出一款比较合适的芯片
2、输出4路高速脉冲并且脉冲数可控,节省CPU,并且少进入中断,考的是对STM32的外设理解能力以及主从定时器协助能力


本题最佳答案为:@nyszx,其次是:@dsjsif 和 @landeng1986

@dsjsif 虽然也指出了定时器的协助,但是并没有实际指出定时器如何具体的搭配和解决思路
@landeng1986 虽然指出了主从搭配,然而并没有从实际上进行设计题目所问道的实际解决方案
@wolfgang2015的回复有待商榷,@zeropandragon 回答不对


https://www.stmcu.org.cn/module/forum/data/attachment/forum/201711/24/144432xt1c9rtj9t9ib7db.png




本帖为 #狂欢节第二波# 活动的附加题,也是最后一题,决定前3的最终排名和DISC归属

本题为开放性题目,届时会根据答题结果,进行点评&排名


答题时间:2017年11月28日 10:00-11月30日 10:00 (两天)


本题由@nyszx、@landeng1986、@Zeyo_Pendragon、@wolfgang2015、@dsjsjf 5位大佬参加,其他网友也可以参加(但不计分)


另外,
请在第二波活动中答对3题及以上(即积分榜蓝色区域)的小伙伴,请速速把STM32中文官网注册邮箱私信给我(通过第一波活动的无需再次提供~)
查看答题积分榜>>(帖末)




http://upload.semidata.info/www.eefocus.com/ckeditor/images/roadshow%20review.jpg






zero99 发表于 2017-11-28 10:05:47

MARK MARK MARK

wolfgang2015 发表于 2017-11-28 11:21:12

本帖最后由 wolfgang2015 于 2017-11-28 18:02 编辑

自行选型一个STM32的单片机,要求输出4路可控制脉冲数的高速脉冲,必须要尽可能的节省CPU时间,而且不能频繁的进入中断(只需提供思路&方法,不用代码)

题目思路分析:
   1、“输出4路可控脉冲“, 需要用到的MCU定时器资源进行脉宽调制(PWM),所以,高级定时器 T1、T8,及普通定时器T2~T5就能满足;
   2、"必须要尽可能的节省CPU时间,而且不能频繁的进入中断",            需要降低控制MCU控制寄存器频度和数量,将MCU的工作量释放出来,这里选用DMA进行数据传递;选择DMA就需要MCU的参考对定时器进行选型,要选择具备4通道DMA输出的定时器方可使用,比如Timer1、Timer3。其他某些DMA通道缺失或者通道不够的定时器需加以排除;
             另外,不能频繁的进入中断,而且是满足"高速"最先可以使用DMA数组的方式进行,将发送脉冲数组+1的数量(数组最后一个字为0,表示停发脉冲)作为DMA数组;如果发送高速脉冲数超过65535个,则可以使用DMA传输完成中断中切换DMA传输的数据起始地址及发送数量,继续发送。

   3、使用CubeMx将芯片选择、定时器选择、DMA选择好,使用HAL方式输出代码,让代码具备
以下功能关键点:
   以选用的MCU是STM32F401RE(84MHz主频设置)为例:
   1)在CubeMx界面中,选中Tim3定时器中Channel1()、Channel2()、Channel3()、Channel4() 的下拉框,分别配置 PWM Generation CH1、PWM Generation CH2、PWM Generation CH3、PWM Generation CH4。

   2)在TIM3配置界面里,将Prescaler设置为84-1,Counter Period设置为1000-1, 脉宽调制的波形频率为1KHz。如果高速,可以调节分频系数,增加DMA队列中需发送脉冲数量,以达到高速脉冲频率的发送要求。

   3)占空比默认为0,极性为低电平;

   4)DMA设置中,分别将TIM3_CH1、TIM3_CH2、TIM3_CH3、TIM3_CH4 对应的DMA数据流(DMAx Stream);

   5)生成代码后,观察stm32f4xx_hal_msp.c 文件中中 HAL_TIM_PWM_MspInit(......)函数中具备 DMA和Timer的相关配置函数;

   6) PWM输出的数量通过DMA数组的方式来定义,能降低对中断的调用次数。         启动DMA命令 HAL_TIM_PWM_Start_DMA(......)
         或者用 HAL_TIM_PWM_Start() 配合 HAL_TIM_DMABurst_WriteStart()函数来实现脉冲数的发送。









Zeyo_Pendragon 发表于 2017-11-28 12:11:35

STM32L432KC
采用TIM2的4个比较/捕获通道加DMA可以产生出4路不同频率和占空比的方波
1)脉冲宽度一致,DMA地址不增加;
2)脉冲频率不同,设置不同的装载值,PWM使用单次触发。
3)发送的脉冲数超过65535个,使用DMA传输完成中断切换DMA传输的数据起始地址及发送数量,继续发送

ddllxxrr 发表于 2017-11-28 13:56:03

用DMA就行,不占用CPU时间

landeng1986 发表于 2017-11-29 01:07:29

选择STM32F302R8T6,前面电机控制培训刚用过的。
主要参考应用笔记AN4776,利用STM32定时器输出指定脉冲个数。
STM32定时器的单脉冲输出功能,让定时器在某个事件触发后的一段时间产生指定脉宽的单脉冲信号。
计数器的启动可由从模式控制器控制,可由比较输出模式或PWM输出模式来产生波形。

例:通过使用STM32定时器的主从模式实现周期性地输出指定数目的脉冲:
TIMER2与TIMER1主从连接,实现周期性的输出5个脉冲。
TIMER2 配置为主触发模式,触发TIMER1的计数;
TIMER1 配置为从单脉冲输出模式;TIM1_RCR=4;

利用这个方法经过改造可实现输出多路可控制脉冲数的高速脉冲。


我刚入门不久,边参与边学习,班门弄斧了:P

zero99 发表于 2017-11-29 12:55:07

顶一下

nyszx 发表于 2017-11-29 21:46:51

题目分析:自行选择一个STM32,为啥不来点干脆的,直接指定型号,毕竟STM32产品线上有11个系列,将近800个型号,从中选择还是难度的,还好,ST提供了很多工具,比如:STMCUFinder、STM32CubeMX可以大大简化选型难度。要求4路可控脉冲数的高速脉冲,节省CPU时间,而且不能频繁的进入中断。重点来了,4路(独立?)、可控脉冲数、高速脉冲(有多高?),节省CPU,中断少。第一反应就想到了STM32强大的外设:定时器/HRTIM,通过外设自己工作才能不耽误CPU。因此通过工具搜索初步定下来在速度快常用的F3/F4以及F7/H7系列,F7/H7对于我这个菜鸟来说太高大上,就在F3/F4中选择,发现F3在电机控制上非常厉害,有强大的HRTIM,但是此题要求的是可控高速脉冲,发现F3在此处似乎并不太合适,F3适合在高精度“花样”控制中,也许是自己低估它了,反正放弃了,最终选择了F4系列。以上废话可忽略,以下才是重点。解决方案:使用多个定时器,工作在主从模式,主定时器负责高速脉冲输出,工作在主模式,设定为PWM 模式1,CH1输出脉冲,脉宽设定为50%占空比,频率可调,开启自动装载功能,设定MMS用作从定时器的预分频器。从定时器负责计数,工作在从模式,选择内部触发,并开启UIE, 在中断中控制主定时器的启停。从来没这么用过,第一次,也算是为了学习,为了简单,选择4个主定时器、4个从定时器,这样一算就要8个定时器,还好,STM32最多的定时器有18个之多,看F4系列的参考手册,可以这样组合:3主、2从;4主5从;10主、9从;13主12从;这样组合出4路独立的组合,而且都使用ITR2触发。除了F411有11个定时器外F4其他系列都有17个定时器,且APB1 Timer 时钟高达84MHzAPB2Timer 时钟高达168MHz 主频达到168MHz完全胜任,因便宜的F407系列就能满足。方案验证:手头有一块F411RE的NUCLEO板,因此就拿他进行验证。查看数据手册F411有1、2、3、4、5、9、10、11,除了9以为都支持主模,除了10、11都支持从模式,遗憾的是只能有三组满足,不过用于验证还是可以的,一组能实现,其他的也类似,输出100KHz高速脉冲,题目没要求多少算高速,按PLC常规的脉冲输出有20Khz\100Khz\200Khz\400Khz,所以就按100KHz做应该满足题目要求吧。部分测试代码(HCLK=APB1 Timer =APB2 Timer=100MHz ):TIM3主、TIM2从
void TIM2_IRQHandler(void)
{
       
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
                TIM3->CR1 &= (uint16_t)~TIM_CR1_CEN;
                TIM3->CCER &= (uint16_t)~0x001;
                TIM2->CNT=0;
                TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
                TIM_Cmd(TIM2, DISABLE);
        }
       
}

void OutputPulseOne(u32 Cycle,u32 PulseNum)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
    TIM_OCInitTypeDefTIM_OCInitStructure;
                NVIC_InitTypeDef NVIC_InitStructure;
       
                //脉冲管脚配置
                RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
               
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 ;             //TIM3_CH1输出脉冲
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
                GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
                GPIO_Init(GPIOA, &GPIO_InitStructure);

                GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);
       
                //主定时器配置TIM3
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
       
                TIM_TimeBaseStructure.TIM_Period = Cycle-1;                                                                 //脉冲频率
                TIM_TimeBaseStructure.TIM_Prescaler = 0;                   //不分频
                TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数模式
                TIM_TimeBaseStructure.TIM_ClockDivision = 0;               //设置时钟不分割
                TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
       
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);                                       

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;             //选择定时器模式:TIM脉冲宽度调制模式1      
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    TIM_OCInitStructure.TIM_Pulse = Cycle/2;                     //设置待装入捕获寄存器的脉冲值                                 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;      //输出极性   
                TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;   //空闲为低
                TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
               
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);                                                         

    TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);        //启用主从模式
    TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);                                        //主定时器可用作从定时器的预分频器

    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);                                                 //输出比较2预装载使能                           
    TIM_ARRPreloadConfig(TIM3, ENABLE);                           //自动重载预装载使能
               
                //从定时器配置 TIM2               
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseStructure.TIM_Period = PulseNum;   
    TIM_TimeBaseStructure.TIM_Prescaler =0;   
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;   
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_SelectInputTrigger(TIM2, TIM_TS_ITR2);
                TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_External1 );//为外部时钟模式SMCR 寄存器中的 SMS=111
       

       
    TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;      
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;   
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
               
                //启动工作
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM2, ENABLE);
    TIM_Cmd(TIM3, ENABLE);
}OutputPulseOne(160,10)代表100KHz,10个脉冲
另外一组类似,使用的是TIM4主、TIM5从
效果如图:
两组同时输出15个脉冲、和10个脉冲

两组同时输出10个脉冲、和6个脉冲

两组同时输出8个脉冲、和8个脉冲

两组尝试150KHz 输出10个脉冲、和10个脉冲

最后附上已经摧残过很多次的F411板子

此方案没有处理计数超过定时器定时溢出时的方法,可以通过中断来循环计数实现,扩展可实现4组输出,应该实现了题目要求,自己水平有限,就不在此班门弄斧了,期待学习高手更好的方案。

nyszx 发表于 2017-11-29 21:52:34

期间还测了测F411高达4Mhz PWM输出,很强大, 但已经失真很严重,2M还好。有机会拿刚换到的F7测测.:lol

dsjsjf 发表于 2017-11-29 22:15:59

附加题:
自行选型一个STM32的单片机,要求输出4路可控制脉冲数的高速脉冲,必须要尽可能的节省CPU时间,而且不能频繁的进入中断(只需提供解决方案,不用代码)
一、首先,单片机的选型,因为需要高速脉冲,优先选择主频高的,STM32H743,定时器的时钟频率可达200MHz;
二、需要4路脉冲输出,可以采用TIM2的PWM CH1--CH4来输出,当然,如果所需要的4路脉冲频率不同,可以用4个独立的定时器的通道来输出;
三、节省CPU时间和不能频繁的进入中断,说明需要用单片机的硬件资源来实现。脉冲的周期、占空比由硬件PWM输出,都不是问题,主要是脉冲数量要可控。查看AN4013应用笔记定时器概览,定时器的从模式中的门控模式,可以满足要求。
四、那就需要另外一个定时器,作为主模式来触发TIM2的使能与关闭,采用TIM5的单脉冲模式,这个脉冲宽度设定为需要输出脉冲周期的N倍,N即为需要输出脉冲的数量。
五、通过STM32CubeMX大概配置一下,贴上部分截图(暂时未经实验验证,部分参数可能还需修改):

六、如果4路脉冲的频率、数量等都不相同,或者都需要相互独立,则需要更换为独立的定时器来控制输出。
七、看到F3和H7系列都还有HRTIM(High-resolution timer),据说时钟倍频后可高达4点几GHz,无奈最近出差,都是抽晚上时间看看资料,也没能看懂怎么使用,说不定可以输出更高频率的脉冲,只能等以后有空再学习。
页: [1] 2 3 4
查看完整版本: (已公布)狂欢节答题(附加题)