搜索
bottom↓
回复: 73

请教并讨论STM32的TIM控制步进电机的策略

  [复制链接]

出0入0汤圆

发表于 2009-9-27 13:38:18 | 显示全部楼层 |阅读模式
参考ST官方的应用笔记,将TIM2初始化为TIM_OCMode_Toggle模式,而非直接输出PWM来控制电机;
而在其调速控制过程中,是通过修改ARR寄存器(#define   TIM2_ARR_Address    0x4000002C),也即是修改TIM_Period;
这跟PWM控制,修改Period有什么区别?
官方的应用笔记与原代码: http://www.stmicroelectronics.com.cn/stonline/mcu/STM32_AN.htm
附我现在的TIM代码:
#define SET_STEPMOTOR_ENA()  GPIO_SetBits(GPIOE,GPIO_Pin_13)
#define CLR_STEPMOTOR_ENA()  GPIO_ResetBits(GPIOE,GPIO_Pin_13)

void StepMotor_Configration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;

  /* GPIOA Configuration:TIM2 Channel1 in Output */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  //PE12 ALM  PE13 ENA  PE14 DIR
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOE, &GPIO_InitStructure);  
  
  SET_STEPMOTOR_ENA();

  /* ---------------------------------------------------------------
  TIM2 Configuration: Output Compare Toggle Mode:
  --------------------------------------------------------------- */
   /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period =800;
  TIM_TimeBaseStructure.TIM_Prescaler = 2;
  TIM_OCInitStructure.TIM_Pulse = 0;  
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* Output Compare Toggle Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode =TIM_OCMode_Toggle;  
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC1Init(TIM2, &TIM_OCInitStructure);

  TIM_ARRPreloadConfig(TIM2, ENABLE);
  
  /* TIM enable counter */
  TIM_Cmd(TIM2, ENABLE);   
}

出0入0汤圆

 楼主| 发表于 2009-9-27 13:41:02 | 显示全部楼层
另外我在EDN看到southcreek网友的一段话,十分不明白其控制方法,为什么PWM要改变占空比,不是直接改变频率就行吗?望高人释惑:

"一般控制步进电机不要用PWM ,因为一般使用PWM,总是固定一个频率然后改变占空比。我的办法是使用定时器的输出比较功能。将需要的定时的一半写入一个输出比较定时器。将输出比较对应的通道设置为在达到匹配时切换输出电平。在产生输出比较时进入中断,清空定时器。然后设置下一步需要的频率。"

地址:http://group.ednchina.com/619/25416.aspx

出0入0汤圆

发表于 2009-9-27 16:52:20 | 显示全部楼层
不知道EDN的southcreek兄用什么MCU控了

用PWM控制可以,我做过用430的PWM控制伺服电机,周期和占空比很容易改
现在研究STM32在固定的频率,输出任意个脉冲数(非定时器中断IO反转那种)

出0入0汤圆

 楼主| 发表于 2009-9-27 17:38:11 | 显示全部楼层
回复qwerttt,上面的southcreek也是用的STM32;
另外我想用TIM的一个CHNNAEL输出固定频率的脉冲,再用另一个CHANNEL或者TIMER计数,就可以控制输出脉冲个数呢?或者还有更简单的方法?请大家赐教。

出0入0汤圆

 楼主| 发表于 2009-9-29 08:28:14 | 显示全部楼层
讨论,上去

出0入0汤圆

发表于 2009-9-29 09:20:59 | 显示全部楼层
我想到一个思路
用到了Timer Master Slave中的Gate模式
比如TIM1输出PWM, 频率为F
可以用TIM2通过Gate来控制TIM1的输出
将TIM2预频设为1/(F*2),则TIM2的Period 就是 脉冲个数*2 - 1

/*           1     2     3     4     5     6     7     8     9
             __    __    __    __    __    __    __    __    __           
            |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |            
TIM1:    ___|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |____________________
          ->| Period1|<-
             1) 2) 3) 4) 5) 6) 7) 8) 9) 10)11)12)13)14)15)16)17)
             __________________________________________________  
            |                                                  |  
TIM2:    ___|                                                  |____________________
          ->|  |<--- Pres2 = Period1/2
            |<------------  Period2 =  N*2-1 = 17 ------------>|
*/

出0入0汤圆

