【51单片机】直流电机的驱动和PWM调速

2023-05-16

51单片机驱动直流电机与 PWM 调速是通过使用 51 单片机来控制直流电机的转速和方向。51 单片机通过控制电机的电流来实现驱动,并通过生成 PWM 信号来调节电机的转速。使用 PWM 调速可以使得直流电机的转速精确可控,并且减少了电机的功率损耗。在 51 单片机的控制系统中,这两种技术都是常见的应用。

一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转。除直流电机外,常见的电机还有步进电机、舵机、无刷电机、空心杯电机等。

一、硬件电路

电机属于大功率负载,如果直接接在i/o口,会损坏单片机硬件。因此需要在单片机和电机之间加入驱动电路,常见的是直接驱动和h桥驱动。

直接驱动

H桥驱动

这里我们使用单片机开发板自带的资源ULN2002D进行驱动。

ULN2003D 是一种高电流可溶性继电器驱动芯片,它通常用于驱动直流电机。ULN2003D 的主要作用是将较低电压的控制信号转换为较高电压的驱动信号,从而可以通过驱动直流电机。ULN2003D 具有高电流输出能力,使用它可以减少控制系统的电路复杂度和功率损耗,并且可以额外提供驱动电流。ULN2003D 在驱动直流电机时主要用于将低电压的控制信号转换为高电压的驱动信号,从而提高驱动能力,减少电路复杂度和功率损耗。

他的内部结构与直接驱动的电路基本相同。内置达林顿管和续流二极管,工作电压高,工作电流大,灌电流可达500mA,并且能够在关态时承受50V 的电压,输出还可以在高负载电流并行运行。

这里我们使用P1.0控制OUT1来间接控制电机。

二、PWM调速

PWM 调速是一种用来控制直流电机转速的方法。它的原理是通过不断地开关直流电源来调节电机的转速。

PWM 调速的具体实现方法是通过生成一个频率固定的、占空比可变的 PWM 信号来控制直流电机的转速。占空比是指 PWM 信号在一个周期内的工作时间与总时间的比值。如果占空比越高,电机的转速就越快;如果占空比越低,电机的转速就越慢。PWM 调速的优点在于可以精确控制电机的转速,并且还可以减少电机的功率损耗。

重要参数:

频率 = 1 / TS 占空比= TON / TS 精度= 占空比变化步距

这里我们使用单片机内部的资源,定时器进行pwm控制。

首先配置定时器,使用51单片机小工具快速生成定时器初始化函数。

void Timer0Init(void)        //10毫秒@11.0592MHz
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0xA4;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0=1;        //中断初始化【程序生成的函数内没有这个】
    EA=1;                    //中断初始化
    PT0=0;                //中断初始化
}

在主函数中添加定时器的中断函数。我们提前定义一个比较值Compare用来与计数值比较,这个值会响应按键的动作进行加减,从而实现按键控制速度。

计数器内设置count定时自增,当count<compare时将P1.0口(Motor)置1,反之置0使其停止运行。当这一过程执行的速度很快,就会产生pwm方波。

void Timer0Routine() interrupt 1        //中断
{
    TL0 = 0xA4;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    Count++;                                        //每100us打断一次,计数器加1
    if(Count<Compare)                            
    {
        Motor=1;
    }
    else
    {
        Motor=0;
    }
    Count%=100;
}

三、按键选择

这里我们使用单片机开发板上的独立按键模块。原理图如下。

我们需要设定程序,对独立按键的四个i/o口进行扫描,实时读取按键信息,将按下的按键值传回函数。

unsigned char Key()
{
    unsigned char KeyNumber=0;
    if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
    if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
    if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
    if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
    return KeyNumber;
}

在主函数中我们要将传回的按键值与他对应的转速进行绑定。为了方便,我们只使用按键1对电机转速进行控制。

        KeyNum=Key();
        if(KeyNum==1)
        {
            Speed++;
            Speed%=5;        //当speed超过4将其值0,从而实现转速选择的循环
            if(Speed==0){Compare=0;}
            if(Speed==1){Compare=50;}
            if(Speed==2){Compare=70;}
            if(Speed==3){Compare=90;}
            if(Speed==4){Compare=100;}
        }

为了方便查看当前转速等级,我们引入数码管来显示转速等级。

