你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F407用PWM的问题??谢谢

[复制链接]
风沙星辰-364087 提问时间:2016-6-21 17:21 /
      最近在做一个项目,需要用到STM32F407的定时器产生一个频率可调的PWM驱动电机,思路是这样的??

     需要放出的PWM放在两个数组里面,cycles表示需要放脉冲的时间(按照定时器单位周期为单位),steps表示在指定的cycles时间内需要放出的脉冲的数量。表示如下:
  1. int16_t steps[10] = {5,-5,6,-7,8,-9,0,3};
  2. uint32_t cycles[10] = {354672,145256,33423,45612,180356,20444,5647343};
复制代码

     最后用STM32F407的PF9(TIM14)作为PWM输出引脚,PC2作为方向引脚,

       思路大概是:我首先开启定时器(定时10ms),在第一次中断中记录该次pwm脉冲的宽度,并把值转化为PSC和ARR的值,采用自动重装模式,也就是在本次中断里面计算出下一个脉冲的宽度,最后选择在中断时自动PSC和ARR的值,进行放脉冲(第一个10ms中断目的就是重装第一个pwm脉冲的宽度,在 10ms之后放出)。
      最后发现实际放出的脉冲数组的每段少放一个脉冲,比如数组的第一列,在354672个周期内放出5个脉冲,实际只放出了4个脉冲,少了一个,数组的每列都少放了一个脉冲,不知道什么情况,我猜测是不是寄存器重装(PSC和ARR的值)装载出了问题?这一块由于不是很熟悉,调试了一个上午,现象依旧,大家帮忙看一下代码?非常感谢!

      初始化函数:
  1. void Motor_Init_T1(void)
  2. {
  3. //定义IO口初始化变量
  4. GPIO_InitTypeDef GPIO_InitStructure;

  5. //定义定时器初始化变量
  6. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  7. TIM_OCInitTypeDef TIM_OCInitStructure;
  8. NVIC_InitTypeDef        NVIC_InitStructure;


  9. //定时器时钟初始化
  10. RCC_APB1PeriphClockCmd(MOTOR1_TIMER_CLOCK, ENABLE);

  11. //IO口时钟初始化
  12. RCC_AHB1PeriphClockCmd(MOTOR1_PU_CLOCK | MOTOR1_DR_CLOCK, ENABLE);


  13. //MOTOR_DR1 IO口初始化
  14. GPIO_InitStructure.GPIO_Pin = MOTOR1_DR_PIN;        
  15. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;        
  16. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;        
  17. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        
  18. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  19. GPIO_Init(MOTOR1_DR_BASE, &GPIO_InitStructure);
  20. //初始化方向引脚电平
  21. MOTOR_DR_OUTBIT = 1;

  22. //初始化MOTOR_PU IO口
  23. GPIO_InitStructure.GPIO_Pin = MOTOR1_PU_PIN ;
  24. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  25. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  26. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  27. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
  28. GPIO_Init(MOTOR1_PU_BASE, &GPIO_InitStructure);

  29. //设置定时器PWM输出到MOTOR_PU1引脚上
  30. GPIO_PinAFConfig(MOTOR1_PU_BASE, MOTOR1_PU_PINSOURCE, GPIO_AF_TIM14);

  31. //定时器中断初始化
  32. NVIC_InitStructure.NVIC_IRQChannel = TIM8_TRG_COM_TIM14_IRQn;
  33. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  34. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  35. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  36. NVIC_Init(&NVIC_InitStructure);

  37. //定时器初始化
  38. TIM_DeInit(TIM14);
  39. TIM_TimeBaseStructure.TIM_Period = 999;
  40. TIM_TimeBaseStructure.TIM_Prescaler = 839;
  41. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  42. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  43. TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);

  44. TIM_OCStructInit(&TIM_OCInitStructure);
  45. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  46. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  47. TIM_OCInitStructure.TIM_Pulse = 0xffff;
  48. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  49. TIM_OC1Init(TIM14, &TIM_OCInitStructure);
  50. TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);

  51. TIM_ClearFlag(TIM14, TIM_FLAG_Update);
  52. TIM_ITConfig(TIM14, TIM_IT_Update, ENABLE);

  53. TIM_ARRPreloadConfig(TIM14, ENABLE);
  54. TIM_Cmd(TIM14, DISABLE);

  55. }
复制代码


     定时器溢出中断处理函数:
  1. uint16_t        serial = 0;
  2. uint16_t        serialOld = 0;
  3. int16_t        dir = 1;
  4. uint16_t count = 0;
  5. uint16_t        period = 1000, prescaler = 840;
  6. uint16_t        pulse = 0xffff;


  7. uint16_t error = 0; //误差累计值,计算脉冲的时间产生的误差,叠加到下一个脉冲中去)
  8. uint32_t times = 0;


  9. uint16_t        serialNums = 1;//要放出脉冲的数组的个数(小于数据的长度即可)
  10. uint16_t        stepNums = 0;



  11. void Motor_ISR_T1( const int16_t * pSteps, const uint32_t        * pCycles)
  12. {
  13. uint32_t        timerPwm = 0;

  14. if(serial <= serialNums)
  15. {
  16. TIM_SetCompare1(TIM14,pulse);        
  17. }
  18. if(count == 0)
  19. {
  20. if(serial < serialNums)
  21. {
  22. if(pSteps[serial] > 0)
  23. {
  24. MOTOR_DR_OUTBIT = 1;        //正方向
  25. count = pSteps[serial];
  26. }
  27. else if(pSteps[serial] < 0)
  28. {
  29. MOTOR_DR_OUTBIT = 0;        //反方向
  30. count = -pSteps[serial];
  31. }
  32. else if (pSteps[serial] == 0)
  33. {
  34. count = 5;
  35. }
  36. times = pCycles[serial] + error;

  37. serial++;
  38. serialOld = serial - 1;
  39. }
  40. else if(serial == serialNums)
  41. {
  42. serial++;
  43. }
  44. else if(serial > serialNums)        //脉冲已经全部放完
  45. {
  46. Motor_Stop_T1();
  47. }
  48. }

  49. if(count > 0)        //有脉冲需要放
  50. {        
  51. timerPwm = times/count;

  52. prescaler = (timerPwm >> 16) + 1;

  53. period = timerPwm/prescaler;

  54. error = timerPwm - period * prescaler;

  55. times = times - timerPwm + error;

  56. TIM_PrescalerConfig(TIM14, prescaler - 1, TIM_PSCReloadMode_Update);
  57. TIM_SetAutoreload(TIM14, period - 1);

  58. if(pSteps[serialOld] == 0)
  59. {
  60. pulse = 0xffff;
  61. }
  62. else
  63. {
  64. pulse = period - (4000/prescaler + 1);
  65. }
  66. count--;
  67. }
  68. }
复制代码


               这里serialNums 为1表示只放出数组的第一列的数据,5个脉冲,实际只放出了4个,如果取2,表示只放出2列总计10个脉冲,前面5个正转,后面5个反转,但是实际只放出了4+4 = 8个脉冲,就是数据每一列都会少放一个脉冲!!!
收藏 评论2 发布时间:2016-6-21 17:21

举报

2个回答
xmshao 回答时间:2016-6-22 17:14:54
会不会跟CCR/ARR预装载配置有关?

请检查确认下。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2 很给力!

查看全部评分

风沙星辰-364087 回答时间:2016-6-26 14:32:21
非常感谢,已经发现是CCR的预装载出现问题,谢谢!!!!

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版