发表于 2009-9-29 11:13:08 | 显示全部楼层
关注,

出0入0汤圆

 楼主| 发表于 2009-9-30 10:19:48 | 显示全部楼层
回复 lxyppc,
看到ST有相关的这种定时器链式应用,还在研究,有点生涩啊。。


  /* Timers synchronisation in cascade mode ----------------------------
     1/TIM2 is configured as Master Timer:
     - PWM Mode is used
     - The TIM2 Update event is used as Trigger Output  

     2/TIM3 is slave for TIM2 and Master for TIM4,
     - PWM Mode is used
     - The ITR1(TIM2) is used as input trigger
     - Gated mode is used, so start and stop of slave counter
      are controlled by the Master trigger output signal(TIM2 update event).
      - The TIM3 Update event is used as Trigger Output.

      3/TIM4 is slave for TIM3,
     - PWM Mode is used
     - The ITR2(TIM3) is used as input trigger
     - Gated mode is used, so start and stop of slave counter
      are controlled by the Master trigger output signal(TIM3 update event).

     The TIMxCLK is fixed to 72 MHz, the TIM2 counter clock is 72 MHz.

     The Master Timer TIM2 is running at TIM2 frequency :
     TIM2 frequency = (TIM2 counter clock)/ (TIM2 period + 1) = 281.250 KHz
     and the duty cycle = TIM2_CCR1/(TIM2_ARR + 1) = 25%.

     The TIM3 is running:
     - At (TIM2 frequency)/ (TIM3 period + 1) = 70.312 KHz and a duty cycle
     equal to TIM3_CCR1/(TIM3_ARR + 1) = 25%

     The TIM4 is running:
     - At (TIM3 frequency)/ (TIM4 period + 1) = 17.578 KHz and a duty cycle
     equal to TIM4_CCR1/(TIM4_ARR + 1) = 25%
  -------------------------------------------------------------------- */

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 255;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  TIM_TimeBaseStructure.TIM_Period = 3;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  TIM_TimeBaseStructure.TIM_Period = 3;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

  /* Master Configuration in PWM1 Mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 64;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OC1Init(TIM2, &TIM_OCInitStructure);

  /* Select the Master Slave Mode */
  TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);

  /* Master Mode selection */
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

  /* Slaves Configuration: PWM1 Mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 1;

  TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  TIM_OC1Init(TIM4, &TIM_OCInitStructure);

  /* Slave Mode selection: TIM3 */
  TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
  TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1);

  /* Select the Master Slave Mode */
  TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

  /* Master Mode selection: TIM3 */
  TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);

  /* Slave Mode selection: TIM4 */
  TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated);
  TIM_SelectInputTrigger(TIM4, TIM_TS_ITR2);

  /* TIM enable counter */
  TIM_Cmd(TIM3, ENABLE);
  TIM_Cmd(TIM2, ENABLE);
  TIM_Cmd(TIM4, ENABLE);

出0入0汤圆

 楼主| 发表于 2009-10-1 14:05:20 | 显示全部楼层
__STM32___推荐的方法是另用一个TIM定时控制以达到控制脉冲个数的目的,大家是怎样做?

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3425424&bbs_page_no=1&search_mode=1&search_text=%C2%F6%B3%E5&bbs_id=3020

出0入0汤圆

发表于 2009-10-1 16:50:56 | 显示全部楼层
那边的前提是频率很低,可以用中断的方式
我用的是Gate的方式

出0入0汤圆

 楼主| 发表于 2009-10-2 15:40:33 | 显示全部楼层
回复lxyppc ,看到STM32的AN有这样的应用,也是GATE从模式,想请问你用的方法有用代码实现过吗?能很方便的控制TIMx输出脉冲个数吗?因为我还是对你的想法不太理解,望参考下代码,谢谢。

(原文件名:01.JPG)


(原文件名:02.JPG)

出0入0汤圆

发表于 2009-10-5 18:56:45 | 显示全部楼层
好的
不过代码在公司,要放完假才能贴过来了

那个的代码的思路是MASTER用one pulse模式
门控slave,同时用master的另一路channel触发一个DMA,用来复位slave

楼主能描述一下你应用的需求吗?

出0入0汤圆

 楼主| 发表于 2009-10-6 10:19:57 | 显示全部楼层
