OpenEdv-开源电子网

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

STM32怎么实现精确控制PWM输出数量同时能改变频率?

[复制链接]

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
193
金钱
193
注册时间
2015-2-2
在线时间
53 小时
发表于 2015-2-2 09:28:27 | 显示全部楼层 |阅读模式
5金钱
目前要实现电机加速启动和减速停止,并且要实现精确定位,就是控制PWM输出数量。频率范围 4000-40K
STM32怎么实现精确控制PWM输出数量,驱动的同时能改变频率?
这个问题可能大家问过,我在网上查了些资料,基本有一下几种方法:
1:采样PWM输出模式,外部再弄个IO口接到PWM脚上,用外部中断的办法,单独来计数。此办法可行,但个人感觉不科学,太频繁进入中断,严重影响资源。
2:使用2个定时器,使用一个和PWM频率一致的定时器,使用定时器中断来计数。但计数的过程中怎么实现频率的改变
3:使用1个定时器产生PWM,设定一个量,改变这个量值来改变频率同时波形计数。但实验过程中频率不能较好的线性改变。
------------------------------------------------------------
以上是我个人总结的一些观点,各位大神有没有好的办法!谢谢!!!

最佳答案

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

http://www.openedv.com/posts/list/46194.htm 跟我遇到了一样的问题,看看我的帖子吧,可能对你有帮助
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

29

主题

486

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3083
金钱
3083
注册时间
2014-7-19
在线时间
413 小时
发表于 2015-2-2 09:28:28 | 显示全部楼层
http://www.openedv.com/posts/list/46194.htm
跟我遇到了一样的问题,看看我的帖子吧,可能对你有帮助
电子人生!
回复

使用道具 举报

5

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2013-6-8
在线时间
2 小时
发表于 2015-2-2 09:28:28 | 显示全部楼层
打开PWM捕获中断即可,每输出一个PWM波形,都会响应一次捕获中断,
你在捕获中断计数就是了
即使爬到最高的山上,一次也只能脚踏实地地迈一步。
回复

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
193
金钱
193
注册时间
2015-2-2
在线时间
53 小时
 楼主| 发表于 2015-9-17 15:48:03 | 显示全部楼层
回复【2楼】翱翔云端的鸟:
---------------------------------
过了大半年才回复。呵呵!
按照你的方法控制一路PWM需要2个定时器。是不是占资源?
我目前的方案用一个定时器翻转输出电平,计数输出脉冲数。同时根据脉冲数改变定时器中断时间来改变PWM频率,从而实现电机的加速减速。
系统运行了大半年,算稳定。目前实现梯形加减速,S型的不会!哈哈。
回复

使用道具 举报

4

主题

62

帖子

0

精华

高级会员

Rank: 4

积分
788
金钱
788
注册时间
2015-8-21
在线时间
128 小时
发表于 2015-9-17 16:30:11 | 显示全部楼层
回复【4楼】西域海盗:
---------------------------------
回复【4楼】西域海盗:
---------------------------------
请问下如何控制电机提醒加减速呢?
回复

使用道具 举报

13

主题

60

帖子

0

精华

初级会员

Rank: 2

积分
161
金钱
161
注册时间
2013-12-20
在线时间
8 小时
发表于 2015-9-27 15:14:37 | 显示全部楼层
回复【4楼】西域海盗:
---------------------------------
请问可以给个资料学习吗?
回复

使用道具 举报

36

主题

227

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3096
金钱
3096
注册时间
2016-4-15
在线时间
350 小时
发表于 2018-2-3 18:46:28 | 显示全部楼层
西域海盗 发表于 2015-9-17 15:48
回复【2楼】翱翔云端的鸟:
---------------------------------
过了大半年才回复。呵呵!
按照你的方法控制 ...

那么你每一次改变的频率是多少呢?计算出来的值是否有小数
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2018-12-12
在线时间
2 小时
发表于 2018-12-12 10:21:30 | 显示全部楼层
本帖最后由 电子陌离 于 2018-12-12 10:23 编辑

//看看对你有用不,DutyCycle:占空比    Frequency:频率      jishu:脉冲输入计数//实测没问题的,我做圆织机的
#include "WMinput.h"

volatile u16 IC2Value = 0;
volatile u16 DutyCycle = 0;  //Õ¼¿Õ±è
volatile u32 Frequency = 0;  //ÆμÂê
u16  maijishu = 0;   //¼ÆËãÂö3å
u32 jishu = 0;       //Âö3å½óêÕ
u32 maicojishu = 0;  //Âö3å½óêÕ
float Duty_ycle = 0;               //Õ¼¿Õ±è
float Freq_ncy = 0;                //ÆμÂê


void PWM_INPUT_Config(void)//PWMêäèë2¶»ñ3õê¼»ˉ
{
                GPIO_InitTypeDef  GPIO_InitStructure;
                NVIC_InitTypeDef  NVIC_InitStructure;
                TIM_ICInitTypeDef TIM_ICInitStructure;
          TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     //¸¡¿Õêäèë
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//                GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        //        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
                GPIO_Init(GPIOA,&GPIO_InitStructure);
          GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);
//                GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_2);
    //éèÖÃÆμÂê1MHZ,¼ÆË&#227WMÆμÂêê±òaê1óÃ
                TIM_TimeBaseStructure.TIM_Period = 0xffff;//ÖüÆú0~FFFF
                TIM_TimeBaseStructure.TIM_Prescaler = 72-1;//ê±Öó·ÖÆμ,·ÖÆμêyÎa5+1¼′6·ÖÆμ
                TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//ê±Öó·Ö¸î
                TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//Ä£ê½
                TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);//»ù±¾3õê¼»ˉ        

                NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;//′ò¿aTIM3μÄ諾ÖÖD¶Ï
                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//ÇàÕ¼óÅÏè¼¶Îa0
                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//Ïìó|óÅÏè¼¶Îa1
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //ê1Äü
                NVIC_Init(&NVIC_InitStructure);

