赞
踩
本程序使用TIM5通用定时器的输出比较功能实现pwm输出,程序运行时出现舵机向一边旋转直接卡死的故障。
芯片型号:STM32F103ZET6,
所用定时器:TIM5,72分频,
定时器预装载值:20000-1,周期20ms
STM32舵机向一边转直接卡死:
2023年10月6日在调试stm32智能小车时舵机出现直接卡死的情况,主要表现为刚下载好程序舵机可以正常工作,完全断开电源小车电源重启舵机直接向右旋转直到完全卡死不动弹。再次下载程序恢复正常,之后每次重启都需要重新下载,舵机才会正常工作。
于是本人尝试断开舵机,直接测量pwm波形。
重启之前波形如下,由此可见波形是正常的。
然后断电重启之后就出现问题了,波形杂乱无章。
原因是预分频因子没有配置,导致重启后波形无法正常输出。
添加红圈内代码后工作正常。
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); } } }
现象:
舵机左中右方向依次摆动,动作重复三次。最后回到舵机回到中间停止不动。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。