lxyppc 上午好,
我是想用TIM控制输入给步进驱动器的驱动脉冲个数,我现在用TIM2产生PWM波供驱动器,用TIM8检测电机光电编码盘的反馈脉冲,但是遇到些问题,所以想在源头,即输入脉冲上作控制,就比如,我想让电机走半圈,我就控制TIM输出500个PWM脉冲给驱动器。

出0入0汤圆

发表于 2009-10-7 21:10:46 | 显示全部楼层
推荐使用TMC223这款芯片集成了控制功能+驱动功能+MOSFETS,加速度,减速度,位置,速度,细分全部集成在TMC223芯片内部.上位的MCU只需要调用其函数进行管理即可.

(原文件名:1.gif)


(原文件名:3.gif)


(原文件名:6.gif)
TMC223资料:
点击此处下载 ourdev_489168.pdf(文件大小:1.79M) (原文件名:TMC223_datasheet.pdf)
电路图:
点击此处下载 ourdev_489169.pdf(文件大小:86K) (原文件名:Eval222_Schematics.pdf)

出0入0汤圆

发表于 2009-10-7 21:34:56 | 显示全部楼层
型号        性能
                           控制芯片
TMC211        1个步进控制+驱动芯片 LIN通讯
TMC222        1个步进控制+驱动芯片 IIC通讯
TMC223        1个步进控制+驱动芯片 IIC通讯 StallGuard功能
TMC428        3个电机控制芯片;SPI或step/dir控制信号
TMC454        位置闭环芯片,PID功能,ABN编码器输入,微步406,classic/SPI/SD
TMC457        位置闭环芯片,PID功能,ABN编码器输入,微步2048;classic/SPI/SD
TMC401        信号转化芯片 SPI---STEP/DIR;42细分
                   编码器信号处理芯片
TMC423        3路ABN编码器处理芯片
                        步进驱动芯片
TMC236        2相步进驱动芯片;1.5A;64细分;齐全的保护和诊断功能
TMC239        2相步进驱动芯片;MOSFETS外置;64细分;齐全的保护和诊断功能
TMC246        2相步进驱动芯片;1.5A;64细分;齐全的保护和诊断功能; 具有专利技术StallGuard技术
TMC249        2相步进驱动芯片;MOSFETS外置;64细分;齐全的保护和诊断功能;具有专利技术StallGuard技术
                                      3相步进驱动芯片
TMC332        适用2相或3相步进电机;自动高速;运动平稳;细分数2相256细分,3相171细分;S/D接口;ABN编码器输入
                     无传感器直流无刷驱动芯片
TMC603        3相BLDC;20A;12-50V;无需Hall换向
       
       
详细资料及参考电路        详细资料及参考电路
       
TMC211        http://www.trinamic.com/tmc/render.php?sess_pid=209
TMC222        http://www.trinamic.com/tmc/render.php?sess_pid=222
TMC223        http://www.trinamic.com/tmc/render.php?sess_pid=223
TMC428        http://www.trinamic.com/tmc/render.php?sess_pid=428
TMC454        http://www.trinamic.com/tmc/render.php?sess_pid=454
TMC457        http://www.trinamic.com/tmc/render.php?sess_pid=457
TMC401        http://www.trinamic.com/tmc/render.php?sess_pid=401
       
TMC423        http://www.trinamic.com/tmc/render.php?sess_pid=423
       
TMC236        http://www.trinamic.com/tmc/render.php?sess_pid=236
TMC239        http://www.trinamic.com/tmc/render.php?sess_pid=239
TMC246        http://www.trinamic.com/tmc/render.php?sess_pid=246
TMC249        http://www.trinamic.com/tmc/render.php?sess_pid=249
       
TMC332        http://www.trinamic.com/tmc/render.php?sess_pid=332
       
TMC603        http://www.trinamic.com/tmc/render.php?sess_pid=603

出0入0汤圆

发表于 2009-10-7 21:52:39 | 显示全部楼层
楼上的芯片太贵了
AVR也可以实现的  但是前提是要用两个定时器资源

1个产生pulse
另外一个计数,比较中断中停止脉冲
比较寄存器的值就是脉冲个数

STM32不知到用一个定时器能不能实现,原本以为那个重复寄存器可以实现这个功能,看来是不行的。

