OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15316|回复: 11

伺服电机加减速控制

[复制链接]

1

主题

3

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1209
金钱
1209
注册时间
2015-5-17
在线时间
115 小时
发表于 2015-5-17 18:11:30 | 显示全部楼层 |阅读模式
5金钱
请教各位大神,本人用的是stm32f103zet6板子,怎么实现电机的加减速控制(只要梯形加速-匀速-减速的就可以了)。我在论坛看了一些资料,但不是很明白。我的思路是让pwm每隔一段时间产生一个中断,在中断中改变pwm的频率,但是改变频率应该是改变ARR的值还是PSC的值?还有这需要几个定时器才能完成?

最佳答案

查看完整内容[请看2#楼]

[mw_shl_code=c,true]#include "stm32f10x.h" #include <OS_Config.h> extern int read_D(u16 ndata,u8 dbit); extern void write_D(u16 ndata,u8 dbit,int d); extern u16 read_M(u16 ndata); extern void write_M(u16 ndata,u8 mbit ); extern void BSP_pwm(void); extern void BSP_IO(void); extern void PWM(void ); vu16 CCR1_Val = 695; /* 初始化输出比较通道1计数周期变量*/ vu16 CCR2_Val = 20000; ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

40

主题

107

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
308
金钱
308
注册时间
2014-11-21
在线时间
22 小时
发表于 2015-5-17 18:11:31 | 显示全部楼层
[mw_shl_code=c,true]#include "stm32f10x.h" #include <OS_Config.h> extern int read_D(u16 ndata,u8 dbit); extern void write_D(u16 ndata,u8 dbit,int d); extern u16 read_M(u16 ndata); extern void write_M(u16 ndata,u8 mbit ); extern void BSP_pwm(void); extern void BSP_IO(void); extern void PWM(void ); vu16 CCR1_Val = 695; /* 初始化输出比较通道1计数周期变量*/ vu16 CCR2_Val = 20000; /* 初始化输出比较通道2计数周期变量*/ vu16 CCR3_Val = 10000; /* 初始化输出比较通道3计数周期变量*/ vu16 CCR4_Val = 5000; /* 初始化输出比较通道4计数周期变量*/ u32 arr,psc,psc1; u8 pwm,pwm1,PLSY_0,Y0_d32; u8 D32,W0,P0,P1; //D32 PLSY/DPLSY切换,W0开写当前脉冲数,P0 P1 频率大于小于1000切换 /***********************配置RCC寄存器组,使用PLL输出72MHz时钟并作为主时钟源***********************************/ void RCC_Configuration(void)//设置系统各部分时钟 { /* 定义枚举类型变量 HSEStartUpStatus */ ErrorStatus HSEStartUpStatus; /* 复位系统时钟设置*/ RCC_DeInit(); /* 开启HSE*/ RCC_HSEConfig(RCC_HSE_ON); /* 等待HSE起振并稳定*/ HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* 判断HSE起是否振成功,是则进入if()内部 */ if(HSEStartUpStatus == SUCCESS) { /* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */ RCC_PCLK2Config(RCC_HCLK_Div1); /* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */ RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* 使能PLL */ RCC_PLLCmd(ENABLE); /* 等待PLL输出稳定 */ while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); /* 选择SYSCLK时钟源为PLL */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* 等待PLL成为SYSCLK时钟源 */ while(RCC_GetSYSCLKSource() != 0x08); } /* 打开 TIM2 时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* 打开 APB 总线上的 GPIOA,USART1 时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); } void TIM_Configuration(void) { /* 定义 TIM_TimeBase 初始化结构体 TIM_TimeBaseStructure */ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /* 定义 TIM_OCInit 初始化结构体 TIM_OCInitStructure */ TIM_OCInitTypeDef TIM_OCInitStructure; /* * 计数重载值为65535 * 预分频值为(7199 + 1 = 7200) * 时钟分割0 * 向上计数模式 */ TIM_TimeBaseStructure.TIM_Period = 65535; //如TIM_Period = 0x3E7则波形频率为TIMCLK/(0x3E7+1) // 且只要TIM_Period 不为零,则其TIMCLK为系统频率的一半 if (arr > 1000)TIM_TimeBaseStructure.TIM_Prescaler = 0; //分频 TIMCLK/(0x3E7+1)/(TIM_Prescaler+1) if (arr <= 1000)TIM_TimeBaseStructure.TIM_Prescaler = 999; //分频 TIMCLK/(0x3E7+1)/(TIM_Prescaler+1) TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2 , &TIM_TimeBaseStructure); /* * 设置 OC1,OC2,OC3,OC4 通道 * 工作模式为计数器模式 * 使能比较匹配输出极性 * 时钟分割0 * 向上计数模式 */ //TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Single); //只输出一个脉冲 TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OC1Init(TIM2, &TIM_OCInitStructure); // TIM_OCInitStructure.TIM_Pulse = CCR2_Val; // TIM_OC2Init(TIM2, &TIM_OCInitStructure); // // TIM_OCInitStructure.TIM_Pulse = CCR3_Val; // TIM_OC3Init(TIM2, &TIM_OCInitStructure); // // TIM_OCInitStructure.TIM_Pulse = CCR4_Val; // TIM_OC4Init(TIM2, &TIM_OCInitStructure); /* 禁止预装载寄存器 */ TIM_OC1PreloadConfig(TIM2 , TIM_OCPreload_Disable);//若没有禁止预装载寄存器,则每次计数至65525过程中 //总在当前固定值处发生计数比较匹配事件,并请求计数比较匹配中断,执行中断服务函数* // TIM_OC2PreloadConfig(TIM2 , TIM_OCPreload_Disable); // TIM_OC3PreloadConfig(TIM2 , TIM_OCPreload_Disable); // TIM_OC4PreloadConfig(TIM2 , TIM_OCPreload_Disable); // TIM_ITConfig(TIM2 , TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 , ENABLE); TIM_ARRPreloadConfig(TIM2, ENABLE); TIM_ITConfig(TIM2 , TIM_IT_CC1, ENABLE); } void PWM(void ) { if (PLSY_0 == 1) //脉冲启动 { if(W0 == 0) { if(Y0_d32 == 0)write_D (8140,1,psc1/2),W0 = 1; //当前脉冲数 else write_D (8140,2,psc1/2),W0 = 1; //当前脉冲数 } if (arr > 1000) { CCR1_Val = 36000000/arr ; if (P0 == 0) TIM_Cmd(TIM2 , DISABLE ),pwm = 0,P0 = 1,P1 = 0; } if (arr <= 1000) { CCR1_Val = 36000/arr ; if (P1 == 0) TIM_Cmd(TIM2 , DISABLE ),pwm = 0,P1 = 1,P0 = 0; } /* 启动 TIM 计数 */ if (pwm == 0) { Y00 = 1; BSP_pwm (); TIM_Configuration(); TIM_Cmd(TIM2 , ENABLE); pwm = 1; pwm1 = 1; } } else { TIM_Cmd(TIM2 , DISABLE ); if(Y0_d32 == 0)psc1 = read_D (7900,1)*2; else psc1 = read_D (7900,2)*2; pwm = 0; if (pwm1 == 1) { pwm1 = 0; BSP_IO (); Y00 = 1; } } } static void PLSY(void) { u8 H0,H1,H2,H3,L0,L1,L2,L3; u16 S1,S2; u8 S3,S4; H0 = *p_prog/0x100,L0 = *p_prog%0x100,p_prog++; H1 = *p_prog/0x100,L1 = *p_prog%0x100,p_prog++; H2 = *p_prog/0x100,L2 = *p_prog%0x100,p_prog++; H3 = *p_prog/0x100,L3 = *p_prog%0x100,p_prog++; if (*p_prog/0x100 == 0x84)S3 = *p_prog%0x100,p_prog++; else p_prog++; if (*p_prog/0x100 == 0x80)S4 = *p_prog%0x100,p_prog++; else p_prog++; if(H0 == 0x86) //D { if (H1 == 0x86) S1 = (L0 + L1 * 256)/2; //D<1000 if (H1 == 0x88) S1 = (L0 + L1 * 256)/2 + 1000; //D>=1000 } if ((H0 == 0x80 || H0 == 0x82) && H1 == 0x80) S1 = (L0 + L1 * 256); if(H2 == 0x86) //D { if (H3 == 0x86)S2 = (L2 + L3 * 256)/2; if (H3 == 0x88) S2 = (L2 + L3 * 256)/2 + 1000; } if ((H2 == 0x80 || H2 == 0x82) && H3 == 0x80) S2 = (L2 + L3 * 256); if((process_value&0X01)==0X01) { if (H0 == 0x86 && (H1 == 0x86 || H1 == 0x88)) arr = read_D (S1,1); if ((H0 == 0x80 || H0 == 0x82) && H1 == 0x80) arr = S1; //常数 if(S3 == 0x00 && S4 == 0x05) PLSY_0 = 1,Y0_d32 = 0; } else { if (H2 == 0x86 && (H3 == 0x86 || H3 == 0x88)) psc = read_D (S2,1)*2; if ((H2 == 0x80 || H2 == 0x82) && H3 == 0x80) psc = S2*2; //常数 PLSY_0 = 0; } }[/mw_shl_code]

arr 是频率 psc是脉冲数

1~数百KHz可调 

打倒A莫,打倒小日本
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2015-5-17 23:16:32 | 显示全部楼层
帮顶。。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

3

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1209
金钱
1209
注册时间
2015-5-17
在线时间
115 小时
 楼主| 发表于 2015-5-18 01:43:52 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
感谢原子哥帮顶,更希望您能帮我解答,不甚感激!
回复

使用道具 举报

0

主题

19

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2015-5-13
在线时间
1 小时
发表于 2015-5-20 16:12:58 | 显示全部楼层
回复【3楼】牧笛:
---------------------------------改变 定时器的频率就可以啊。开启和关闭定时器交替执行
回复

使用道具 举报

1

主题

3

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1209
金钱
1209
注册时间
2015-5-17
在线时间
115 小时
 楼主| 发表于 2015-5-24 17:10:07 | 显示全部楼层
回复【4楼】randy1986:
---------------------------------
麻烦您说详细点,我要输入初速度、末速度、最大速度和总脉冲数,应该怎样改变频率
回复

使用道具 举报

0

主题

19

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2015-5-13
在线时间
1 小时
发表于 2015-5-27 14:38:11 | 显示全部楼层
回复【5楼】牧笛:
---------------------------------通过关闭开启定时器,控制 定时器。
                             通过设置定时器频率,控制电机转速。
比如,200 和 300,  你先设置200的频率,开定时器,开一段时间后关定时器,设置300的频率,开一段时间的定时器。
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
发表于 2015-5-27 16:21:37 | 显示全部楼层
感觉这得看下是什么电机吧,是步进电机,感应电机还是直流的还是交流的,一般是PSC改变频率,arr改变占空比
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

5

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
88
金钱
88
注册时间
2013-12-14
在线时间
12 小时
发表于 2015-6-25 11:14:26 | 显示全部楼层
我一个四轴的梯形加减速源码,支持0~250k,dma方式发送任意脉冲数
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2016-8-30
在线时间
2 小时
发表于 2016-8-30 16:47:18 | 显示全部楼层
puu1111 发表于 2015-6-25 11:14
我一个四轴的梯形加减速源码,支持0~250k,dma方式发送任意脉冲数

能给我参考一下吗/
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2016-8-30
在线时间
2 小时
发表于 2016-8-30 16:50:50 | 显示全部楼层
puu1111 发表于 2015-6-25 11:14
我一个四轴的梯形加减速源码,支持0~250k,dma方式发送任意脉冲数

我的邮箱983462476@qq.com   最近在学习这个
回复

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-3-26
在线时间
19 小时
发表于 2019-10-24 08:59:40 | 显示全部楼层
puu1111 发表于 2015-6-25 11:14
我一个四轴的梯形加减速源码,支持0~250k,dma方式发送任意脉冲数

zp17777@163.com 能给我一下吗,哥哥,最近就在为这一个事情发愁。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-2 20:22

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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