江科大51单片机笔记【15】直流电机驱动(PWM)

news2025/4/21 4:28:06

写在前言

  此为博主自学江科大51单片机(B站)的笔记,方便后续重温知识

  在后面的章节中,为了防止篇幅过长和易于查找,我把一个小节分成两部分来发,上章节主要是关于本节课的硬件介绍、电路图、原理图等理论知识,主要是为下章节的代码部分打基础。

  我的单片机是24年12月在tb普中买的,型号是STC89C52,在原视频中引脚或接口不对应的我都会改正,保证在我的机子上能运行才发上来的,还有一些文字部分是我的理解,并非照搬,所以可能有理解不到位的现象。

  如有误或交流,敬请指点提问

本节课一共两个代码,LED呼吸灯和直流电机调速

一、直流电机

1.介绍

  • 直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转
  • 直流电机主要由永磁体(定子)、线圈(转子)和换向器组成
  • 除直流电机外,常见的电机还有步进电机(机壳装载了一圈电磁铁,对相对两个电磁铁进行一圈脉冲式通电,优点是严格控速精密)、舵机(跟船舵一样,方便控制转向)、无刷电机(转速特别快)、空心杯电机(体积很小)等
  • 左1就是我们开发板里的电机,有两个电极;左1是N20,一个直流电机+减速箱;右1比左2还多带一个编码器(测速),PID算法(常用)控制电机速度

2.驱动电路

有两种方式

  • 大功率器件直接驱动 

不能正反转上面是一个三极管控制开关,下面是一个蓄流二极管,用于保护电路;因为电机(继电器)是感性负载元件,驱动的时候会出现很高的电压(电感的特效)

这个ULN2003里面也是一个大功率元件

  • H桥驱动

能正反转因为我们使第二、四象限的二极管导通其余的截止,就会令电流向右走,如果反过来就可以令电流向左走;因为没有蓄流二极管保护,所以对mos管和晶体管的耐压特效要求比较高

二、PWM

PWM是控制直流电机调速的


1.介绍

  • PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域
  • PWM重要参数:
  • 频率=1/Ts  占空比=Ton/Ts  精度=占空比变化步距

三、代码实战

1.LED呼吸灯 

先定义一下引脚

然后再定义一个比较快的延时函数,让这个LED灯先亮一段时间,再灭一段时间,这就是PWM的工作原理,通常为了保证周期是稳定的,不随占空比变化而变化,所以亮和灭加起来的时间也要是个固定值

#include <REGX52.H>

sbit LED=P2^0;

void Delay(unsigned int t)
{
	while(t--);
}

void main()
{
	
	while(1)
	{
 		LED=0;
		Delay(5);
		LED=1;
		Delay(95);
	}
}

接下来就是让亮和灭的值不断变化,从而实现呼吸灯的效果

我们就可以定义一个变量Time,让亮的时间为Time,灭的时间为100-Time,这样就可以实现两个数加起来是固定值,然后我们再对Time进行for循环,不断++

但是这个速度还是比较快,我们让他每次亮灭变换的时间再久一点,定义一个i,在for循环里嵌套再进行一次for循环,这样就可以实现LED一直从暗到亮

但是我们还想实现从暗到亮,再从亮到暗又怎么做呢,就是把之前的外层对Time的for循环反过来再依次--

#include <REGX52.H>

sbit LED=P2^0;

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++)
			{
				LED=0;
				Delay(Time);
				LED=1;
				Delay(100-Time);				
			}
		}
		for(Time=100;Time>0;Time--)
		{
			for(i=0;i<20;i++)
			{
				LED=0;
				Delay(Time);
				LED=1;
				Delay(100-Time);				
			}
		}
	}
}

这样就可以实现呼吸灯从暗到亮,再从亮到暗

但是会有一个缺点,就是占用了我们的主循环不断翻转IO口,还比较占用CPU

一般都会写到定时器上,或者从硬件上解决

所以在下面的代码中我们用定时器来实现