数码管驱动文件如下。

#include <REGX52.H>
#include "Delay.h"

unsigned char smgText[]={0x3F,0x06,0x5B,0x4f,0x66,0x6D,0x7D,0x07,0x7F,0x6F};      

void smg(unsigned char location,number)
{
    switch(location)                                                              //location显示的数字
        {
            case 1:P2_4=1;P2_3=1;P2_2=1;break;
            case 2:P2_4=1;P2_3=1;P2_2=0;break;
            case 3:P2_4=1;P2_3=0;P2_2=1;break;
            case 4:P2_4=1;P2_3=0;P2_2=0;break;
            case 5:P2_4=0;P2_3=1;P2_2=1;break;
            case 6:P2_4=0;P2_3=1;P2_2=0;break;
            case 7:P2_4=0;P2_3=0;P2_2=1;break;
            case 8:P2_4=0;P2_3=0;P2_2=0;break;
        }
        P0=smgText[number];        //number显示的数字
        Delay(1);
        P0=0x00;
    }

在主函数中我们只需要输入smg(1,Speed);即可将速度数字显示在数码管第一位。

四、程序总览

本次项目为了使程序调理情绪便于理解,我使用了模块化编程。将按键程序、延迟程序、数码管程序、定时器程序分别进行封装。

主函数完整内容如下:

#include <REGX52.H>
#include "Key.h"
#include "Delay.h"
#include "smg.h"
#include "Timer0.h"

sbit Motor=P1^0;
unsigned char KeyNum,Speed;
unsigned char Compare,Count;

void main()
{
    Motor=0;
    Timer0Init();
    
    for(;;)
    {
        KeyNum=Key();
        if(KeyNum==1)
        {
            Speed++;
            Speed%=5;
            if(Speed==0){Compare=0;}
            if(Speed==1){Compare=50;}
            if(Speed==2){Compare=70;}
            if(Speed==3){Compare=90;}
            if(Speed==4){Compare=100;}
        }
        smg(1,Speed);
    }
}


void Timer0Routine() interrupt 1        //中断
{
    TL0 = 0xA4;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    Count++;                                        //每100us打断一次,计数器加1
    if(Count<Compare)                           
    {
        Motor=1;
    }
    else
    {
        Motor=0;
    }
    Count%=100;
}

独立按键程序如下:

#include <REGX52.H>
#include "Delay.h"


unsigned char Key()
{
    unsigned char KeyNumber=0;
    if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
    if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
    if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
    if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
    return KeyNumber;
}

延迟函数如下:

#include <intrins.h>

void Delay(unsigned int n)

{
    unsigned int i,j;
    for(j=n;j>0;j--)
    for(i=112;i>0;i--);
}

数码管程序如下:

#include <REGX52.H>
#include "Delay.h"

unsigned char smgText[]={0x3F,0x06,0x5B,0x4f,0x66,0x6D,0x7D,0x07,0x7F,0x6F};      

void smg(unsigned char location,number)
{
    switch(location)                                                              //location显示的数字
        {
            case 1:P2_4=1;P2_3=1;P2_2=1;break;
            case 2:P2_4=1;P2_3=1;P2_2=0;break;
            case 3:P2_4=1;P2_3=0;P2_2=1;break;
            case 4:P2_4=1;P2_3=0;P2_2=0;break;
            case 5:P2_4=0;P2_3=1;P2_2=1;break;
            case 6:P2_4=0;P2_3=1;P2_2=0;break;
            case 7:P2_4=0;P2_3=0;P2_2=1;break;
            case 8:P2_4=0;P2_3=0;P2_2=0;break;
        }
        P0=smgText[number];        //number显示的数字
        Delay(1);
        P0=0x00;
    }

定时器程序如下:

#include <REGX52.H>
void Timer0Init(void)        //10毫秒@11.0592MHz
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0xA4;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0=1;        //中断初始化【程序生成的函数内没有这个】
    EA=1;                    //中断初始化
    PT0=0;                //中断初始化
}


//主函数中断示例
//void Timer0Routine() interrupt 1        //中断
//{
//    TL0 = 0x00;                                                //设置定时初值,让定时器重新开始计时            
//    TH0 = 0xDC;                                                //设置定时初值【注意:这里的定时初值要与函数Timer0Init内的初值一样】
//    Timer0Count++;                                        //每10ms打断一次,计数器加1
//    if(Timer0Count>=100)                            //当计数器到100,即经过1秒后让秒加一,然后时分做出响应变化
//    {
//                
//    
//    }

