51单片机学习笔记-13直流电机

news/2024/12/4 7:56:14/

13 直流电机

[toc]

注:笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。
注:工程及代码文件放在了本人的Github仓库。


13.1 直流电机与PWM波

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

图13-1 直流电机实物图
图13-2 直流电机原理图及驱动方式

根据上述原理图可以看出,由于单片机的IO口没有驱动能力,所以还是依靠外接的ULN2003D芯片进行驱动。从OUT1~OUT4任选两个端口即可完成驱动。对于直流电机,主要有两种供电方式:

  1. 大功率器件直接驱动:只能单向驱动。图中,续流二极管的作用是防止三极管截止时,直流电机中的电容击穿三极管。
  2. H桥驱动:可以双向驱动。
  3. 当然,开发板上采用的驱动芯片ULN2003D,在之前的“9蜂鸣器”一节已经介绍过。

13.1.2 PWM介绍
UP主最开始自己接了电位器(滑动变阻器)来控制直流电机转速,而电源供电端保持电压不变。最后发现,只有当电阻非常小的时候直流电机才开始转。但是直流电机需要的电流大,很容易就使得变阻器发热甚至烧毁。所以此方法并不好,还是要控制电源端的变化,也就是下面的PWM。
PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。PWM重要参数:

  • 频率 = 1/TS。频率越高,平均电压波形的谐波含量就越低。但后续使用生成PWM时,定时器重装频率过快会使主函数执行效率大幅下降。一般设置10~20kHz。
  • 占空比 = TON/TS
  • 精度 = 占空比变化步距

在软件层面,可以使用纯软件延时的方式完成PWM波,常用于“呼吸灯”等需要占空比频繁变化的场合;而对于电机调速这样的场合,期望程序在不调节时保持当前的占空比不变,这种场合下更常用的方法是使用定时器产生PWM波

  1. 对定时器进行计数,计数周期就是PWM波的周期。
  2. 在PWM波发生函数中,设定一个比较阈值,用于控制占空比。
  3. 显然,定时器的精度就是PWM波的精度。
图13-3 使用定时器产生PWM波原理

13.2 实验:LED呼吸灯

需求:全体LED以1秒为周期进行“呼吸式”亮度变化。

注:本实验建议纯软件延时完成PWM调节。即,只有一个主函数。

代码展示:
- mian.c

#include <REGX52.H>sbit LED0 = P2^0;
unsigned int PWM_Period = 100;
unsigned int PWM_Duty = 99;// 延时函数一定要有,但单次延时应在10us以下
void Delay(unsigned int cycles){while(cycles--);
}void main(){unsigned char i;P2 = 0xff; //LED初始全部熄灭while(1){for(PWM_Duty=0;PWM_Duty<PWM_Period;PWM_Duty++){for(i=0;i<10;i++){LED0 = 0;Delay(PWM_Duty);LED0 = 1;Delay(PWM_Period-PWM_Duty);}}for(PWM_Duty=PWM_Period-1;PWM_Duty>0;PWM_Duty--){for(i=0;i<10;i++){LED0 = 0;Delay(PWM_Duty);LED0 = 1;Delay(PWM_Period-PWM_Duty);}}}
}

编程感想:

  1. 关于延时函数:TMD天坑啊!思路其实很简单,但是一定要注意呼吸灯的PWM频率一定要非常快!!量级在1KHz以上(由于PWM周期为100,所以意味着延时函数在10us以下)才会有一个很好的效果。否则就会发现灯亮一下又闪,大晚上一直盯着灯看眼都快瞎了……😖

13.3 实验:直流电机调速

需求:设置直流电机转速等级:Stop、40%、50%、75%、100%。

每按下一次按键Key1,直流电机速度等级就上升一级(上升到最高归零)。
LCD第一行显示“DC motor:”;LCD第二行显示“xxx% Power”,如果为0就闪烁显示“Stop!”。
注:综合考虑程序效率和硬件效果,可设置定时器中断周期100us,PWM周期为100个定时器中断。

图13-4 “直流电机调速”代码调用