出0入0汤圆

 楼主| 发表于 2009-10-8 10:13:47 | 显示全部楼层
回复stm32_boy,
对的,其实要实现并不难,以前用ARM7作直接计PWM的中断就可以,但是STM32应该有更好的方法

出0入0汤圆

发表于 2009-10-9 11:07:36 | 显示全部楼层
楼主,用定时器1.2.3.4中的一个做主定时器,另外用一个定时器工作在外部时钟模式下,直接对主定时器的PWM脉冲进行计数,在匹配中断产生后,通知CPU,即可控制任意脉冲数的输出。这个是想法,我实验一下看看,

出0入0汤圆

发表于 2009-10-9 19:40:19 | 显示全部楼层
要控制步进电机的步数、速度以及加减速最好使用AVR应用笔记446的算法,效果很好。我现在把同样的算法移植到STM32上,很爽,加减速很平滑,无抖动!

出0入0汤圆

 楼主| 发表于 2009-10-10 08:28:42 | 显示全部楼层
多谢zhenfanhei;
多谢shenhaojj,去找来看看

出0入0汤圆

发表于 2009-10-10 11:24:59 | 显示全部楼层
20楼提供的资料,要对电机有深入了解呀
还是配上驱动器控制比较方便

出0入0汤圆

发表于 2009-10-10 12:32:17 | 显示全部楼层
【19楼】 zhenfanhei
所说的就是我所说的

出0入0汤圆

发表于 2009-10-12 18:49:03 | 显示全部楼层
终于来上班了,我试了一下,下面代码可以控制输出的脉冲数
软件:
IAR 4.42限制版
ST库    2.01
硬件:
万利199开发板 STM3210B-LK1
/*0001*/  /* Includes ------------------------------------------------------------------*/
/*0002*/  #include "stm32f10x_lib.h"
/*0003*/  
/*0004*/  /* Private typedef -----------------------------------------------------------*/
/*0005*/  /* Private define ------------------------------------------------------------*/
/*0006*/  /* Private macro -------------------------------------------------------------*/
/*0007*/  /* Private variables ---------------------------------------------------------*/
/*0008*/  ErrorStatus HSEStartUpStatus;
/*0009*/  
/*0010*/  /* Private function prototypes -----------------------------------------------*/
/*0011*/  void  RCC_Configuration(void);
/*0012*/  void  NVIC_Configuration(void);
/*0013*/  /* Private functions ---------------------------------------------------------*/
/*0014*/  
/*0015*/  #define   PWM_Period      120
/*0016*/  int main(void)
/*0017*/  {
/*0018*/    u16       waveNumber = 10;
/*0019*/    /* System Clocks Configuration */
/*0020*/    RCC_Configuration();
/*0021*/  
/*0022*/    /* Enable related peripheral clocks */
/*0023*/    RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOA,ENABLE);
/*0024*/    RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOB,ENABLE);
/*0025*/    RCC_APB2PeriphClockCmd(  RCC_APB2Periph_TIM1,ENABLE);
/*0026*/    RCC_APB1PeriphClockCmd(  RCC_APB1Periph_TIM3,ENABLE);
/*0027*/    
/*0028*/    /* Config IO for related timers */
/*0029*/    {
/*0030*/      GPIO_InitTypeDef GPIO_InitStructure;
/*0031*/      /* Timer1 Channel 2, PA9 */
/*0032*/      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9;
/*0033*/      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
/*0034*/      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*0035*/      GPIO_Init(GPIOA, &GPIO_InitStructure);
/*0036*/      /* Timer3 Channel 4, PB1*/
/*0037*/      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1;
/*0038*/      GPIO_Init(GPIOB, &GPIO_InitStructure);
/*0039*/    }
/*0040*/    /* Setup Timer3 channel 4, Timer3 is master timer
<font color=#646400>|*0041*|  
     This timer is used to control the waveform count of timer1 */</font>