每个程序文件单独存放在c文件中,并存在与其同名的h头文件将函数定义在其中。

以定时器函数为例,他的头函数将这样定义!!

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0Init(void);

#endif

本文为学习笔记,欢迎大家在评论区友善讨论,指出我的不足!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【51单片机】直流电机的驱动和PWM调速 的相关文章

  • MBR+BIOS与GPT+UEFI启动系统的区别

    MBR 43 BIOS与GPT 43 UEFI启动系统的区别 近些年来许多电脑厂商的出厂电脑都自带系统 xff0c 这些电脑的分区看起来和我们一般的组装机电脑的分区有些不同 xff0c 它除了有一个系统主分区之外在主分区之前还有3个小分区
  • 如何装GPT+UEFI / MBR+BIOS的系统

    本文将深度讲述装机步骤与原理 xff0c 解决装机过程中遇到的各种问题 xff0c 使用不同的方式装机 本文所有的装机方式笔者都亲自尝试过 xff0c 所有重装步骤不会损毁除系统盘外其他分区文件 这是笔者总结许久的装机经验 xff0c 本文
  • 综合项目之闪讯破解(六)之 如何解决程序/C++Dll的兼容性问题

    如何解决程序 C 43 43 Dll的兼容性问题 本文将尝试解决程序与DLL在不同客户机上运行存在的兼容性问题 前言 前面的五篇文章已经将程序的核心部分全部搞定 xff0c 由于我们调用了一些系统API xff0c 所以这很有可能导致程序在
  • Ubuntu 修改 apt 源为阿里云源

    文章目录 软件源 Software Source使用说明图形界面 xff08 新手推荐 xff09 手动修改配置文件 相关链接 软件源 Software Source 软件源是指用于存储各种 Linux 应用程序的存储库 xff0c 包括自
  • C#如何自绘滚动条控件

    C 如何自绘滚动条控件 滚动条样式 普通情况 鼠标位于滑块上面 鼠标按下滑块 程序变量与函数层级图 垂直滚动条代码 不讲如何编写了 代码上面有注释 直接上代码片了 span class hljs comment 自定义控件 xff1a 垂直
  • TeeChart WPF DLL消除水印

    TeeChart WPF DLL消除水印 准备工作 Steema TeeChart for NET 2017 Evaluation 4 1 2017 03147 DNSPY X86 一些代码 xff1a Texts ExpireMsg1 W
  • polybar基础使用

    如果不喜欢i3或者其他桌面系统的默认状态栏 xff0c polybar还是一个不错的选择 基本上 xff0c 所有的流行的Linux发行版都可以用包管理器直接进行polybar的安装 ArchLinux可以使用yay或者其他AUR工具安装
  • ArchLinux图形界面安装与美化:i3+polybar

    arch只提供了tty xff0c 我们需要自己配置一个漂亮的桌面 你可以选择继承好的GNOME Deepin等桌面 但是他们都包含了许多你可能并不能用到的工具和插件 i3wm是一个窗口管理器 xff0c 它提供了最基础的窗口管理功能 你可
  • ceph学习(1)——手动部署ceph分布式存储集群(使用本地源离线安装),一次成功!!

    手动搭建适合已经使用自动部署工具成功搭建了集群 xff0c 想加深对ceph理解的同学 xff0c 手动搭建ceph可以更灵活的配置ceph集群 xff0c 现在就开始吧 xff01 xff01 一 环境准备 1 服务器配置 xff1a 三
  • iOS开发 - touchBegan事件判断点击的位置在View上还是在View的子View上

    span class hljs pp span class hljs params style color rgb 102 0 102 void span touchesBegan span class hljs params style
  • SQL Server解析Json格式数据

    主要介绍5个函数 xff1a openJson 打开Json字符串IsJson 判断一个字符串是不是合法的Json格式 是返回1 xff0c 否返回0 xff0c null返回null Json Value 从Json字符串中提取值 Jso
  • openwrt 无线桥接(AP)

    无线桥接常见的有三种模式 1 AP模式 AP模式其实是Access Point的简称 xff0c 意思是 xff1a 访问接入点 而无线网桥的AP模式 xff0c 也就是利用无线网桥做无线信号的接入点了 那么 xff0c 究竟是什么东西接入
  • macOS下使用anaconda相关系列

    创建虚拟环境 conda create n 环境名 python 61 3 6 进入虚拟环境 source bash profile source activate 环境名 其中bash profile是安装anaconda时候默认生成的环
  • Windows 安装NET4.6/4.7/4.8 时间戳签名和或证书无法验证或已损坏

    时间戳签名和或证书无法验证或已损坏 问题版本 xff1a 事件 xff1a 解决办法下载补丁程序 xff1a 安装KB2813430补丁 注意事项补丁需要重启设备生效 2021 10 11 by 崔斐然 问题 版本 xff1a win7专业
  • 在 Ubuntu Linux 中使用 PPA(完全指南)

    译 xff1a 在 Ubuntu Linux 中使用 PPA xff08 完全指南 xff09 作者 xff1a Abhishek Prakash 自由和开放源码软件的创造者 一个热心的 Linux 用户和开源推动者 从阿加莎 克里斯蒂和夏
  • RDP(远程桌面)优化

    RDP连接优化 一 优化连接时间二 优化集显帧率三 开启RemoteFX USB重定向 xff08 如果有需要 xff09 四 MacOS系统RDP超高清显示 2022 03 31 by 崔斐然 一 优化连接时间 1 客户端 xff1a 关
  • 【FRP】windowsServer部署FRP

    FRP windowsServer部署FRP 1 下载FRP nssm2 服务器端部署过程 xff1a 3 客户端部署过程 xff1a 4 卸载服务 2022 08 24 by 崔斐然 1 下载FRP nssm 下载地址 xff1a FRP
  • 【FRP】群晖docker中部署Frp

    2022 08 24 by 崔斐然 0 xff1a 需求 公司有台笔记本 xff0c 现在疫情期间居家办公 我用的MacBook RDP客户端做的非常好用 xff0c 如相互粘贴文件 文字等 xff0c MacBook通过远程桌面连接公司内
  • Debian 9/10快速开启Google BBR的方法,实现TCP高效单边加速

    BBR 是谷歌公司的某个员工研发出来的服务器单边加速算法 xff0c Linux内核从4 9版开始集成BBR算法 相比锐速BBR的加速效果更为温和 xff0c 并且占用内存小对服务器压力也很小 xff0c 当时理想情况下是可以跑满整个服务器
  • 基于机器学习的捡球机器人设计与实现(探索)第4篇——机械设计)

    2019 03 18 by 崔斐然 原以为软件很复杂 机械好搞 结果发现 都难搞 一次次想出办法又一次次被自己否定 我tm想静静