2.直流电机调速

在这个代码我们就用定时器来实现LED呼吸灯和直流电机调速功能

产生PWM方法

我们通过改变比较值就可以改变占空比 

由于之前的定时器设置有点慢,我们让他快一点

这个PWM驱动电机在一定范围内是越快越好,一般设置在10K-20K范围里,如果频率比较低,电流就会抖动,如果在1K左右,就会产生一些蜂鸣器的声音

这个中断就是每隔100us中断一次

//timer0.c

#include <REGX52.H>

/**
  * @brief  定时器0初始化,100us@12.000MHz
  * @param  无
  * @retval 无
  */
void Timer0_Init(void)
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;
	EA=1;
	PT0=0;
}

/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	T0Count++;
	if(T0Count>=1000)
	{
		T0Count=0;
		
	}
}
*/

由上面的图可以知道要定义两个值,计数值和比较值,

我们让计数值从0-100然后清零,实现定时自增

    Counter++;
    Counter%=100;

这样写和if(counter==100){清零}是一个效果

接下来再让计数值和比较值进行比较

可以观察到如果比较值越大,低电平时间越久,也就是越暗

这样我们通过控制比较值Compare就可以控制LED的亮度,还剩下下了主循环,接下来我们就实现按键功能

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

sbit LED=P2^0;

unsigned char Counter,Compare;

void main()
{
	Timer0_Init();
	Compare=5;
	while(1)
	{
 		
	
	}

}

void Timer0_Routine() interrupt 1
{
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter%=100;
	if(Counter<Compare)
	{
		LED=0;
	}
	else
	{
		LED=1;
	}
}

注意后面取的Key函数,如果是拿的定时器扫描按键的那章写的Key函数,要在定时器中写上这个Key_Loop()

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

sbit LED=P2^0;

unsigned char Counter,Compare;
unsigned char KeyNum,Speed;

void main()
{

	Timer0_Init();
	Compare=5;
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			Speed++;
			Speed%=4;
		}
		Nixie(1,Speed);
	}

}

void Timer0_Routine() interrupt 1
{
	Key_Loop();
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter%=100;
	if(Counter<Compare)
	{
		LED=0;
	}
	else
	{
		LED=1;
	}
}

这样就可以实现按下按键1数码管显示++并且过3就清零

接下来将Speed跟Compare比较值对应起来,就可以实现按键调速并显示

这样就可以实现LED的亮度控制

            if(Speed==0){Compare=5;}
            if(Speed==1){Compare=5;}
            if(Speed==2){Compare=50;}
            if(Speed==3){Compare=100;}    

那我们如果想控制电机,就直接把LED的端口改成电机的端口,而又因为我们的LED是给0亮给1灭,而电机是给1转给0灭,所以需要把极性反过来

这里有个小问题,在刚上电的时候,电机会转动,这是硬件的问题,因为单片机在复位的时候,IO口默认高电平,所以电机会转

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

sbit Motor=P1^0;

unsigned char Counter,Compare;
unsigned char KeyNum,Speed;

void main()
{

	Timer0_Init();
	Compare=5;
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			Speed++;
			Speed%=4;
			if(Speed==0){Compare=0;}
			if(Speed==1){Compare=50;}
			if(Speed==2){Compare=75;}
			if(Speed==3){Compare=100;}	
		}
		Nixie(1,Speed);
	}

}

void Timer0_Routine() interrupt 1
{
	Key_Loop();
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter%=100;
	if(Counter<Compare)
	{
		Motor=1;
	}
	else
	{
		Motor=0;
	}
}

这样就实现本节课的代码啦,按下按键调节电机的速度并且显示出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2314550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络协议详解】——QOS技术(学习笔记)

目录 QoS简介 QoS产生的背景 QoS服务模型 基于DiffServ模型的QoS组成 MQC简介 MQC三要素 MQC配置流程 优先级映射配置(DiffServ域模式) 优先级映射概述 优先级映射原理描述 优先级映射 PHB行为 流量监管、流量整形和接口限速简介 流量监管 流量整形 接口限速…

