|
本帖最后由 磊磊映画 于 2014-7-21 10:14 编辑
学习过程中参考了ID:lxyppc的程序及思路
帖子http://www.amobbs.com/thread-3607403-1-1.html
stm32发送控制信号给驱动器,驱动器控制步进电机。
驱动器:控制一个步进电机转动,使用一路PWM信号,和一路方向信号,根据pwm信号的频率控制步进电机的转速,方向信号控制步进转动的方向。
之前看到很多寄存器版,我已成功移植到战舰的开发板上,对LXYPPC的程序进行了修改,使用了mdk,lxyppc的程序中调用了很多ARM标准的API,可见功底深厚。
对于程序有几点理解。
1.使用了定时器的主从门控模式,定时器3做主定时器,定时器1做从定时器,综合程序,我不禁要问主从门控模式发生的条件是什么,结果是什么?
根据程序中配置定时器的程序
TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Gated); goto definition后发现#define TIM_SlaveMode_Gated ((uint16_t)0x0005)
查询参考手册发现符合3.15定时器同步中,使用一个定时器使能另一个定时器的类型
门控模式可以对内部计数,当定时器溢出的更新条件发生后,可以使能另一个定时器工作,也就是说,更新发生后,另一个定时器会使能工作,所以就会出现while(1)中,if(!(TIM3->CR1 & 1))这句话,判断定时器3的使能与否。
2.见原帖中的六楼,比如TIM1输出PWM, 频率为F,可以用TIM2通过Gate来控制TIM1的输出,将TIM2预频设为1/(F*2),则TIM2的Period 就是 脉冲个数*2 - 1
对这句话不是很理解,为什么主定时器的频率要跟从定时器的频率发生关系,为什么是两倍,而不是三倍?
TIM1在配置好pwm输出后,就一直输出pwm波,TIM2的预分频跟TIM1设置PWM_Period/2 - 1,周期是waveNumber*2,当TIM1发生了F次PWM波之后,会使能TIM2,TIM2开始工作,这时将定时器TIM1计数器清零,将TIM2的周期修改,以便下次达到pwm发生预设的次数后,触发发生条件。
3.以上程序只是控制一路步进电机的,实际应用中要控制多路步进电机工作,在多路步进电机控制中使用该方法控制时要怎么做呢?
比如程序中使用的是定时器1的通道2和定时器3的通道4的主从门控工作模式,再多一路步进电机控制时,仍使用定时器1和定时器3的其他通道吗?还是使用另外两个定时器?
4.以上是我个人的理解,可能不对,欢迎指教。
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "key.h"
- #include "usart.h"
- #include "exti.h"
- #include "wdg.h"
- #include "timer.h"
- #include "pwm.h"
- //Mini STM32开发板范例代码8
- //PWM输出 实验
- //正点原子@ALIENTEK
- //技术论坛:www.openedv.com
- #define PWM_Period 120
- void RCC_Configuration(void);
- void NVIC_Configuration(void);
- void TIMER_Configuration(void);
- u16 waveNumber = 10;
- /*---------------------------------------------------------------------------------------------------------------------------------------*/
- /* Just make parameter name shorter */
- #define _GetInternalTrigger(S,M) \
- (S == TIM1 ? (M == TIM5 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
- (S == TIM8 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM4 ? TIM_TS_ITR2 :(M == TIM5 ? TIM_TS_ITR3 : (u16)-1)))): \
- (S == TIM2 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM8 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
- (S == TIM3 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM5 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
- (S == TIM4 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM8 ? TIM_TS_ITR3 : (u16)-1)))): \
- (S == TIM5 ? (M == TIM2 ? TIM_TS_ITR0 : (M == TIM3 ? TIM_TS_ITR1 : (M == TIM4 ? TIM_TS_ITR2 :(M == TIM8 ? TIM_TS_ITR3 : (u16)-1)))): \
- (u16)-1))))))
- #define GetInternalTrigger(SlaveTimer,MasterTimer) _GetInternalTrigger(SlaveTimer,MasterTimer)
- #define compile_assert(exp) {extern char lxyppc_at_163_dot_com[(exp) ? 1:-1];}
- int main(void)
- {
- /* System Clocks Configuration */
- SystemInit();
- delay_init(72); //延时初始化
- NVIC_Configuration();
- //uart_init(9600);
- /* Enable related peripheral clocks */
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE);
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE);
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1,ENABLE);
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3,ENABLE);
- TIMER_Configuration();
- /* Create relationship between timer1 and timer3, timer3 is master, timer1 is slave
- timer1 is work under gate control mode, and controled by timer3
- timer3's channel 4 is used as the control signal */
- /* Enable timer's master/slave work mode */
- TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
- TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);
- /* timer3's channel 4 is used as the control signal */
- TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_OC4Ref );
- /* Check the master/slave is valid or not */
- compile_assert((u16)GetInternalTrigger(TIM1,TIM3) != (u16)-1);
- /* Config timer1's external clock */
- TIM_ITRxExternalClockConfig(TIM1, GetInternalTrigger(TIM1,TIM3));
- TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Gated);
- /* Enable the slave timer*/
- TIM_Cmd(TIM1,ENABLE);
- while(1){
- /* Check whether the previous action is done or not */
- if(!(TIM3->CR1 & 1)){
- TIM1->CNT = 0; /* It would be very perfect if gate mode can
- reset the slave timer automatically */
- TIM3->ARR = waveNumber*2; /* Reload wave number*/
- TIM3->CCR4 = waveNumber*2 - 1;
- TIM3->CR1|=1; /* Re-enable the timer */
- /* update waveform number */
- waveNumber++;
- if(waveNumber == 13){
- waveNumber = 10;
- }
- }
- }
- }
- /* Config IO for related timers */
- void TIMER_Configuration(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- /* Timer1 Channel 2, PA9 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- /* Timer3 Channel 4, PB1*/
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- /* Setup Timer3 channel 4, Timer3 is master timer
- This timer is used to control the waveform count of timer1 */
- do
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- TIM_DeInit(TIM3);
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
- TIM_OCStructInit(&TIM_OCInitStructure);
- TIM_TimeBaseStructure.TIM_Prescaler = PWM_Period/2 - 1;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_Period = waveNumber*2;
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
-
- /* Timer2 Channel 3 Configuration in PWM2 mode, this is used for enable Recive clcok */
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = waveNumber*2 - 1;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OC4Init(TIM3,&TIM_OCInitStructure);
- TIM_CtrlPWMOutputs(TIM3, ENABLE);
- TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single);
-
- do
- {
- /* Setup timer1 channel 2, Timer1 is slave timer
- This timer is used to output waveforms */
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- TIM_DeInit(TIM1);
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
- TIM_OCStructInit(&TIM_OCInitStructure);
- TIM_TimeBaseStructure.TIM_Prescaler = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_Period = PWM_Period;
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
-
- /* Timer2 Channel 3 Configuration in PWM2 mode, this is used for enable Recive clcok */
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = PWM_Period/2;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OC2Init(TIM1,&TIM_OCInitStructure);
- TIM_CtrlPWMOutputs(TIM1, ENABLE);
- }
- while(0);
- }
- while(0);
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
阿莫论坛才是最爱国的,关心国家的经济、社会的发展、担心国家被别国牵连卷入战争、知道珍惜来之不易的和平发展,知道师夷之长,关注世界的先进文化与技术,也探讨中国文化的博大精深,也懂得警惕民粹主义的祸国殃民等等等等,无不是爱国忧民的表现。(坛友:tianxian)
|