关于STM32单片机重启后舵机卡死问题

概况

本程序使用TIM5通用定时器的输出比较功能实现pwm输出,程序运行时出现舵机向一边旋转直接卡死的故障。
芯片型号:STM32F103ZET6,
所用定时器:TIM5,72分频,
定时器预装载值:20000-1,周期20ms

​故障现象

STM32舵机向一边转直接卡死:
2023年10月6日在调试stm32智能小车时舵机出现直接卡死的情况,主要表现为刚下载好程序舵机可以正常工作,完全断开电源小车电源重启舵机直接向右旋转直到完全卡死不动弹。再次下载程序恢复正常,之后每次重启都需要重新下载,舵机才会正常工作。
被卡死的舵机

调试过程

于是本人尝试断开舵机,直接测量pwm波形。
重启之前波形如下,由此可见波形是正常的。

stm32单片机断电重启之前的波形

然后断电重启之后就出现问题了,波形杂乱无章。
STM32断电重启之后的波形
原因是预分频因子没有配置,导致重启后波形无法正常输出。
修复后的代码片段
添加红圈内代码后工作正常。

完整代码

dri_servo_motor.h

#ifndef __DRI_SERVO_MOTOR_H__

#define __DRI_SERVO_MOTOR_H__


#include "stm32f10x.h"

//定义舵机GPIO引脚,以及所对应的时钟
#define SERVO_GPIO_PIN    GPIO_Pin_0
#define SERVO_GPIO_PORT    GPIOA
#define SERVO_GPIO_CLK    RCC_APB2Periph_GPIOA

//定义舵机定时器
#define SERVO_TIM                                TIM5
#define SERVO_TIM_CLK                        RCC_APB1Periph_TIM5
//舵机的定时器时钟开启函数
#define SERVO_TIM_CLK_CMD_FUNC     RCC_APB1PeriphClockCmd

#define SERVO_MOTOR_LEFT                 150
#define SERVO_MOTOR_RIGHT             30
#define SERVO_MOTOR_MIDDLE            90

/**********************************************
*函数名:dri_servo_motor_init(void)
*功能:初始化舵机GPIO和定时器
*参数:无
*返回值:无
*其他说明:无
***********************************************/
void dri_servo_motor_init(void);

/**********************************************
*函数名:void dri_servo_motor_postion(uint32_t angle)
*功能:舵机设定转角
*参数:
            angle:设定角度0-180°超过不会动作
*返回值:无
*其他说明:无
***********************************************/
void dri_servo_motor_postion(uint32_t angle);



#endif

dri_servo_motor.c

#include "dri_servo_motor.h"


#define    COMPARISON_VAL(angle) (((2000/180)*angle)+500)

/**********************************************
*函数名:dri_servo_motor_init(void)
*功能:    初始化舵机GPIO和定时器
*参数:无
*返回值:无
*其他说明:无
***********************************************/
void dri_servo_motor_init(void)
{
    RCC_APB2PeriphClockCmd(SERVO_GPIO_CLK|RCC_APB2Periph_AFIO,ENABLE);
    SERVO_TIM_CLK_CMD_FUNC(SERVO_TIM_CLK,ENABLE);
    
    /*初始化舵机GPIO*/
    GPIO_InitTypeDef GPIO_Initstructure;
    GPIO_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Initstructure.GPIO_Pin = SERVO_GPIO_PIN;
    GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SERVO_GPIO_PORT,&GPIO_Initstructure);

    /*初始化时基单元*/
    TIM_TimeBaseInitTypeDef TIMBaseInitstructure;
    TIMBaseInitstructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIMBaseInitstructure.TIM_Prescaler = 72-1;
    TIMBaseInitstructure.TIM_Period = 20000-1;
    TIMBaseInitstructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(SERVO_TIM,&TIMBaseInitstructure);
    
    /*输出比较单元初始化*/
    TIM_OCInitTypeDef TIM_OCInitstructure;
    TIM_OCInitstructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    TIM_OCInitstructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitstructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitstructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitstructure.TIM_Pulse = COMPARISON_VAL(90);
    TIM_OC1Init(SERVO_TIM,&TIM_OCInitstructure);

}

/**********************************************
*函数名:void dri_servo_motor_postion(uint32_t angle)
*功能:舵机设定转角
*参数:
            angle:设定角度0-180°超过不会动作
*返回值:无
*其他说明:无
***********************************************/
void dri_servo_motor_postion(uint32_t angle)
{
    if(angle > 180) return;
    
    TIM_SetCompare1(SERVO_TIM,COMPARISON_VAL(angle));
    TIM_Cmd(SERVO_TIM,ENABLE);
}




main.c

#include "stm32f10x.h"
#include "interface.h"

//蜂鸣器
#include "dri_beep.h"

//滴答定时器
#include "dri_systick.h"

//led
#include "dri_led.h"

//舵机控制程序
#include "dri_servo_motor.h"

int main()
{        
  
    uint8_t i = 0;
    dri_beep_init();
    dri_led_init();
    dri_servo_motor_init();
    
    while(1)
    {        if(i<3){    
        dri_servo_motor_postion(SERVO_MOTOR_LEFT);
        dri_systick_delay_ms(500);
        dri_servo_motor_postion(SERVO_MOTOR_MIDDLE);
        dri_systick_delay_ms(500);
        dri_servo_motor_postion(SERVO_MOTOR_RIGHT);
        dri_systick_delay_ms(500);
        i++;
        }else{
            dri_servo_motor_postion(SERVO_MOTOR_MIDDLE);
        }
    }
}

现象:
舵机左中右方向依次摆动,动作重复三次。最后回到舵机回到中间停止不动。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值