直流电机驱动--DRV8870/AT8870【STM32CubeMX,含驱动代码】【PWM+DMA可调速】

目录

两款芯片的简要说明:

引脚定义:

电路:

控制简要:

MX配置:

代码:

测试:


两款芯片的简要说明:

DRV8870是德州仪器的,AT8870是台湾厂商的,都是直流有刷电机驱动器,它们的引脚定义是一样的,驱动代码也是一样的。
价格方面AT8870稍微贵一点。

引脚定义:

这里供电我给12V,参考电压给VDD(3.3V)

电路:

根据手册给出的典型电路,绘制出自己的电路图
1.直流电机在电刷换向时会产生杂乱的尖峰噪声,在马达两端接一个电容起消除噪声的作用。
2.IN1和IN2通过一个100欧姆的电阻接在单片机的定时器PWM输出引脚,这个100欧姆的电阻起阻抗匹配的作用。

控制简要:

我这里使用需要实现基础的调速功能,所以采用PWM控制,采用慢衰减,(快衰减停止后会滑行一段距离)。对于H桥快衰减和慢衰减的知识这里引用一下这个博主的文章:http://t.csdnimg.cn/ziMEa

MX配置:

我这里用的是STM32G0B1的主控,HAL库开发。这里把IN1配置成PWM,IN2配置成普通IO输出,输出低电平时为正转快衰减,输出高电平时为反转慢衰减;当然,如果想要正反转和衰减模式都可以自由配置,那就把IN2用另一个定时器PWM通道引脚代替,这样可以随时把IN1的PWM关闭并配置成IO输出,再把IN2的PWM打开即可。
配置这两个地方,时钟源选择,通道二配置成PWM模式
这里的系统频率为64M,把定时器配置成1ms,这里不会配置定时器的同学可以去看一下我的这篇文章:http://t.csdnimg.cn/q7ZPc
配置DMA:
这里搞不懂循环模式和正常模式的同学可以去看一下我的这篇文章:

代码:

DrvAT8870.c
#include "DrvAT8870.h"

/*********************************************************
说明:
PWM+DMA驱动AT8870/DRV8870的驱动层文件
*********************************************************/

//AT8870的DC_IN2输出
#define SetIn2Low()  	HAL_GPIO_WritePin(DC_IN2_GPIO_Port, DC_IN2_Pin, GPIO_PIN_RESET)	
#define SetIn2High()  	HAL_GPIO_WritePin(DC_IN2_GPIO_Port, DC_IN2_Pin, GPIO_PIN_SET)	

static u32 AT8870Data[AT8870_ONCE_PWM];//发送区缓存

/*******************************
设置衰减模式
0快衰减1慢衰减
*******************************/
void SetAt8870Mode(u8 mode)
{    
	if(mode)
		SetIn2High();
	else
		SetIn2Low();
}

/*******************************
设置占空比
*******************************/
void SetAt8870PWMDuty(u16 duty)
{    
	u16 i;
	
	for(i=0; i<AT8870_ONCE_PWM; i++)
	{
		AT8870Data[i] = duty;
	}
}

/*******************************
开始发送pwm,DMA模式
*******************************/
void At8870PWMStart()
{
	//HAL库函数,打开DMA传输
	//第三个参数为要发送的数据的起始地址,第四个参数是要发送的个数
	HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, AT8870Data, AT8870_ONCE_PWM);
}


/*******************************
停止发送pwm,DMA模式
*******************************/
void At8870PWMStop(void)
{    	
	HAL_TIM_PWM_Stop_DMA(&htim1, TIM_CHANNEL_2);
}

主要介绍一下HAL_TIM_PWM_Start_DMA函数的第三个参数的意思,这是一个数组,里面存放了控制PWM占空比的数据,那这个数据怎么设置勒,很简单,我们这里的定时器是1ms,即1秒计数1000次,占空比50%时就把这个值设置成500,占空比10%时就是100,总之就是有效电平(这里是高电平)所占一个计数周期的比列乘以一个周期的计数次数。同时,我们这里是不用改变每个PWM的占空比,只要在调速的时候把数组里的100个数据改变掉即可,至于为什么是一次性发送100个,这是因为如果要用到回调来精确控制PWM的个数,100是一个比较合适的数字,这个以后再说。

DrvAT8870.h

#ifndef _DRV_AT8870_H_
#define _DRV_AT8870_H_
#include "DrvSys.h"

#define AT8870_ONCE_PWM    	100	//一次传送的pwm个数


void SetAt8870Mode(u8 mode);
void SetAt8870PWMDuty(u16 duty);
void At8870PWMStart(void);
void At8870PWMStop(void);


#endif
 
  

 

测试:

上机可以运行,能实现变速和正反转

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是基于51单片机的DRV8870驱动直流电机PWM调速代码: ```c #include <reg51.h> // 定义端口 sbit PWM = P1^0; sbit IN1 = P1^1; sbit IN2 = P1^2; // 定义变量 unsigned int speed = 0; // PWM占空比 unsigned char flag = 0; // 电机转动方向标志 // 定义函数 void delay(unsigned int t); // 延时函数 void change_speed(unsigned int s); // 改变PWM占空比函数 void main() { while(1) { // 正转 IN1 = 1; IN2 = 0; for(speed = 0; speed <= 1000; speed += 10) { change_speed(speed); delay(50); } // 反转 IN1 = 0; IN2 = 1; for(speed = 1000; speed >= 0; speed -= 10) { change_speed(speed); delay(50); } } } void delay(unsigned int t) { unsigned int i, j; for(i = t; i > 0; i--) { for(j = 110; j > 0; j--); } } void change_speed(unsigned int s) { unsigned int i; for(i = 1000; i > 0; i--) { if(i <= s) { PWM = 1; } else { PWM = 0; } } } ``` 上述代码中,使用P1口控制了DRV8870的IN1、IN2引脚,控制电机正转和反转;使用P1.0口控制DRV8870PWM引脚,控制PWM信号的占空比。同时,使用定时器延时的方法控制PWM的占空比。 在main函数中,先让电机正转,逐渐加速,直到最大速度;然后让电机反转,逐渐减速,直到停止。可以通过改变delay函数的参数来改变PWM信号的频率,以达到更精确的调速效果。 需要注意的是,具体的PWM占空比和延时时间需要根据实际情况进行调整。 ### 回答2: 使用51单片机驱动DRV8870直流电机进行PWM调速代码如下: ```c #include <reg51.h> sbit IN1 = P1^0; // 设置输入引脚 IN1 为 P1.0 sbit IN2 = P1^1; // 设置输入引脚 IN2 为 P1.1 // 定义PWM占空比的变量 unsigned int dutyCycle = 0; // 延时函数 void delay(unsigned int time) { unsigned int i, j; for(i = 0; i < time; i++) { for(j = 0; j < 125; j++); } } // 定时器0中断服务函数,用于PWM波形输出 void Timer0_ISR() interrupt 1 { if(dutyCycle > 0) { IN1 = 1; // IN1 输出高电平使电机正转 IN2 = 0; // IN2 输出低电平使电机正转 } if(dutyCycle < 100) { // 将占空比转换为脉冲数量 unsigned int pulseCount = (100 - dutyCycle) * 10; delay(pulseCount); IN1 = 0; // IN1 输出低电平使电机停止 IN2 = 0; // IN2 输出低电平使电机停止 delay(100 - pulseCount); } } int main() { TMOD = 0x01; // 将定时器0配置为16位定时器模式 TH0 = 0xDC; // 设置定时器0初始值高字节 TL0 = 0x00; // 设置定时器0初始值低字节 ET0 = 1; // 允许定时器0中断 EA = 1; // 允许总中断 TR0 = 1; // 启动定时器0 while(1) { // 逐渐增加占空比 for(dutyCycle = 0; dutyCycle <= 100; dutyCycle += 10) { delay(1000); // 每隔1秒钟改变一次占空比 } // 逐渐减小占空比 for(dutyCycle = 90; dutyCycle >= 0; dutyCycle -= 10) { delay(1000); // 每隔1秒钟改变一次占空比 } } } ``` 上述代码中,首先定义了P1口的IN1和IN2引脚分别作为DRV8870的IN1和IN2引脚的定义。然后定义了一个代表PWM占空比的变量dutyCycle,并初始化为0。 接下来定义了一个延时函数delay用于控制PWM的占空比。然后定义了定时器0中断服务函数Timer0_ISR,用于输出PWM波形。 在主函数中,配置了定时器0为16位定时器模式,并设置初始值。然后使能定时器0中断和总中断,启动定时器0。 在主循环中,通过循环改变dutyCycle的值,从而改变PWM的占空比,从而控制电机的转速。每次改变占空比后,延时1秒钟。 以上就是使用51单片机驱动DRV8870直流电机进行PWM调速代码。 ### 回答3: 51单片机drv8870驱动直流电机pwm调速代码的编写包括以下几个步骤: 1. 配置51单片机的IO口,将pwm信号输出口与drv8870驱动输入端口连接起来。 2. 设置pwm的频率和占空比。drv8870pwm控制输入采用了低电平有效占空比控制,因此我们需要将占空比转换成一个高电平脉冲的宽度。通过改变脉冲的宽度(高电平时间)来调节电机的速度。 3. 编写一个控制函数来调整占空比。通过改变控制函数的参数来改变占空比值,进而改变电机的转速。 4. 在主函数中调用控制函数,以实现pwm调速。根据需要调整占空比的值,可以通过一个循环不断调整pwm信号的占空比,从而实现直流电机的调速。 下面是一个简化的51单片机drv8870驱动直流电机pwm调速代码的示例: #include <reg52.h> // 51单片机头文件 sbit pwm_out = P1^0; // 设置pwm信号输出口 void init_pwm() { TMOD = 0x01; // Timer0工作在方式1(16位定时器/计数器)下,用于产生pwm信号 TH0 = 0xFF; // Timer0初值设为0xFF,下面的代码中会通过改变TL0的值改变占空比 TL0 = 0xFF; TR0 = 1; // 启动Timer0 } void pwm_control(int duty_cycle) { int pulse_width; pulse_width = (65536 - duty_cycle * 256) / 100; // 将占空比转换为高电平脉冲的宽度 TL0 = pulse_width % 256; // 设置Timer0的低8位 TH0 = pulse_width / 256; // 设置Timer0的高8位 } void main() { init_pwm(); // 初始化pwm信号输出 pwm_control(50); // 设置初始的占空比为50%,即电机半速 while(1) { // 这里可以通过一些方式来改变pwm的占空比,从而实现调速功能 pwm_control(25); // 设置占空比为25%,即电机四分之一速度 // 延时一段时间 pwm_control(75); // 设置占空比为75%,即电机三分之二速度 // 延时一段时间 } } 以上是一个简单的51单片机drv8870驱动直流电机pwm调速代码示例,可以根据实际需要进行适当的修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值