4.6 DRV8833 电机驱动模块
该模块相对于传统的 L298N 效率上提高很多,体积上也大幅度减少,在额定范围内,芯片基本不发热,当然也就显得更加娇贵,所以我们建议有一定动手能力的朋友使用,接线的时候务必细心细心再细心,注意正负极性。
DRV8833 电机驱动模块可直接替换 TB6612 驱动模块,管脚基本完全兼容。
4.6.1 模块来源
采购链接: DRV8833 直流电机驱动模块 驱动器驱动板 替代 TB6612FNG
资料下载:
4.6.2 规格参数
VM电机电压:<12V
VCC芯片电压:2.7~5.5V
输出电流:1A
控制方式:PWM
4.6.3 移植过程
我们的目标是在梁山派 GD32F470 上能够控制电机旋转速度的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
4.6.3.1 查看资料
STBY 口接单片机的 IO 口,STBY 置 0 电机全部停止,置 1 才能工作。STBY 置 1 后通过 AIN1、AIN2、BIN1、BIN2 来控制正反转。
| A 端真值表 | ||||
|---|---|---|---|---|
| AIN1 | 0 | 0 | speed | 1 |
| AIN2 | 0 | speed | 0 | 1 |
| 停止 | 正转 | 反转 | 停止 |
其中 A 端(AIN1 与 AIN2)只能控制 AO1 与 AO2 端。B 端(BIN1 与 BIN2)只能控制 BO1 与 BO2 端。因此是双路电机驱动。speed 为 PWM 控制的占空比,通过占空比控制电机速度。
4.6.3.2 引脚选择
DRV8833 控制电机速度的方式,是通过将 IN1 与 IN2 接入 PWM,直接通过调整 PWM 的占空比进行速度控制。因此要求 AIN1/AIN2/BIN1/BIN2 都要使用 PWM 功能。
这里将 STBY 接入 3.3V,让其一直为高电平,后续的电机停止控制通过 IN1 与 IN2 进行控制。
| DRV8833 | 立创·梁山派 |
|---|---|
| GND | GND |
| VM | 接入外部电源(3.7V-10.8V) |
| AIN1 | PA5 |
| AIN2 | PA7 |
| BIN1 | PA6 |
| BIN2 | PA3 |
| STBY | 3V3 |
4.6.3.3 移植至工程
移植步骤中的导入.c 和.h 文件与之前相同,只是将.c 和.h 文件更改为 bsp_drv8833.c 与 bsp_drv8833.h。见 2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件 bsp_drv8833.c 中,编写如下代码。
/********************************************************************************
* 文 件 名: bsp_drv8833.c
* 版 本 号: 初版
* 修改作者: LC
* 修改日期: 2022年04月19日
* 功能介绍:
******************************************************************************
* 开发板官网:www.lckfb.com
*********************************************************************************/
#include "bsp_drv8833.h"
#include "systick.h"
/******************************************************************
* 函 数 名 称:DRV8833_Init
* 函 数 说 明:PWM配置
* 函 数 形 参: pre定时器时钟预分频值 per周期
* 函 数 返 回:无
* 作 者:LC
* 备 注:PWM频率=200 000 000 /( (pre+1) * (per+1) )
******************************************************************/
void DRV8833_Init(uint16_t pre,uint16_t per)
{
timer_parameter_struct timere_initpara={0}; // 定义定时器结构体
timer_oc_parameter_struct timer_ocintpara={0}; //定时器比较输出结构体
//定时器时钟
rcu_periph_clock_enable(RCU_AIN1_TIMER); // 开启定时器时钟
rcu_periph_clock_enable(RCU_AIN2_TIMER);
rcu_periph_clock_enable(RCU_BIN1_TIMER);
rcu_periph_clock_enable(RCU_BIN2_TIMER);
//引脚时钟
rcu_periph_clock_enable(RCU_AIN1);
rcu_periph_clock_enable(RCU_AIN2);
rcu_periph_clock_enable(RCU_BIN1);
rcu_periph_clock_enable(RCU_BIN2);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); // 配置定时器时钟
/* 配置AIN1*/
gpio_mode_set(PORT_AIN1,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_AIN1);
gpio_output_options_set(PORT_AIN1,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_AIN1);
gpio_af_set(PORT_AIN1,AF_AIN1,GPIO_AIN1);
/* 配置AIN2*/
gpio_mode_set(PORT_AIN2,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_AIN2);
gpio_output_options_set(PORT_AIN2,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_AIN2);
gpio_af_set(PORT_AIN2,AF_AIN2,GPIO_AIN2);
/* 配置BIN1*/
gpio_mode_set(PORT_BIN1,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_BIN1);
gpio_output_options_set(PORT_BIN1,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_BIN1);
gpio_af_set(PORT_BIN1,AF_BIN1,GPIO_BIN1);
/* 配置BIN2*/
gpio_mode_set(PORT_BIN2,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_BIN2);
gpio_output_options_set(PORT_BIN2,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_BIN2);
gpio_af_set(PORT_BIN2,AF_BIN2,GPIO_BIN2);
/* 配置定时器参数 */
timer_deinit(BSP_AIN1_TIMER);
timer_deinit(BSP_AIN2_TIMER);
timer_deinit(BSP_BIN1_TIMER);
timer_deinit(BSP_BIN2_TIMER);
// 复位定时器
timere_initpara.prescaler = pre-1; // 时钟预分频值
timere_initpara.alignedmode = TIMER_COUNTER_EDGE; // 边缘对齐
timere_initpara.counterdirection = TIMER_COUNTER_UP; // 向上计数
timere_initpara.period = per-1; // 周期
timere_initpara.clockdivision = TIMER_CKDIV_DIV1; // 分频因子
timere_initpara.repetitioncounter = 0; // 重复计数器 0-255
timer_init(BSP_AIN1_TIMER,&timere_initpara); // 初始化定时器
timer_init(BSP_AIN2_TIMER,&timere_initpara); // 初始化定时器
timer_init(BSP_BIN1_TIMER,&timere_initpara); // 初始化定时器
timer_init(BSP_BIN2_TIMER,&timere_initpara); // 初始化定时器
/* 配置输出结构体 */
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; // 有效电平的极性
timer_ocintpara.outputstate = TIMER_CCX_ENABLE; // 配置比较输出模式状态 也就是使能PWM输出到端口
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; // 通道互补输出极性为高电平
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; // 通道互补输出状态失能
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; // 信道输出的空闲状态为低
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;// 信道互补输出的空闲状态为低
/* 配置定时器输出功能 */
timer_channel_output_config(BSP_AIN1_TIMER,BSP_AIN1_CHANNEL,&timer_ocintpara);
timer_channel_output_config(BSP_AIN2_TIMER,BSP_AIN2_CHANNEL,&timer_ocintpara);
timer_channel_output_config(BSP_BIN1_TIMER,BSP_BIN1_CHANNEL,&timer_ocintpara);
timer_channel_output_config(BSP_BIN2_TIMER,BSP_BIN2_CHANNEL,&timer_ocintpara);
/* 配置占空比 范围 0 ~ (per-1) */
timer_channel_output_pulse_value_config(BSP_AIN1_TIMER,BSP_AIN1_CHANNEL,0);
timer_channel_output_pulse_value_config(BSP_AIN2_TIMER,BSP_AIN2_CHANNEL,0);
timer_channel_output_pulse_value_config(BSP_BIN1_TIMER,BSP_BIN1_CHANNEL,0);
timer_channel_output_pulse_value_config(BSP_BIN2_TIMER,BSP_BIN2_CHANNEL,0);
timer_channel_output_mode_config(BSP_AIN1_TIMER,BSP_AIN1_CHANNEL,TIMER_OC_MODE_PWM0); // 配置定时器通道输出比较模式
timer_channel_output_mode_config(BSP_AIN2_TIMER,BSP_AIN2_CHANNEL,TIMER_OC_MODE_PWM0); // 配置定时器通道输出比较模式
timer_channel_output_mode_config(BSP_BIN1_TIMER,BSP_BIN1_CHANNEL,TIMER_OC_MODE_PWM0); // 配置定时器通道输出比较模式
timer_channel_output_mode_config(BSP_BIN2_TIMER,BSP_BIN2_CHANNEL,TIMER_OC_MODE_PWM0); // 配置定时器通道输出比较模式
timer_channel_output_shadow_config(BSP_AIN1_TIMER,BSP_AIN1_CHANNEL,TIMER_OC_SHADOW_DISABLE); // 配置定时器通道输出影子寄存器
timer_channel_output_shadow_config(BSP_AIN2_TIMER,BSP_AIN2_CHANNEL,TIMER_OC_SHADOW_DISABLE); // 配置定时器通道输出影子寄存器
timer_channel_output_shadow_config(BSP_BIN1_TIMER,BSP_BIN1_CHANNEL,TIMER_OC_SHADOW_DISABLE); // 配置定时器通道输出影子寄存器
timer_channel_output_shadow_config(BSP_BIN2_TIMER,BSP_BIN2_CHANNEL,TIMER_OC_SHADOW_DISABLE); // 配置定时器通道输出影子寄存器
/* 只有高级定时器使用 */
timer_auto_reload_shadow_enable(BSP_AIN1_TIMER);
timer_auto_reload_shadow_enable(BSP_AIN2_TIMER);
timer_auto_reload_shadow_enable(BSP_BIN1_TIMER);
timer_auto_reload_shadow_enable(BSP_BIN2_TIMER);
timer_primary_output_config(BSP_AIN1_TIMER, ENABLE);
timer_primary_output_config(BSP_AIN2_TIMER, ENABLE);
timer_primary_output_config(BSP_BIN1_TIMER, ENABLE);
timer_primary_output_config(BSP_BIN2_TIMER, ENABLE);
/* 使能定时器 */
timer_enable(BSP_AIN1_TIMER);
timer_enable(BSP_AIN2_TIMER);
timer_enable(BSP_BIN1_TIMER);
timer_enable(BSP_BIN2_TIMER);
}
/******************************************************************
* 函 数 名 称:AO_Control
* 函 数 说 明:A端口电机控制
* 函 数 形 参:dir旋转方向 1正转0反转 speed旋转速度,范围(0 ~ per-1)
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AO_Control(uint8_t dir, uint32_t speed)
{
if( dir == 1 )
{
//AO1输出
timer_channel_output_pulse_value_config(BSP_AIN1_TIMER,BSP_AIN1_CHANNEL, 0 );
//AO2输出
timer_channel_output_pulse_value_config(BSP_AIN2_TIMER,BSP_AIN2_CHANNEL, speed );
}
else
{
//AO1输出
timer_channel_output_pulse_value_config(BSP_AIN1_TIMER,BSP_AIN1_CHANNEL, speed );
//AO2输出
timer_channel_output_pulse_value_config(BSP_AIN2_TIMER,BSP_AIN2_CHANNEL, 0 );
}
}
/******************************************************************
* 函 数 名 称:B0_Control
* 函 数 说 明:B端口电机控制
* 函 数 形 参:dir旋转方向 1正转0反转 speed旋转速度,范围(0 ~ per-1)
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void BO_Control(uint8_t dir, uint32_t speed)
{
if( dir == 1 )
{
//BO1输出
timer_channel_output_pulse_value_config(BSP_BIN1_TIMER,BSP_BIN1_CHANNEL, 0 );
//BO2输出
timer_channel_output_pulse_value_config(BSP_BIN2_TIMER,BSP_BIN2_CHANNEL, speed );
}
else
{
//BO1输出
timer_channel_output_pulse_value_config(BSP_BIN1_TIMER,BSP_BIN1_CHANNEL, speed );
//BO2输出
timer_channel_output_pulse_value_config(BSP_BIN2_TIMER,BSP_BIN2_CHANNEL, 0 );
}
}
/********************************************************************************
* 文 件 名: main.c
* 版 本 号: 初版
* 修改作者: LC
* 修改日期: 2022年04月19日
* 功能介绍:
******************************************************************************
* 开发板官网:www.lckfb.com
*********************************************************************************/
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "bsp_usart.h"
#include "bsp_drv8833.h"
/************************************************
函数名称 : main
功 能 : 主函数
参 数 : 无
返 回 值 : 无
作 者 : LC
*************************************************/
int main(void)
{
int i = 0;
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); // 优先级分组
systick_config(); // 滴答定时器初始化
usart_gpio_config(9600U); // 串口0初始化
DRV8833_Init(10,8000);
while(1)
{
i += 100;
if( i > 8000 ) i = 0;
AO_Control(0,i);//A端电机反转
BO_Control(1,i);//B端电机正转
delay_1ms(50);
}
}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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
在文件 bsp_drv8833.h 中,编写如下代码。
#ifndef _BSP_DRV8833_H
#define _BSP_DRV8833_H
#include "gd32f4xx.h"
#include "systick.h"
#define RCU_AIN1 RCU_GPIOA
#define PORT_AIN1 GPIOA
#define GPIO_AIN1 GPIO_PIN_5
#define AF_AIN1 GPIO_AF_1
#define RCU_AIN2 RCU_GPIOA
#define PORT_AIN2 GPIOA
#define GPIO_AIN2 GPIO_PIN_7
#define AF_AIN2 GPIO_AF_2
#define RCU_BIN1 RCU_GPIOA
#define PORT_BIN1 GPIOA
#define GPIO_BIN1 GPIO_PIN_6
#define AF_BIN1 GPIO_AF_2
#define RCU_BIN2 RCU_GPIOA
#define PORT_BIN2 GPIOA
#define GPIO_BIN2 GPIO_PIN_3
#define AF_BIN2 GPIO_AF_1
#define RCU_AIN1_TIMER RCU_TIMER1
#define BSP_AIN1_TIMER TIMER1 // 定时器
#define BSP_AIN1_CHANNEL TIMER_CH_0 // 定时器通道
#define RCU_AIN2_TIMER RCU_TIMER2
#define BSP_AIN2_TIMER TIMER2 // 定时器
#define BSP_AIN2_CHANNEL TIMER_CH_1 // 定时器通道
#define RCU_BIN1_TIMER RCU_TIMER2
#define BSP_BIN1_TIMER TIMER2 // 定时器
#define BSP_BIN1_CHANNEL TIMER_CH_0 // 定时器通道
#define RCU_BIN2_TIMER RCU_TIMER1
#define BSP_BIN2_TIMER TIMER1 // 定时器
#define BSP_BIN2_CHANNEL TIMER_CH_3 // 定时器通道
#define AIN1_OUT(X) gpio_bit_write(PORT_AIN1, GPIO_AIN1, X?SET:RESET)
#define AIN2_OUT(X) gpio_bit_write(PORT_AIN2, GPIO_AIN2, X?SET:RESET)
#define BIN1_OUT(X) gpio_bit_write(PORT_BIN1, GPIO_BIN1, X?SET:RESET)
#define BIN2_OUT(X) gpio_bit_write(PORT_BIN2, GPIO_BIN2, X?SET:RESET)
void DRV8833_Init(uint16_t pre,uint16_t per);
void AO_Control(uint8_t dir, uint32_t speed);
void BO_Control(uint8_t dir, uint32_t speed);
#endif /* BSP_DRV8833_H */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
4.6.4 移植验证
在自己工程中的 main 主函数中,编写如下。
/********************************************************************************
* 文 件 名: main.c
* 版 本 号: 初版
* 修改作者: LC
* 修改日期: 2022年04月19日
* 功能介绍:
******************************************************************************
* 开发板官网:www.lckfb.com
*********************************************************************************/
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "bsp_usart.h"
#include "bsp_drv8833.h"
/************************************************
函数名称 : main
功 能 : 主函数
参 数 : 无
返 回 值 : 无
作 者 : LC
*************************************************/
int main(void)
{
int i = 0;
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); // 优先级分组
systick_config(); // 滴答定时器初始化
usart_gpio_config(9600U); // 串口0初始化
DRV8833_Init(10,8000);
while(1)
{
i += 100;
if( i > 8000 ) i = 0;
AO_Control(0,i);//A端电机反转
BO_Control(1,i);//B端电机正转
delay_1ms(50);
}
}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
移植现象:两个电机速度由慢变快的正反转。
移植成功示例,见文件 4.6.4-1 。
文件 4.6.4-1 移植成功示例
通过网盘分享的文件:立创·梁山派GD32F470ZGT6开发板【模块移植手册代码】
链接: https://pan.baidu.com/s/1pp44yjD1Dhh7U9iZ2a11IA 提取码: LCKF