/*0042*/    {
/*0043*/      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
/*0044*/      TIM_OCInitTypeDef  TIM_OCInitStructure;
/*0045*/      TIM_DeInit(TIM3);
/*0046*/      TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
/*0047*/      TIM_OCStructInit(&TIM_OCInitStructure);
/*0048*/      TIM_TimeBaseStructure.TIM_Prescaler = PWM_Period/2 - 1;
/*0049*/      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
/*0050*/      TIM_TimeBaseStructure.TIM_Period = waveNumber*2;
/*0051*/      TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
/*0052*/      TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
/*0053*/     
/*0054*/      /* Timer2 Channel 3 Configuration in PWM2 mode, this is used for enable Recive clcok */
/*0055*/      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
/*0056*/      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
/*0057*/      TIM_OCInitStructure.TIM_Pulse = waveNumber*2 - 1;
/*0058*/      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
/*0059*/      TIM_OC4Init(TIM3,&TIM_OCInitStructure);
/*0060*/      TIM_CtrlPWMOutputs(TIM3, ENABLE);
/*0061*/      TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single);
/*0062*/    }
/*0063*/    /* Setup timer1 channel 2, Timer1 is slave timer
<font color=#646400>|*0064*|  
     This timer is used to output waveforms */</font>
/*0065*/    {
/*0066*/      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
/*0067*/      TIM_OCInitTypeDef  TIM_OCInitStructure;
/*0068*/      TIM_DeInit(TIM1);
/*0069*/      TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
/*0070*/      TIM_OCStructInit(&TIM_OCInitStructure);
/*0071*/      TIM_TimeBaseStructure.TIM_Prescaler = 0;
/*0072*/      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
/*0073*/      TIM_TimeBaseStructure.TIM_Period = PWM_Period;
/*0074*/      TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
/*0075*/      TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
/*0076*/     
/*0077*/      /* Timer2 Channel 3 Configuration in PWM2 mode, this is used for enable Recive clcok */
/*0078*/      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
/*0079*/      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
/*0080*/      TIM_OCInitStructure.TIM_Pulse = PWM_Period/2;
/*0081*/      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
/*0082*/      TIM_OC2Init(TIM1,&TIM_OCInitStructure);
/*0083*/      TIM_CtrlPWMOutputs(TIM1, ENABLE);
/*0084*/    }
/*0085*/    /* Create relationship between timer1 and timer3, timer3 is master, timer1 is slave
<font color=#646400>|*0086*|  
    timer1 is work under gate control mode, and controled by timer3
|*0087*|      timer3's channel 4 is used as the control signal
|*0088*|     */</font>
/*0089*/      /* Enable timer's master/slave work mode */
/*0090*/      TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
/*0091*/      TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);
/*0092*/      /* timer3's channel 4 is used as the control signal */
/*0093*/      TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_OC4Ref );
/*0094*/      /* Check the master/slave is valid or not */
/*0095*/      compile_assert((u16)GetInternalTrigger(TIM1,TIM3) != (u16)-1);
/*0096*/      /* Config timer1's external clock */
/*0097*/      TIM_ITRxExternalClockConfig(TIM1, GetInternalTrigger(TIM1,TIM3));
/*0098*/      TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Gated);
/*0099*/     
/*0100*/    /* Enable the slave tiemr*/
/*0101*/    TIM_Cmd(TIM1,ENABLE);
/*0102*/    //SetupAlltimers();
/*0103*/    while(1){
/*0104*/      /* Check whether the previous action is done or not */
/*0105*/      if(!(TIM3->CR1 & 1)){
/*0106*/        TIM1->CNT = 0; /* It would be very perfect if gate mode can
<font color=#646400>|*0107*|  
                        reset the slave timer automatically */</font>
/*0108*/        TIM3->ARR = waveNumber*2;  /* Reload wave number*/
/*0109*/        TIM3->CCR4 = waveNumber*2 - 1;
/*0110*/        TIM3->CR1|=1; /* Re-enable the timer */
/*0111*/        /* update waveform number */
/*0112*/        waveNumber++;
/*0113*/        if(waveNumber == 13){
/*0114*/          waveNumber = 10;
/*0115*/        }
/*0116*/      }
/*0117*/    }
/*0118*/  }
/*0119*/  
/*0120*/  /*******************************************************************************
<font color=#646400>|*0121*|  
* Function Name  : RCC_Configuration
|*0122*|  * Description    : Configures the different system clocks.
|*0123*|  * Input          : None
|*0124*|  * Output         : None
|*0125*|  * Return         : None
|*0126*|  *******************************************************************************/</font>
/*0127*/  void RCC_Configuration(void)
/*0128*/  {
/*0129*/    /* RCC system reset(for debug purpose) */
/*0130*/    RCC_DeInit();
/*0131*/  
/*0132*/    /* Enable HSE */
/*0133*/    RCC_HSEConfig(RCC_HSE_ON);
/*0134*/  
/*0135*/    /* Wait till HSE is ready */
/*0136*/    HSEStartUpStatus = RCC_WaitForHSEStartUp();
/*0137*/  
/*0138*/    if(HSEStartUpStatus == SUCCESS)
/*0139*/    {
/*0140*/      /* Enable Prefetch Buffer */
/*0141*/      FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/*0142*/  
/*0143*/      /* Flash 2 wait state */
/*0144*/      FLASH_SetLatency(FLASH_Latency_2);
/*0145*/  
/*0146*/      /* HCLK = SYSCLK */
/*0147*/      RCC_HCLKConfig(RCC_SYSCLK_Div1);
/*0148*/    
/*0149*/      /* PCLK2 = HCLK */
/*0150*/      RCC_PCLK2Config(RCC_HCLK_Div1);
/*0151*/  
/*0152*/      /* PCLK1 = HCLK/2 */
/*0153*/      RCC_PCLK1Config(RCC_HCLK_Div2);
/*0154*/  
/*0155*/      /* PLLCLK = 8MHz * 9 = 72 MHz */
/*0156*/      RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/*0157*/  
/*0158*/      /* Enable PLL */
/*0159*/      RCC_PLLCmd(ENABLE);
/*0160*/  
/*0161*/      /* Wait till PLL is ready */
/*0162*/      while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
/*0163*/      {
/*0164*/      }
/*0165*/  
/*0166*/      /* Select PLL as system clock source */
/*0167*/      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/*0168*/  
/*0169*/      /* Wait till PLL is used as system clock source */
/*0170*/      while(RCC_GetSYSCLKSource() != 0x08)
/*0171*/      {
/*0172*/      }
/*0173*/    }
/*0174*/  }