Spring学习笔记:工厂模式与反射机制实现解耦

1.什么是Spring? spring是一个开源轻量级的java开发应用框架&#xff0c;可以简化企业级应用开发 轻量级 1.轻量级(对于运行环境没有额外要求) 2.代码移植性高(不需要实现额外接口) JavaEE的解决方案 Spring更像是一种解决方案&#xff0c;对于控制层&#xff0c;它有Spring…

pytest数据库测试文章推荐

参考链接&#xff1a; 第一部分&#xff1a;http://alextechrants.blogspot.fi/2013/08/unit-testing-sqlalchemy-apps.html第二部分&#xff1a;http://alextechrants.blogspot.fi/2014/01/unit-testing-sqlalchemy-apps-part-2.html

vue3 二次封装uni-ui中的组件,并且组件中有 v-model 的解决方法

在使用uniappvue3开发中&#xff0c; 使用了uni-ui的组件&#xff0c;但是我们也需要自定义组件&#xff0c;比如我要自定一个picker 的组件&#xff0c; 是在 uni-data-picker 组件的基础上进行封装的 父组件中的代码 <classesselect :selectclass"selectclass"…

探索高性能AI识别和边缘计算 | NVIDIA Jetson Orin Nano 8GB 开发套件的全面测评

随着边缘计算和人工智能技术的迅速发展&#xff0c;性能强大的嵌入式AI开发板成为开发者和企业关注的焦点。NVIDIA近期推出的Jetson Orin Nano 8GB开发套件&#xff0c;凭借其40 TOPS算力、高效的Ampere架构GPU以及出色的边缘AI能力&#xff0c;引起了广泛关注。本文将从配置性…

【学习笔记】《逆向工程核心原理》03.abex‘crackme-2、函数的调用约定、视频讲座-Tut.ReverseMe1

文章目录 abexcrackme-21. Visual Basic文件的特征1.1. VB专用引擎1.2. 本地代码与伪代码1.3. 事件处理程序1.4. 未文档化的结构体 2. 开始调试2.1. 间接调用2.2. RT_MainStruct结构体2.3. ThunRTMain()函数 3. 分析crackme3.1. 检索字符串3.2. 查找字符串地址3.3. 生成Serial的…

React基础之项目实战

规范的项目结构 安装scss npm install sass -D 安装Ant Design组件库 内置了一些常用的组件 npm install antd --save 路由基础配置 npm i react-router-dom 路由基本入口 import Layout from "../page/Layout"; import Login from "../page/Login"; impor…

SAP-ABAP:SAP数据库视图的创建图文详解

在SAP ABAP中&#xff0c;数据库视图&#xff08;Database View&#xff09;是通过ABAP字典&#xff08;ABAP Dictionary&#xff09;创建的。数据库视图是基于一个或多个数据库表的虚拟表&#xff0c;它允许你定义一种逻辑视图来访问数据。以下是创建数据库视图的步骤&#xf…

基于深度学习的肺炎X光影像自动诊断系统实现,真实操作案例分享,值得学习!

医疗影像智能化的技术演进 医学影像分析正经历从人工判读到AI辅助诊断的革命性转变。传统放射科医师分析胸部X光片需要8-12年专业训练&#xff0c;而基于深度学习的智能系统可在秒级完成检测。本文将以肺炎X光检测为切入点&#xff0c;详解从数据预处理到模型部署的全流程实现。…

Unity Shader学习总结

1.帧缓冲区和颜色缓冲区区别 用于存储每帧每个像素颜色信息的缓冲区 帧缓冲区包括&#xff1a;颜色缓冲区 深度缓冲区 模板缓冲区 自定义缓冲区 2.ImageEffectShader是什么 后处理用的shader模版 3.computerShader 独立于渲染管线之外&#xff0c;在显卡上运行&#xff0c;大量…

算法精讲 | 树(番外):平衡世界的四大守护者:AVL vs 红黑树 vs B树 vs B+树

