单片机学习笔记---LED呼吸灯&直流电机调速

目录

LED呼吸灯

直流电机调速

模型结构

波形

定时器初始化函数

中断函数

主程序


上一节讲了电机的工作原理,这一节开始代码演示!

我们上一篇说Ton的时间长Toff时间短电机会快,Ton的时间短Toff时间长电机会慢

并且我们还要保证无论Ton和Toff哪个时间比较长,Ts都得是固定值,因为为了保证周期一定。

下面我们先做一个“呼吸灯”感受一下上一篇博客中提到的PWM的意义:

LED呼吸灯

新创建本节第一个工程:LED呼吸灯

开始代码讲解:

首先根据LED的原理图定义一下引脚,P20(LED)为0时,灯亮。

#include <REGX52.H>

sbit LED=P2^0;//D1号LED的所接的单片机引脚

如果LED亮的时长比LED灭的时长要久,那么灯看上去就比较亮,反之就比较暗。这和前面说的Ton的时间长Toff时间短电机会快,Ton的时间短Toff时间长电机会慢是类似的。并且我们要保证LED亮灭的时间是一定的,即亮灭周期一定。

void Delay(unsigned int t)//传过来一个时间
{
	while(t--);//传过来一个时间,每一次while循环都减1
}

void main()
{
	unsigned char Time,i;
	while(1)
	{
		for(Time=0;Time<100;Time++)		//改变亮灭时间,由暗到亮
		{
			//比如TIME=1时,100-Time=99,然后进去循环20次再出来
			//这时TIME=2,100-Time=98......如此循环
			for(i=0;i<20;i++)			//计次延时
			{
				//TIME+(100-TIME)等于固定值是为了保持周期是一样的
				LED=0;					//LED亮
				Delay(Time);			//延时Time
				LED=1;					//LED灭
				Delay(100-Time);		//延时100-Time
			}
		}
		for(Time=100;Time>0;Time--)		//改变亮灭时间,由亮到暗
		{
			for(i=0;i<20;i++)			//计次延时
			{
				LED=0;					//LED亮
				Delay(Time);			//延时Time
				LED=1;					//LED灭
				Delay(100-Time);		//延时100-Time
			}
		}
	}
}

效果请看视频:

LED呼吸灯

呼吸灯就做成了,但是这种方式的缺点是显而易见的。它需要占用主循环不断地来翻转IO口来延时,在这一段时间内,也就是呼吸灯的整个过程中,主循环是没办法做其他事情的。

我们通常将PWM写到定时器里面,而且现在稍微高级一点的单片机,像STC的12系列或15系列及最新的系列都会有硬件的PWM,或者STM32单片机也会有硬件的PWM。因为不断地翻转IO口是一种比较简单但是比较占用CPU的一种操作,所以通常我们会用硬件来实现。而且硬件实现通常会寄生到定时器里面去,就是定时器既可以定时还可以兼具PWM的任务。但是我们STC89C52是没有这种功能的。所以我们就用定时器中断来实现这个功能。

直流电机调速

接下来我们开始演示第二个代码,并且是用定时器的这种方式来实现PWM。

写这个程序之前,我们先来看看产生PWM的方法。

模型结构

图中的比较值在硬件PWM里面是一个寄存器,我们可以从这个寄存器写一个固定值,那这个比较值就决定了我们的占空比(占空比 = TON / TS)。在我们的程序中可以定义一个变量,把它当做一个比较值,如果占空比不变的话,这个比较值通常也是固定的。

最终我们如何翻转IO口呢?我们就通过一个比较大小(在硬件是硬件比较器,在软件是 if 判断),将计数器的值和比较值进行比较。如果这个计数器的值小于比较值,就会输出0;如果计数器的值大于等于比较值,则输出1。当然,到底是大于输出0还是小于输出0呢,这就涉及到PWM的输出极性,在程序中是可以调节的,在硬件中也有这样相应的配置。

这个模型结构和单片机里面硬件的定时器以及PWM的结构是相似的,如果理解了这个结构,以后再学那些定时器PWM就会比较简单。

我们即将会写程序来模拟这个结构,来看看它是如果产生PWM的。

