请教并讨论STM32的TIM控制步进电机的策略
参考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_TimeBaseInitTypeDefTIM_TimeBaseStructure;
TIM_OCInitTypeDefTIM_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 ALMPE13 ENAPE14 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);
} 另外我在EDN看到southcreek网友的一段话,十分不明白其控制方法,为什么PWM要改变占空比,不是直接改变频率就行吗?望高人释惑:
"一般控制步进电机不要用PWM ,因为一般使用PWM,总是固定一个频率然后改变占空比。我的办法是使用定时器的输出比较功能。将需要的定时的一半写入一个输出比较定时器。将输出比较对应的通道设置为在达到匹配时切换输出电平。在产生输出比较时进入中断,清空定时器。然后设置下一步需要的频率。"
地址:http://group.ednchina.com/619/25416.aspx 不知道EDN的southcreek兄用什么MCU控了
用PWM控制可以,我做过用430的PWM控制伺服电机,周期和占空比很容易改
现在研究STM32在固定的频率,输出任意个脉冲数(非定时器中断IO反转那种) 回复qwerttt,上面的southcreek也是用的STM32;
另外我想用TIM的一个CHNNAEL输出固定频率的脉冲,再用另一个CHANNEL或者TIMER计数,就可以控制输出脉冲个数呢?或者还有更简单的方法?请大家赐教。 讨论,上去 我想到一个思路
用到了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 ------------>|
*/ 关注, 回复 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); __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 那边的前提是频率很低,可以用中断的方式
我用的是Gate的方式 回复lxyppc ,看到STM32的AN有这样的应用,也是GATE从模式,想请问你用的方法有用代码实现过吗?能很方便的控制TIMx输出脉冲个数吗?因为我还是对你的想法不太理解,望参考下代码,谢谢。
http://cache.amobbs.com/bbs_upload782111/files_19/ourdev_487854.JPG
(原文件名:01.JPG)
http://cache.amobbs.com/bbs_upload782111/files_19/ourdev_487855.JPG
(原文件名:02.JPG) 好的
不过代码在公司,要放完假才能贴过来了
那个的代码的思路是MASTER用one pulse模式
门控slave,同时用master的另一路channel触发一个DMA,用来复位slave
楼主能描述一下你应用的需求吗? lxyppc 上午好,
我是想用TIM控制输入给步进驱动器的驱动脉冲个数,我现在用TIM2产生PWM波供驱动器,用TIM8检测电机光电编码盘的反馈脉冲,但是遇到些问题,所以想在源头,即输入脉冲上作控制,就比如,我想让电机走半圈,我就控制TIM输出500个PWM脉冲给驱动器。 推荐使用TMC223这款芯片集成了控制功能+驱动功能+MOSFETS,加速度,减速度,位置,速度,细分全部集成在TMC223芯片内部.上位的MCU只需要调用其函数进行管理即可.
http://cache.amobbs.com/bbs_upload782111/files_19/ourdev_489165.gif
(原文件名:1.gif)
http://cache.amobbs.com/bbs_upload782111/files_19/ourdev_489166.gif
(原文件名:3.gif)
http://cache.amobbs.com/bbs_upload782111/files_19/ourdev_489167.gif
(原文件名:6.gif)
TMC223资料:
点击此处下载 ourdev_489168.pdf(文件大小:1.79M) (原文件名:TMC223_datasheet.pdf)
电路图:
点击此处下载 ourdev_489169.pdf(文件大小:86K) (原文件名:Eval222_Schematics.pdf) 型号 性能
控制芯片
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 楼上的芯片太贵了
AVR也可以实现的但是前提是要用两个定时器资源
1个产生pulse
另外一个计数,比较中断中停止脉冲
比较寄存器的值就是脉冲个数
STM32不知到用一个定时器能不能实现,原本以为那个重复寄存器可以实现这个功能,看来是不行的。 回复stm32_boy,
对的,其实要实现并不难,以前用ARM7作直接计PWM的中断就可以,但是STM32应该有更好的方法 楼主,用定时器1.2.3.4中的一个做主定时器,另外用一个定时器工作在外部时钟模式下,直接对主定时器的PWM脉冲进行计数,在匹配中断产生后,通知CPU,即可控制任意脉冲数的输出。这个是想法,我实验一下看看, 要控制步进电机的步数、速度以及加减速最好使用AVR应用笔记446的算法,效果很好。我现在把同样的算法移植到STM32上,很爽,加减速很平滑,无抖动! 多谢zhenfanhei;
多谢shenhaojj,去找来看看 20楼提供的资料,要对电机有深入了解呀
还是配上驱动器控制比较方便 【19楼】 zhenfanhei
所说的就是我所说的 终于来上班了,我试了一下,下面代码可以控制输出的脉冲数
软件:
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*/voidRCC_Configuration(void);
/*0012*/voidNVIC_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_TimeBaseInitTypeDefTIM_TimeBaseStructure;
/*0044*/ TIM_OCInitTypeDefTIM_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_TimeBaseInitTypeDefTIM_TimeBaseStructure;
/*0067*/ TIM_OCInitTypeDefTIM_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*/}
输出波形如下图
http://cache.amobbs.com/bbs_upload782111/files_20/ourdev_490837.jpg
(原文件名:TEK0000.jpg) 感谢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 */ 更新TIM3是为了让每次间隔后输出的脉冲的个数不一样(如示波器看到的那样),如果不改变输出脉冲的个数,就不用更新TIM3的参数 MARK 有点兴趣 mark 收藏 mark 学习 mark 我目前正在做一个东西,用stm32给电机发脉冲,电机要求可定位,可调速,有编码器反馈,完成这东西最少要用几个定时器呢? 学习了啊,AVR的资料也看了一下
以前看STM32的时候不知道这个主从模式应该如何使用,现在又点感觉了
有时间的话可以试一下啊 mark mark 这个资料好,标记 回复【20楼】shenhaojj
要控制步进电机的步数、速度以及加减速最好使用avr应用笔记446的算法,效果很好。我现在把同样的算法移植到stm32上,很爽,加减速很平滑,无抖动!
-----------------------------------------------------------------------
你说的avr应用笔记446的算法在哪里有,能否共享你移植到stm32上的代码? mark 同样关注加减速控制问题 MARK mark
代码中的compile_assert见
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3551560&bbs_page_no=73&bbs_id=3020 写的不错 仔细研究 回复【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是否有中断产生呢?可否用中断方式处理? TIM1总是有脉冲啊 MARK mark mark mark mark mark Mark 谢谢楼主奉献 没看懂lxyppc的程序,注释中的TIM2是做什么用的啊 看到如此好贴,不得不赶快注册一个然后回复。 谢谢分享 这个帖子里面的东西技术含量高啊,要看,要好好看,呵呵,非常感谢LZ及坛友! 好资料,正在找这样的资料 好帖子,讲得不错 好帖。收藏细看。 正在找相关的资料,回头研究一下ls提供的方法。 daicp 发表于 2011-9-12 23:54
回复【24楼】lxyppc
-----------------------------------------------------------------------
放在主程序里面,在执行的的时候就要把这个判断保护起来,套到while(1)中,完成后再跳出来,不这样的话很有可能错过这个条件的发生啊,不知道用中断怎么做呢 下载了先,明天再看{:victory:} 好帖。收藏细看。 mark{:lol:} Nice,正在参考这个帖子做 3轴联动 STM32对步进电机的控制,并没有PIC做的好。这个方法很好,学习了! 在看用DMA+脉冲反转调速,希望能有帮助
页:
[1]