输出波形如下图

(原文件名:TEK0000.jpg)

出0入0汤圆

 楼主| 发表于 2009-10-13 08:29:34 | 显示全部楼层
感谢lxyppc,我现在直接用PWM更新中断计的脉冲个数,最笨,最耗资源的办法,过后就实验您的代码方法,谢谢。

有点疑问,为什么主程序里面每次都要重新更新TIM3的参数呢?
TIM1->CNT = 0; /* It would be very perfect if gate mode can
|*0107*|                          reset the slave timer automatically */
/*0108*/        TIM3->ARR = waveNumber*2;  /* Reload wave number*/
/*0109*/        TIM3->CCR4 = waveNumber*2 - 1;
/*0110*/        TIM3->CR1|=1; /* Re-enable the timer */

出0入0汤圆

发表于 2009-10-13 09:26:02 | 显示全部楼层
更新TIM3是为了让每次间隔后输出的脉冲的个数不一样(如示波器看到的那样),如果不改变输出脉冲的个数,就不用更新TIM3的参数

出0入0汤圆

发表于 2009-12-25 21:31:27 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-12-25 22:42:51 | 显示全部楼层
有点兴趣

出0入0汤圆

发表于 2009-12-26 14:52:11 | 显示全部楼层
mark

出0入8汤圆

发表于 2010-1-5 11:11:56 | 显示全部楼层
收藏

出0入0汤圆

发表于 2010-1-5 12:13:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-1-7 18:11:13 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-6-28 17:22:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-28 19:35:34 | 显示全部楼层
我目前正在做一个东西,用stm32给电机发脉冲,电机要求可定位,可调速,有编码器反馈,完成这东西最少要用几个定时器呢?

出0入0汤圆

发表于 2010-7-5 16:15:35 | 显示全部楼层
学习了啊,AVR的资料也看了一下
以前看STM32的时候不知道这个主从模式应该如何使用,现在又点感觉了

有时间的话可以试一下啊

出0入0汤圆

发表于 2010-7-30 23:58:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-4 21:28:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-4 23:03:24 | 显示全部楼层
这个资料好  ,标记

出0入0汤圆

