当前位置:   article > 正文

stm32驱动直流电机实现启动/加速/减速/倒车/停车等功能_stm32底层驱动程序

stm32底层驱动程序

不积跬步,无以至千里;不积小流,无以成江海。
大家好,我是闲鹤,公众号 xxh_zone,十多年开发、架构经验,先后在华为、迅雷服役过,也在高校从事教学3年;目前已创业了7年多,主要从事物联网/车联网相关领域和业务。
喜欢交友、骑行、写毛笔字、弹吉他、折腾硬件和写代码。

ps:
如对以下内容有疑问或者咨询,可进行留言 或 添加我的微信公众号留言

原理

  1. 使用 PWM 输出脉冲信号
  2. 直流电机驱动TB6612
    通过驱动模块,实现直流电机的启动、停止、加速、减速和倒车

演示视频
https://www.bilibili.com/video/BV1Ai421e7sv/?vd_source=f1d43113e0df5436df9402483a18e193

电路图:
file

主要实现的功能:

  1. 启动 MC_Start
  2. 停止 MC_Stop
  3. 加速 MC_ACC
  4. 减速 MC_DEC
  5. 倒车 MC_Back

模块封装

代码层封装成了4部分:

  1. PWM 驱动
    这里主要封装了 OC 相关的配置,比如:ARR、PSC等,同时向外提供了修改 CCR 值的函数,以实现 PWM 脉宽的改变(占空比),从而实现电机的旋转速度
  2. 直流电机驱动
    1. 对 PWM 的封装
    2. 驱动 TB6612 模块
    3. 提供了 Motor_InitMotor_StartMotor_StopMotor_ForwardMotor_ReverseMotor_Accelerate 函数
  3. 直流电机控制
    1. 对 直流电机驱动 封装
    2. 提供5个按钮功能,分别实现:启动(MC_Start)、停止(MC_Stop)、加速(MC_ACC)、加速(MC_DEC)、倒车(MC_Back) 和 就绪(MC_Ready)
      就绪(MC_Ready)又是对前面5个接口的封装,在主函数内部只需要调用这个一个函数即可
  4. 运行主入口
    程序的入口,初始化了直流电机控制,调用了 MC_Ready 函数,并且把相关信息输出到 OLED 屏

整体代码结构图:
file

源码

PWM.c

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	// 时基
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
	TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStruct.TIM_Period = 100 - 1;
	TIM_TimeBaseStruct.TIM_Prescaler = 36 - 1;
	TIM_TimeBaseStruct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStruct);
	
	// OC
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_OCStructInit(&TIM_OCInitStruct);
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse = 0;
	TIM_OC1Init(TIM2, &TIM_OCInitStruct);
	
	// 输出
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	TIM_Cmd(TIM2, ENABLE);
}

void PWM_SetCompare(uint8_t compare)
{
	TIM_SetCompare1(TIM2, compare);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

Motor.c


#include "Motor.h"
#include "PWM.h"

#define IN1 GPIO_Pin_10
#define IN2 GPIO_Pin_11

void Motor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin = IN1 | IN2;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	PWM_Init();
}

/**
 启动
**/
void Motor_Start(void)
{
	Motor_Forward();
	Motor_Accelerate(30);
}

/*
	停止
*/
void Motor_Stop(void)
{
	GPIO_ResetBits(GPIOA, IN1);
	GPIO_ResetBits(GPIOA, IN2);
}


/**
 正转 前进
**/
void Motor_Forward(void)
{
	GPIO_SetBits(GPIOA, IN1);
	GPIO_ResetBits(GPIOA, IN2);
}

/**
 反转 后退
**/
void Motor_Reverse(void)
{
	GPIO_SetBits(GPIOA, IN2);
	GPIO_ResetBits(GPIOA, IN1);
}

