题目分析: 自行选择一个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 时钟高达84MHz APB2Timer 时钟高达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 =[url=]APB2 Timer=100MHz [/url]): 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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_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组输出,应该实现了题目要求,自己水平有限,就不在此班门弄斧了,期待学习高手更好的方案。
|