随机推荐

  • 人脸识别之Hog特征+SVM分类器训练与使用

    原文来自 xff1a https juejin im post 5b0e70686fb9a00a1451c8e7 计算机视觉 人脸识别 xff08 Hog特征 43 SVM分类器 xff09 一 SVM支持向量机 1 SVM原理 在机器学习
  • python利用PIL实现对图片截图

    在对图像处理时 xff0c 我们有时候需要对图片某区域进行截图 xff0c 话不多说 xff0c 直接上代码 xff1a from PIL import Image import sys 先将 input image 填充为正方形 def
  • PowerMock介绍和用法

    PowerMock PowerMock简介一 PowerMock xff1f 二 Mock底层原理1 Mockito2 PowerMock原理 三 应用场景1 依赖问题 xff0c 打桩 2 工程质量 PowerMock使用步骤一 添加依赖
  • Windows10 WSL2磁盘迁移

    一 使用 WSL 命令行工具 在 Windows 10 版本 1903 xff08 2019 年 4 月更新 xff09 或更高版本中 xff0c 您可以使用wsl exe命令行工具 1 导出分布 使用要移动的分发创建一个 tar文件wsl
  • linux下搭建confluence

    一 Java环境 java环境 二 mysql 2 1 安装前的检查和准备工作 2 1 1检查 1 是否安装过mysql xff1a rpm qa grep mysql 2 如果有的话 xff0c 就删除 xff08 XXXX是自己的mys
  • 译:SOME/IP 技术细节

    译 xff1a SOME IP 技术细节 原文 SOME IP technical details SOME IP Scalable service Oriented MiddlewarE over IP 基于 IP 可扩展面向服务中间件
  • Python requests_toolbelt的使用

    multipart form data Encoder The main attraction is a streaming multipart form data object MultipartEncoder Its API looks
  • ArchLinux中文安装教程

    以自己的电脑安装为参考 xff0c 已安装win10系统 最后效果为win10和arch双系统 xff01 xff01 xff01 一 准备工作 1 按照实际需要划分出一部分空闲磁盘空间 xff0c 右击想要安装arch的分区点击删除卷 x
  • C++20 范围库:关键优势——算法的组合

    从概念上讲 xff0c 范围 xff08 Range xff09 是一个简单的概念 xff1a 它只是一对迭代器 指向序列的开始和结束 xff08 在某些情况下是一个哨兵 xff09 然而 xff0c 这样的抽象却可以从根本上改变编写算法的
  • Drupal菜鸟笔记之使用Focal Point 模块实现图片压缩与裁剪

    在项目开发中总是有地方需要上传图片 xff0c 因此也常常需要对图片进行压缩与裁剪来达到我们想要的效果 最近项目中刚好要用到 xff0c 我就去搜索了 解了下图片的压缩与裁剪模块 xff0c 最后选择了 Focal Point Focal
  • Linux系统学习——ubuntu16.04开机蓝屏问题

    1 蓝屏原因 由于频繁地强制关机等原因造成 xserver xorg包出现损坏 xff0c 故在开机时屏幕显示出现问题 1 1 顺便提一下 xorg xorg 我们知道 xff0c Linux内核本身是没有图形化界面的 xff0c 其本身是
  • 最小生成树 Kruskal算法 Prim算法 洛谷P3366

    最小生成树 Kruskal算法 Prim算法 洛谷P3366 相较于Prim算法 xff0c 我觉得Kruskal算法更优 xff08 因为一般情况 xff0c 题目给你的边数都是正常的 xff0c Kruskal算法的时间复杂度为O El
  • 13. 罗马数字转整数

    题目 罗马数字包含以下七种字符 xff1a I xff0c V xff0c X xff0c L xff
  • 【转载】重新安装Anaconda卡在Loading applications无法进入

    我出现这个问题的原因是 xff1a 之前安装Anaconda没在系统添加路径 xff0c 虽然可以正常使用Pycharm xff0c 但Visual Studio Code 不能调用python 因此在胡老师帮助下 xff0c 决定卸载原来
  • C++语法(三)string字符串的输入、拼接、删除、查找、截取、比较、遍历

    1 字符串的输入 1 输入不含空格的字符串 string str cin gt gt str 2 输入包含空格的字符串 string str 如果前面有了cin输入 xff0c 则还需添加如下一句 getchar getline cin s
  • Python的坑(4) -- 【if x:】的含义

    原文链接 xff1a http www liaoxuefeng com wiki 0014316089557264a6b348958f449949df42a6d3a2e542c000 001431675624710bb20e9734ef34
  • 交叉编译 acl

    交叉编译 acl 概述 访问控制列表 xff08 Access Control Lists xff0c ACL xff09 是应用在路由器接口的指令列表 在 Linux 系统中 xff0c ACL 用于设定用户针对文件的权限 xff0c 而
  • 使用xrdp实现windows 远程桌面连接linux

    之前一直用mstsc连接windows主机 xff0c 今天想用此来连接linux主机时 xff0c 发现 连接不了 xff01 xff01 与度娘亲热好久之后 xff0c 分享一篇博客给大家 xff1a 传送门 一般情况下我们用ssh客户
  • 【51单片机】定时器的简单应用——计时器

    一 定时器 stc89c52 具有三个定时器 xff08 T0 T1 T2 xff09 xff08 1 xff09 T0 T1均有四种模式 最常用模式1 xff08 2 xff09 定时器模式1工作框图 SYSclk xff08 系统时钟
  • 【51单片机】直流电机的驱动和PWM调速

    51单片机驱动直流电机与 PWM 调速是通过使用 51 单片机来控制直流电机的转速和方向 51 单片机通过控制电机的电流来实现驱动 xff0c 并通过生成 PWM 信号来调节电机的转速 使用 PWM 调速可以使得直流电机的转速精确可控 xf