&#x1f332; 算法精讲 | 树&#xff08;番外&#xff09;&#xff1a;平衡世界的四大守护者&#xff1a;AVL vs 红黑树 vs B树 vs B树 &#x1f4c5; 2025/03/12 || &#x1f31f; 推荐阅读时间 30分钟 &#x1f680; 开篇&#xff1a;数据结构界的四大天王 想象你是一名图书…

第十八:go 并发 goroutine

channel 可以让多个goroutine 之间实现通信 Add方法调用时机&#xff1a;必须在goroutine 启动之前调用Add方法来增加计数器的值。 如果在goroutine已经启动之后再调用Add&#xff0c;可能会导致Wait方法提前返回&#xff0c;因为计数器没有正确反映正在运行的goroutine的数量…

在vs中无法用QtDesigner打开ui文件的解决方法

解决方法 右键ui文件&#xff0c;选择打开方式&#xff0c;弹出如下界面。 点击添加&#xff0c;弹出如下界面 点击程序后边的三个点&#xff0c;去电脑查找designer.exe,我的位置为D:\Qt\Qt5.9.9\5.9.9\msvc2015_64\bin\designer.exe。 名称可以自己起一个名字&#xff0c…

图像识别技术与应用-YOLO

1 YOLO-V1 YOLO-V1它是经典的one-stage方法&#xff0c;You Only Look Once&#xff0c;名字就已经说明了一切&#xff01;把检测问题转化成回归问题&#xff0c;一个CNN就搞定了&#xff01;也可以对视频进行实时检测&#xff0c;应用领域非常广&#xff01; YOLO-V1诞生与2…

LLM推理和优化(1):基本概念介绍

一、LLM推理的核心过程&#xff1a;自回归生成 LLM&#xff08;如DeepSeek、ChatGPT、LLaMA系列等&#xff09;的推理本质是自回归生成&#xff1a;从初始输入&#xff08;如[CLS]或用户prompt&#xff09;开始&#xff0c;逐token预测下一个词&#xff0c;直到生成结束符&…

Kubernetes教程(七)了解集群、标签、Pod和Deployment

了解集群、标签、Pod和Deployment 一、K8s资源对象二、K8s集群1. Master2. Node 三、Namespace&#xff08;命名空间&#xff09;四、Label&#xff08;标签&#xff09;五、Pod1. 共享网络命名空间2. 共享数据 六、工作负载1. 设置副本数2. 应用升级 结语 Kubernetes的知识真的…

【最新】DeepSeek 实用集成工具有那些?

deepseek 系列github仓库地址 【主页】deepseek-aiDeepSeek-R1DeepSeek-V3DeepSeek-VL2【本文重点介绍】awesome-deepseek-integration 注意&#xff1a;以下内容来自awesome-deepseek-integration DeepSeek 实用集成&#xff08;awesome-deepseek-integration&#xff09; 将…

Flutter_学习记录_video_player、chewie 播放视频

1. video_player 视频播放 插件地址&#xff1a;https://pub.dev/packages/video_player 添加插件 导入头文件 import package:video_player/video_player.dart;Android配置&#xff08;iOS不用配置&#xff09; 修改这个文件&#xff1a;/android/app/src/main/AndroidMani…

【MySQL】增删改查进阶

目录 一、数据库约束 约束类型 NULL约束&#xff1a;非空约束 UNIQUE&#xff1a;唯一约束 DEFAULT&#xff1a;默认值约束 PRIMARY KEY&#xff1a;主键约束 FOREIGN KEY&#xff1a;外键约束 二、表的设计 三、新增 四、查询 聚合查询 聚合函数 GROUP BY子句 HA…

静态时序分析:SDC约束命令set_ideal_latency详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 当使用set_ideal_network命令将当前设计中的一组端口或引脚标记为理想网络源后&#xff0c;理想属性会沿着组合逻辑进行传播&#xff0c;理想网络中的线网和单元…