代码展示:
-main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "PushKey.h"
#include "Timer0.h"#define motor P1_0
unsigned int PWM_Peri = 100;
unsigned int PWM_Duty = 0;
unsigned char speed_motor[5] = {0,40,50,75,100};void main(){unsigned char key_num=0;//按键的编号unsigned char speed_index=0;//转速等级索引//LCD1602初始化LCD1602_Init();LCD1602_DispString(1,1,"DC motor:");LCD1602_DispString(2,1,"Stop!");//初始化定时器Timer0_Init();while(1){key_num = PushKey_GetKey();if(key_num==1){speed_index++;speed_index%=5;//调整PWM占空比(转速)PWM_Duty = speed_motor[speed_index];  }//LCD更新显示转速等级switch(speed_index){case 0:LCD1602_DispString(2,1,"Stop!     ");break;case 1:LCD1602_DispString(2,1," 40% Power");break;case 2:LCD1602_DispString(2,1," 50% Power");break;case 3:LCD1602_DispString(2,1," 75% Power");break;case 4:LCD1602_DispString(2,1,"100% Power");break;default:;}}
}// 定义定时器T0中断后要执行的动作
void Timer0_Routine() interrupt 1{static unsigned int count1_T0,count2_T0; //中断次数TH0 = 0xFF; TL0 = 0xA4; // 恢复溢出周期,近似100us//对于PWM所需的中断count1_T0++; //更新中断次数if(count1_T0>PWM_Peri){count1_T0 = 0;    }else{if(count1_T0<PWM_Duty){motor=1;}//电机运行else                  {motor=0;}//电机不运行}//按键检测所需的中断count2_T0++; //更新中断次数if(count2_T0>20){count2_T0 = 0;PushKey_Loop();}
}

LCD1602.hLCD1602.c与第12节的实验代码相同。PushKey.hTimer0.h与13.2“温度报警器”的代码相同。

编程感想:

  1. 只要直流电机连着,就没法下载程序。必须要拔掉直流电机下载好之后,断电插上直流电机,插电。推测是因为USB所需电流激增,导致电脑主板进行端口保护,就不再进行串口通信??
  2. 直流电机和LCD显示屏冲突:USB电源的电流一般不超过1000MA(一般限流在750mA),当电流大时,电压下降得厉害,不能启动LCD1602。 所以可以使用其他驱动电流小的元件(如数码管),来显示当前的速度等级。
  3. 关于直流电机:注意电机引脚拉高时启动,因为达林顿晶体管阵列是非门。另外当PWM占空比过低时,也会导致直流电机平均启动电压过小而不转。
  4. 下面是使用LED来指示转速的代码:
//LCD更新显示转速等级
switch(speed_index){case 0:P2 = 0xff;break;case 1:P2 = 0xfc;break;case 2:P2 = 0xf0;break;case 3:P2 = 0xc0;break;case 4:P2 = 0x00;break;default:;
}

http://www.ppmy.cn/news/20672.html

相关文章

1753A1 - Make Nonzero Sum (easy version)

题目链接 1753A1 - Make Nonzero Sum (easy version) Rating:1300 题目描述 This is the easy version of the problem. The difference is that in this version the array can not contain zeros. You can make hacks only if both versions of the problem are solved. Yo…

关于栈和队列

目录栈&#xff08;Stack&#xff09;什么是栈栈的使用栈的模拟实现队列&#xff08;Queue&#xff09;什么是队列队列的使用队列的模拟实现循环队列双端队列 (Deque)栈&#xff08;Stack&#xff09; 什么是栈 栈是一种特殊的线性表&#xff0c;它只允许在固定的一端进行插入…

Java SSM (springboot+mybatis)美食菜谱分享平台系统设计和实现以及论文报告

Java SSM (springbootmybatis)美食菜谱分享平台系统设计和实现以及论文报告 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收…

什么蓝牙耳机便宜音质好?平价高音质蓝牙耳机推荐

随着蓝牙耳机的品类越来越多&#xff0c;人们在选择时有了更大的空间。作为蓝牙耳机选择的两大参考要素&#xff0c;性价比和音质的出现频率相对来说会比较高。那么&#xff0c;什么蓝牙耳机便宜音质好&#xff1f;下面&#xff0c;我来给大家推荐几款平价高音质的蓝牙耳机&…

19 | 三方协议怎么签?

前言 前言&#xff1a;简介三方协议签约的相关内容。 文章目录前言一. 什么是就业协议书二. 签约流程1. 网签流程&#xff08;线上签约&#xff09;三. 参考链接一. 什么是就业协议书 就业协议书俗称三方协议&#xff0c;是《全国普通高等学校毕业生就业协议书》的简称。 它是…

新来测试用一手Postman实现UI自动化测试拿下了大厂面试官

看到这篇文章的标题&#xff0c;是不是有小伙伴会感到惊讶呢&#xff1f; Postman不是做接口测试的吗&#xff1f;为什么还能做UI自动化测试呢&#xff1f; 其实&#xff0c;只要你了解Selenium的运行原理&#xff0c;就可以理解为什么Postman也能实现UI自动化测试了。 Sele…

JavaScriptArray和String对象~

初识Array&#xff1a; 定义&#xff1a; 方式1 var 变量名new Array(元素列表);举例&#xff1a; <script>var arraynew Array(1,2,3);alert(array); </script>显示如下&#xff1a; 方式2 var 变量名[元素列表];举例&#xff1a; <script>var array[…

51单片机学习笔记-3模块化编程

3 模块化编程 [toc] 注&#xff1a;笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。 注&#xff1a;工程及代码文件放在了本人的Github仓库。 3.1 模块化编程 传统方式编程&#xff1a;所有的函数均放在main.c里&#xff0c…