/*ê1ÄüË«±ßÑØ¼ì2a*/
//    TIM1->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC1E);
//                TIM1->CCMR1 |= 0x03;
//                TIM1->SMCR |= (1<<6);
//                TIM1->SMCR &= ~((1<<5)|(1<<4));
//                TIM1->CCER |= ((uint16_t)TIM_CCER_CC1E);
               
                TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;   //&#209;&#161;&#212;&#241;ê&#228;è&#235;&#182;&#203;,IC1ó3é&#228;μ&#189;TI1é&#207;
                TIM_ICInitStructure.TIM_ICFilter = 0x0;        //&#197;&#228;&#214;&#195;&#194;&#203;2¨,2&#187;&#194;&#203;2¨
                TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//é&#207;éy&#209;&#216;
                TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //&#197;&#228;&#214;&#195;·&#214;&#198;μ,2&#187;·&#214;&#198;μ
                TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//ó3é&#228;μ&#189;TI1é&#207;
               
//                TIM_ITRxExternalClockConfig(TIM3,TIM_TS_ETRF);          //&#197;&#228;&#214;&#195;ía2&#191;′¥·¢,·&#241;&#212;ò2&#187;&#187;á&#188;&#198;êy
//    TIM_ETRClockMode2Config(TIM3, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
//                TIM_ClearITPendingBit(TIM1,TIM_IT_Update); //
               
                TIM_PWMIConfig(TIM3,&TIM_ICInitStructure); //&#184;ù&#190;Y2&#206;êy&#197;&#228;&#214;&#195;TIMíaéèD&#197;&#207;¢
                TIM_SelectInputTrigger(TIM3,TIM_TS_TI2FP2);  //&#209;&#161;&#212;&#241;IC2&#206;aê&#188;&#214;&#213;′¥·¢&#212;′
                TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//′¥·¢D&#197;o&#197;μ&#196;é&#207;éy&#209;&#216;&#214;&#216;D&#194;3&#245;ê&#188;&#187;ˉ&#188;&#198;êy&#198;÷oí′¥·¢&#188;&#196;′&#230;&#198;÷
                TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);//&#198;&#244;&#182;ˉ&#182;¨ê±&#198;÷μ&#196;±&#187;&#182;ˉ′¥·¢        
                TIM_Cmd(TIM3,ENABLE);                        //&#198;&#244;&#182;ˉ&#182;¨ê±&#198;÷3
                TIM_ITConfig(TIM3,TIM_IT_CC3,ENABLE);        //′ò&#191;a&#214;D&#182;&#207;′|àíoˉêy
}
void TIM3_IRQHandler(void)
{
          TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);  //&#199;&#229;3yTIMμ&#196;&#214;D&#182;&#207;′y′|àí&#206;&#187;
                IC2Value = TIM_GetCapture2(TIM3);        //&#182;áè&#161;IC22&#182;&#187;&#241;&#188;&#196;′&#230;&#198;÷&#214;μ,&#188;′&#206;aPWM&#214;ü&#198;ú&#188;&#198;êy&#214;μ
                maijishu = TIM3->SR;
          if(IC2Value != 0)
                 {
                        DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;   //&#182;áè&#161;IC12&#182;&#187;&#241;&#188;&#196;′&#230;&#198;÷&#214;μ,2¢&#188;&#198;&#203;&#227;&#213;&#188;&#191;&#213;±è
                        Frequency = 1000000 / IC2Value;               //&#188;&#198;&#203;&#227WM&#198;μ&#194;ê,1MHZè&#161;é&#207;&#195;&#230;&#197;&#228;&#214;&#195;
                        Duty_ycle = (float)DutyCycle;
                        Freq_ncy = (float)Frequency;
//                        maijishu = TIM_GetCounter(TIM3);
//                        maijishu = TIM_GetCapture2(TIM3);         
                 }
                else
                 {
                         DutyCycle = 0;
                         Frequency = 0;
                         Freq_ncy = 0;
                         Duty_ycle = 0;
                 }
                 if(maijishu&0x02)     //·¢éú2&#182;&#187;&#241;ê&#194;&#188;t
                 {
                         jishu++;         //&#194;&#246;3&#229;&#188;&#198;êy2&#182;&#187;&#241;é&#207;éy&#209;&#216;&#194;&#246;3&#229;x22&#197;ê&#199;ê&#228;è&#235;&#213;&#230;&#213;yμ&#196;&#194;&#246;3&#229;êy
                         maicojishu = jishu;
                 }
                 TIM3->SR = 0;      //&#199;&#229;3t&#214;D&#182;&#207;±ê&#214;&#190;&#206;&#187;
        // printf("DutyCycle= %d\n",DutyCycle);
        // printf("Frequency= %d\n",Frequency);
}

回复

使用道具 举报

2

主题

57

帖子

0

精华

高级会员

Rank: 4

积分
602
金钱
602
注册时间
2014-3-3
在线时间
57 小时
发表于 2019-4-17 13:47:26 | 显示全部楼层
用这样的方法我尝试过,我用FreeRTOS  来做的,原本想用来控制步进电机的,控制如   速度和距离,但是用定时器产生的PWM输出会不断的进入中断,如果说低速  控制的轴也不多.还能勉强的应付的过来你,三十我做的是6轴,脉冲输出的还必须在10K以上.不断的进入中断,导致我其他优先级较低的任务效率很低下.如果让电机 的PWM降低优先级.又会出现步进电机输出抖动的问题.所有后来我采用的是2片TMC429来完成的
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-22 05:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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