搜盘 资源网,合肥seo推广公司,torrent种子搜索引擎,想做外贸做哪些网站好目录
LED呼吸灯
直流电机调速
模型结构
波形
定时器初始化函数
中断函数
主程序 上一节讲了电机的工作原理#xff0c;这一节开始代码演示#xff01; 我们上一篇说Ton的时间长Toff时间短电机会快#xff0c;Ton的时间短Toff时间长电机会慢 并且我们还要保证无论Ton和…目录
LED呼吸灯
直流电机调速
模型结构
波形
定时器初始化函数
中断函数
主程序 上一节讲了电机的工作原理这一节开始代码演示 我们上一篇说Ton的时间长Toff时间短电机会快Ton的时间短Toff时间长电机会慢 并且我们还要保证无论Ton和Toff哪个时间比较长Ts都得是固定值因为为了保证周期一定。
下面我们先做一个“呼吸灯”感受一下上一篇博客中提到的PWM的意义 LED呼吸灯
新创建本节第一个工程LED呼吸灯
开始代码讲解
首先根据LED的原理图定义一下引脚P20(LED)为0时灯亮。
#include REGX52.Hsbit LEDP2^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(Time0;Time100;Time) //改变亮灭时间由暗到亮{//比如TIME1时100-Time99,然后进去循环20次再出来//这时TIME2,100-Time98......如此循环for(i0;i20;i) //计次延时{//TIME(100-TIME)等于固定值是为了保持周期是一样的LED0; //LED亮Delay(Time); //延时TimeLED1; //LED灭Delay(100-Time); //延时100-Time}}for(Time100;Time0;Time--) //改变亮灭时间由亮到暗{for(i0;i20;i) //计次延时{LED0; //LED亮Delay(Time); //延时TimeLED1; //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
根据原理图定义引脚如果p10Motor1则电机旋转 #include REGX52.H
#include Delay.h
#include Key.h
#include Nixie.h
#include Timer0.hsbit MotorP1^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开始计时ET01;EA1;PT00;
}
中断函数
相应的我们写好的中断函数里的重装载值也要改。中断函数在之前的博客中也讲过了
PS这个PWM驱动电机在一定范围内是越快越好越快越稳定但是过快的话也没必要这会占用资源并且会增加开关损耗。我们通常设置在10K到20KHz的频率。如果频率比较低的话电机会抖动。如果频率在1K附近的话电机可能会产生鸣叫。
根据模型结构图中的计数器那部分设置它会定时自增假设它是从0自增到100再回到0
所以将Counter设置为Counter%100;
如果Counter99,那99对100取余是99 如果Counter100,那99对100取余是0 所以Counter%100和If(Counter100)Counter0是一个效果
然后我们将计数器的值和比较值进行比较。
void Timer0_Routine() interrupt 1 //每100微秒进来一次
{TL0 0x9C; //设置定时初值TH0 0xFF; //设置定时初值Counter;Counter%100; //计数值变化范围限制在0~99//如果Counter等于100Counter自动清零if(CounterCompare) //计数值小于比较值{Motor1; //输出1电机旋转}else //计数值大于比较值{Motor0; //输出0电机停止}
}
注意我们这里设置的极性和模型结构图上的例子是不一样的根据原理图Motor(p10)为高电平1时电机转动所以我们这里设置成当计数值小于比较值时输出1电机旋转反之则输出0电机停止。所以如果比较值越大则输出1的之间就越大电机速度越快。
主程序
那我们要设置占空比的话只需要设置比较值Compare
void main()
{Timer0_Init();//定时器初始化while(1){KeyNumKey();if(KeyNum1)//如果K1按下{Speed;Speed%4;//如果speed等于4speed自动清零//设置速度的档次为0,1,2,3//比较值compare越大速度越大if(Speed0){Compare0;} //设置比较值改变PWM占空比if(Speed1){Compare50;}if(Speed2){Compare75;}if(Speed3){Compare100;}}Nixie(1,Speed);//在第一个数码管上显示速度档次}
}
刚上电的时候电机会转一下是因为单片机默认上电时IO口都是高电平。
效果请看视频 直流电机调速 以上就是本篇的内容源码会放在评论区如有问题可评论区留言