我们有了这个结构之后,如果知道它怎么工作的呢?主要是看这个波形

波形

PS:蓝色的波形对应的是模型结构图中的计数器那部分,它会定时自增,假设它是从0自增到100再回到0,它的波形就是这样的:

这个比较值是设置值,比如说我们想设置为60(即图中的红线所示),它在时间上就是固定肯定为60的。它会和计数器的值有一个交点。如果我们再把这两个值比较大小的话,那它的输出波形,就会呈现下面这个效果:

 比如第一个交点前,计数器的值小于比较值,则输出0,在PWM传输的波形图上就是0。然后第一个交点过后,计数器的值大于比较值,则输出1,在PWM传输的波形图上就是1。

如果将比较值设置为10,则PWM输出的波形也发生相应的变化,占空比会变得高一些。

因此我们通过控制这个比较值就可以控制占空比。 

比较值越大,占空比越小的;比较值越小,占空比越大。我们就利用这一点来控制电机的速度。

下面开始代码讲解:

新创建一个工程:直流电机调速

把这几个程序文件添加进来(下面每一个程序在之前的博客中都讲过了,如果不懂的可以翻之前的博客来看看)

然后新创建主程序main.c

根据原理图定义引脚,如果p10(Motor)=1,则电机旋转

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

sbit Motor=P1^0;

定义四个变量

unsigned char Counter,Compare;	//计数值和比较值,用于输出PWM
unsigned char KeyNum,Speed;//键码和速度

定时器初始化函数

然后初始化定时器,但是我们之前写的定时器初始化函数是1ms中断一次太慢了,我们重新生成一个100微秒中断一次的函数。

将生成的这个重装载值复制下来替换掉我们原先Timer0.c中的重装载值。

void Timer0_Init(void)
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;
	EA=1;
	PT0=0;
}

中断函数

相应的,我们写好的中断函数里的重装载值也要改。(中断函数在之前的博客中也讲过了)

PS:这个PWM驱动电机在一定范围内是越快越好,越快越稳定,但是过快的话也没必要,这会占用资源,并且会增加开关损耗。我们通常设置在10K到20KHz的频率。如果频率比较低的话电机会抖动。如果频率在1K附近的话,电机可能会产生鸣叫。

根据模型结构图中的计数器那部分,设置它会定时自增,假设它是从0自增到100再回到0

所以将Counter设置为Counter%=100;

如果Counter=99,那99对100取余是99,
如果Counter=100,那99对100取余是0,
所以Counter%=100和If(Counter>100)Counter=0是一个效果

然后我们将计数器的值和比较值进行比较。

void Timer0_Routine() interrupt 1 //每100微秒进来一次
{
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter%=100;	//计数值变化范围限制在0~99
	//如果Counter等于100,Counter自动清零
	
	if(Counter<Compare)	//计数值小于比较值
	{
		Motor=1;		//输出1,电机旋转
	}
	else				//计数值大于比较值
	{
		Motor=0;		//输出0,电机停止
	}
}

注意:我们这里设置的极性和模型结构图上的例子是不一样的,根据原理图Motor(p10)为高电平1时,电机转动,所以我们这里设置成:当计数值小于比较值时输出1,电机旋转,反之则输出0,电机停止。所以如果比较值越大,则输出1的之间就越大,电机速度越快。

主程序

那我们要设置占空比的话只需要设置比较值Compare

void main()
{
	Timer0_Init();//定时器初始化
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)//如果K1按下
		{
			Speed++;
			Speed%=4;//如果speed等于4,speed自动清零
			//设置速度的档次为0,1,2,3
			//比较值compare越大,速度越大
			if(Speed==0){Compare=0;}	//设置比较值,改变PWM占空比
			if(Speed==1){Compare=50;}
			if(Speed==2){Compare=75;}
			if(Speed==3){Compare=100;}
		}
		Nixie(1,Speed);//在第一个数码管上显示速度档次
	}
}

刚上电的时候电机会转一下是因为单片机默认上电时IO口都是高电平。

效果请看视频:

直流电机调速

以上就是本篇的内容,源码会放在评论区,如有问题可评论区留言!

​​​​​​​

  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Vera工程师养成记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值