/**
 加速
**/
void Motor_Accelerate(uint8_t speed)
{
	PWM_SetCompare(speed);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

MotorControl.c

#include "stm32f10x.h"                  // Device header
#include "MotorControl.h"
#include "Delay.h"
#include "Motor.h"

/*
	提供
	1. 启动按键 B12
	2. 停止按键 B13
	3. 加速按键 B14
	4. 减速按键 B15
	5. 倒车按键 B11
*/

#define MC_KEY_GPIO			GPIOB

#define MC_START_KEY_PIN	GPIO_Pin_11
#define MC_START_KEY_GPIO	GPIOB

#define MC_STOP_KEY_PIN		GPIO_Pin_10
#define MC_STOP_KEY_GPIO	GPIOB

#define MC_ACC_KEY_PIN		GPIO_Pin_0
#define MC_ACC_KEY_GPIO		GPIOB

#define MC_DEC_KEY_PIN		GPIO_Pin_6
#define MC_DEC_KEY_GPIO		GPIOA

#define MC_BACK_KEY_PIN		GPIO_Pin_3
#define MC_BACK_KEY_GPIO	GPIOA

int8_t speed = 0;
uint8_t is_running = 0;

void MC_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 低电平有效
	GPIO_InitStruct.GPIO_Pin = MC_START_KEY_PIN | MC_STOP_KEY_PIN | MC_ACC_KEY_PIN | MC_DEC_KEY_PIN | MC_BACK_KEY_PIN;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	Motor_Init();
}

/**
	启动
**/
void MC_Start(void)
{
	if(GPIO_ReadInputDataBit(MC_START_KEY_GPIO, MC_START_KEY_PIN) == 0) {
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(MC_START_KEY_GPIO, MC_START_KEY_PIN) == 0);
		Delay_ms(20);
		speed = 30;
		is_running = 1;
		Motor_Forward();
		Motor_Accelerate(speed);
	}
}

/**
	停止
**/
void MC_Stop(void)
{
	if(GPIO_ReadInputDataBit(MC_STOP_KEY_GPIO, MC_STOP_KEY_PIN) == 0) {
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(MC_STOP_KEY_GPIO, MC_STOP_KEY_PIN) == 0);
		Delay_ms(20);
		speed = 0;
		is_running = 0;
		Motor_Stop();
	}
}

/**
	加速
**/
void MC_ACC(void)
{
	if(is_running == 0) return;
	if(GPIO_ReadInputDataBit(MC_ACC_KEY_GPIO, MC_ACC_KEY_PIN) == 0) {
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(MC_ACC_KEY_GPIO, MC_ACC_KEY_PIN) == 0);
		Delay_ms(20);
		speed += 20;
		if(speed >= 100) speed = 100;
		Motor_Accelerate(speed);
	}
}

/**
	减速
**/
void MC_DEC(void)
{
	if(is_running == 0) return;
	if(GPIO_ReadInputDataBit(MC_DEC_KEY_GPIO, MC_DEC_KEY_PIN) == 0) {
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(MC_DEC_KEY_GPIO, MC_DEC_KEY_PIN) == 0);
		Delay_ms(20);
		speed -= 20;
		if(speed <= 0) speed = 0;
		Motor_Accelerate(speed);
	}
}

/**
	倒车
**/
void MC_Back(void)
{
	if(GPIO_ReadInputDataBit(MC_BACK_KEY_GPIO, MC_BACK_KEY_PIN) == 0) {
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(MC_BACK_KEY_GPIO, MC_BACK_KEY_PIN) == 0);
		Delay_ms(20);
		is_running = 1;
		Motor_Reverse();
	}
}

/**
	准备就绪
**/
void MC_Ready(void) 
{
	MC_Start();
	MC_Stop();
	MC_ACC();
	MC_DEC();
	MC_Back();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include <stdio.h>
#include "MotorControl.h"

char loginfo[100] = {0};

extern uint8_t speed;
extern uint8_t is_running;

void Log(uint8_t Line, uint8_t Column)
{
	OLED_ShowString(Line, Column, loginfo);
}

int main() 
{
	OLED_Init();
	MC_Init();
	
	while(1) {
		
		MC_Ready();
		
		sprintf(loginfo, "Run: %s  ", (is_running == 1 ? "Y" : "N"));
		Log(1, 1);
		sprintf(loginfo, "Speed: %d  ", speed);
		Log(2, 1);

	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/837995
推荐阅读
相关标签
  

闽ICP备14008679号