51单片机从零开始入门教程(直流电机篇)

参考教程:[15-1] 直流电机驱动(PWM)_哔哩哔哩_bilibili

1、直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转。直流电机主要由永磁体(定子)、线圈(转子)和换向器组成。除直流电机外,常见的电机还有步进电机、舵机、无刷电机、空心杯电机等。

2、电机驱动电路:

(1)大功率器件直接驱动:(D1二极管用于保护电路,否则断电后,由于电机有电感的特性,但是电路却是断路,因此电机两端的电压会异常地高;电机只能单向转动)

(2)H桥驱动:(电机可以正向转动,也可以逆向转动,要求三极管有很强的耐压特性)

(3)开发板上的电机模块:VCC和OUT1接电机的两端,当然,电机一端接VCC另一端可以接OUT1-4,下面代码以接OUT1为准,OUT1的电平与IN1的电平相同,也就是与P10有关,且OUT1高电平才能驱动电机转动(这点可以看原理图中是否有非门,或者说看有没有取反,一般引脚有取反的都是对应低电平驱动,没有取反的都是高电平驱动)。

3、PWM:PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。

4、产生PWM方法:

(1)模型结构:

(2)波形:

5、LED呼吸灯:

(1)理论上给LED灯一个模拟信号(如上面那个紫色虚线的波形),LED灯的亮度可以从低慢慢变高,再从高慢慢变低,但是这在单片机中难以实现(因为软件中只能写出数字信号),不过可以给LED灯一个占空比不断变化的方波脉冲(可能不是专业名词,能理解就行),因为有PWM调制,就相当于给了LED一个模拟信号量

(2)将下列代码添加到main.c文件中,然后进行编译、调试。

#include <REGX52.H>

sbit LED = P2^0;  //第一盏LED灯

void Delay(unsigned int t)  //简陋的延时函数
{
	while(t--);
}

void main()
{
	unsigned char Time, i;
	while(1)
	{
		for(Time=0;Time<100;Time++)  //亮度增加(通过改变占空比实现)
		{
			for(i=0;i<20;i++)  //20个相同脉宽的脉冲
			{
				LED=0;
				Delay(Time);  //低电平占时Time(亮度逐渐变大)
				LED=1;
				Delay(100 - Time);  //高电平占时100 - Time(暗度逐渐变小)
			}
		}
//亮度达到巅峰
		for(Time=100;Time>0;Time--)  //亮度下降(通过改变占空比实现)
		{
			for(i=0;i<20;i++)  //20个相同脉宽的脉冲
			{
				LED=0;
				Delay(Time);  //低电平占时Time(亮度逐渐变小)
				LED=1;
				Delay(100 - Time);  //高电平占时100 - Time(暗度逐渐变大)
			}
		}
//LED完全熄灭
	}
}

6、按键调节直流电机转速:

(1)为了调节直流电机转速,在下面的代码中会引入变量Compare,这是用户自设的一个比较值,当计数器低于比较值时输出高电平、高于比较值时输出低电平,通过更改比较值产生占空比不同的脉冲,以此达到调节直流电机转速的目的。(直流电机由方波信号驱动,高电平时直流电机工作,低电平时会由于惯性继续运动,不过运动速度逐渐下降)

(2)将直流电机导线的一端插到开发板步进电机模块的U5脚,另一端插到U5隔壁的1号脚,然后在项目中添加下列文件,接着进行编译,按照main.c文件中的注释进行调试。(独立按键和数码管可以不用定时器扫描,我的项目中独立按键是用定时器扫描,数码管则不是,所以不用延时函数,另外数码管只需要静态显示即可,所以不需要消影)

①Timer0.c文件:

#include <REGX52.H>

/**
  * @brief  定时器0初始化,100us@11.0592MHz
  * @param  无
  * @retval 无
  */
void Timer0_Init()
{
	
	TMOD = 0x01;
	//仅关注0-3位,0位和1位决定配置定时器0为模式1(16位定时器/计数器)
	//2位决定选择定时器功能(与之相对的是计数器功能)
	//3位决定打开定时器(具体见原理图以及手册)
	//TMOD“不可位寻址”,也就是说对其进行配置的话不能按位进行配置,要“一气呵成”
	
	TF0 = 0;  //中断标志位初始化为0,计数产生溢出时该位被置为1,向CPU发出中断请求,CPU响应中断后该位被置为0
	TR0 = 1;  //允许定时器T0计数
	//由于TMOD的3位,也就是GATE被置为了0,那么无论IE0、IT0如何配置,结果都是一样的
	
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	
	ET0 = 1;
	EA = 1;
	PT0 = 0;
	//结合原理图理解,这是在配置中断系统,创造产生中断的环境
	
}

/* 定时器0函数中断模板
void Timer0_Routine()  interrupt 1  //CPU响应中断后执行的函数(每隔100us执行一次)
{
	static unsigned int T0Count = 0;  //定义计数器
	
	T0Count++;
	
	if(T0Count >= 10000)  //每10000个中断信号(1秒)执行一次下面的代码段
	{
		T0Count = 0;
	}
	
	//每次中断结束都要重置计数单元
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
}
*/

②main.c文件:

#include <REGX52.H>
#include "Nixie.h"
#include "Timer0.h"
#include "key.h"

sbit Motor = P1^0;  //电机(是P1^0还是P2^0,具体看开发板的原理图)
unsigned char Counter, Compare;
unsigned char KeyNum;
unsigned char Speed;

void main()
{
	Timer0_Init();
	Compare = 0;
	while(1)
	{
		KeyNum = Key();
		if(KeyNum == 1)  //每按一次按键1,转速提高一级
		{
			Speed++;  //转速等级分为4级
			Speed %= 4;  //超过3级,转速回归0级
			if(Speed == 0){Compare = 0;}  //不转
			if(Speed == 1){Compare = 5;}  //慢转
			if(Speed == 2){Compare = 50;} //稍快转
			if(Speed == 3){Compare = 100;}//快转
		}
		Nixie(2,Speed);  //第二个数码管显示当前档位
	}
}

void Timer0_Routine()  interrupt 1  //CPU响应中断后执行的函数
{
	static unsigned int T0Count = 0;  //定义计数器
	
	T0Count++;
	
	if(T0Count >= 200)  //每200个中断信号(20ms)执行一次下面的代码段(20ms正好是按键消抖需要的时间)
	{
		Key_Loop();  //定时器扫描独立按键
		T0Count = 0;
	}
	
	Counter++;
	Counter %= 100;
	
	if(Counter < Compare)  //计数器和自设比较值比较
	{
		Motor = 1;  //计数器低于比较值,输出高电平
	}
	else
	{
		Motor = 0;  //计数器高于比较值,输出低电平
	}
	
	//每次中断结束都要重置计数单元
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
}
  • 12
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevalin爱灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值