发表于 2010-11-11 10:34:38 | 显示全部楼层
回复【20楼】shenhaojj
要控制步进电机的步数、速度以及加减速最好使用avr应用笔记446的算法,效果很好。我现在把同样的算法移植到stm32上,很爽,加减速很平滑,无抖动!
-----------------------------------------------------------------------

你说的avr应用笔记446的算法在哪里有,能否共享你移植到stm32上的代码?

出0入0汤圆

发表于 2010-11-13 23:08:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-18 16:21:43 | 显示全部楼层
同样关注加减速控制问题

出0入0汤圆

发表于 2011-5-6 16:33:11 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-6-13 11:57:17 | 显示全部楼层
mark

代码中的compile_assert见
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3551560&bbs_page_no=73&bbs_id=3020

出0入0汤圆

发表于 2011-6-13 12:51:15 | 显示全部楼层
写的不错

出0入0汤圆

发表于 2011-9-3 11:47:11 | 显示全部楼层
仔细研究

出0入0汤圆

发表于 2011-9-12 23:54:16 | 显示全部楼层
回复【24楼】lxyppc
-----------------------------------------------------------------------

回复【24楼】lxyppc
终于来上班了,我试了一下,下面代码可以控制输出的脉冲数
软件:
iar 4.42限制版
st库    2.01
硬件:
万利199开发板 stm3210b-lk1
/*0001*/  /* includes ------------------------------------------------------------------*/
/*0002*/  #include "stm32f10x_lib.h"
/*0003*/  
<font co......
-----------------------------------------------------------------------

请教if(!(TIM3->CR1 & 1)) 这个位清0是否有中断产生呢?可否用中断方式处理?

出0入0汤圆

发表于 2011-9-13 03:35:46 | 显示全部楼层
TIM1总是有脉冲啊

出0入0汤圆

发表于 2011-9-13 09:54:23 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-9-22 13:32:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-10 14:22:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-11 11:13:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-11 12:58:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-18 19:21:35 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-8 07:11:07 | 显示全部楼层
Mark

出0入0汤圆

发表于 2012-4-13 10:49:15 | 显示全部楼层
谢谢楼主奉献

出0入0汤圆

发表于 2012-7-3 09:51:50 | 显示全部楼层
没看懂lxyppc的程序,注释中的TIM2是做什么用的啊

出0入0汤圆

发表于 2012-7-10 11:19:37 | 显示全部楼层
看到如此好贴,不得不赶快注册一个然后回复。

出0入0汤圆

发表于 2012-7-26 08:59:02 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-8-5 23:36:04 | 显示全部楼层
这个帖子里面的东西技术含量高啊,要看,要好好看,呵呵,非常感谢LZ及坛友!

出0入0汤圆

发表于 2012-9-4 11:34:42 | 显示全部楼层
好资料,正在找这样的资料

出0入0汤圆

发表于 2013-1-21 09:46:26 | 显示全部楼层
好帖子,讲得不错

出0入30汤圆

发表于 2014-5-27 09:31:38 | 显示全部楼层
好帖。收藏细看。

出0入0汤圆

发表于 2014-7-2 22:57:10 | 显示全部楼层
正在找相关的资料,回头研究一下ls提供的方法。

出0入0汤圆

发表于 2014-7-20 21:41:45 | 显示全部楼层
daicp 发表于 2011-9-12 23:54
回复【24楼】lxyppc
-----------------------------------------------------------------------

放在主程序里面,在执行的的时候就要把这个判断保护起来,套到while(1)中,完成后再跳出来,不这样的话很有可能错过这个条件的发生啊,不知道用中断怎么做呢

出0入0汤圆

发表于 2015-3-11 22:43:22 | 显示全部楼层
下载了先,明天再看

出0入0汤圆

发表于 2015-4-28 14:19:42 | 显示全部楼层
好帖。收藏细看。

出0入0汤圆

发表于 2015-8-6 21:44:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2015-11-25 09:52:44 | 显示全部楼层
Nice,正在参考这个帖子做 3轴联动

出0入0汤圆

发表于 2018-6-11 15:16:24 | 显示全部楼层
STM32对步进电机的控制,并没有PIC做的好。这个方法很好,学习了!

出0入0汤圆

发表于 2020-11-7 17:26:15 | 显示全部楼层
在看用DMA+脉冲反转调速,希望能有帮助
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 18:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表