PWM与时间片思想

改编自:http://www.moz8.com/thread-79049-1-1.html

 什么是PWM?

PWM:脉冲宽度调制,由于在数字电路(或者单片机)输出模拟信号的成本高昂,换句话说,受制于只能输出数字信号,无法正常输出模拟量,如果需要使用数字电路输出模拟量,那么便需要考虑等效的概念。举个例子,单片机只能输出高低电平(5V,0V),如何答案输出2.5V显然是不可能的,但是我们却可以利用等效的概念:

  假设在1秒钟内,前半秒是高电平(5V),后半秒是低电平(0V),那一秒内的平均电压是多少?平均电压就可以当成2.5V。

同理,适用于灯的亮度,电机的转速,甚至是蜂鸣器的响度。

 

如何产生PWM信号:

#include<reg51.h>

sbit LED_R=P3^4;//定义红灯
sbit LED_G=P3^3;//定义绿灯
sbit LED_B=P3^2;//定义蓝灯

sbit Key1=P3^0;//定义按键

unsigned char count;    //定义一个数据,记录循环次数

void Delay1ms()                //@12.000MHz
{
        unsigned char i, j;

        i = 12;
        j = 169;
        do
        {
                while (--j);
        } while (--i);
}

void delay_n_ms(unsigned int n) //自己定义的延时n毫秒函数
{
        while(n)         
        {
                Delay1ms();
                n=n-1;//每循环一次n减小1
        }    
}

main()
{
        while(1)    
        {
                count=count+1;   //每过1ms计数+1
                if(count>9)      //计数大于9重新开始计数,0~9十毫秒周期
                {
                        count=0;
                }

                if(2>count)      //在count 0~9变化中,2大于count的次数是2次。改变2就可以改变占空比
                {
                        LED_R=1;
                        LED_G=1;
                        LED_B=1;       //2次高电平,LED亮白色
                }
                else
                {
                        LED_R=0;
                        LED_G=0;
                        LED_B=0;       //8次低电平,LED熄灭,亮度20%
                }
                delay_n_ms(1);   //每循环一次1ms
        }
}

 

 

PWM与时间片思想

时间片:

CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片,即该进程允许运行的时间,使各个程序从表面上看是同时进行的。

 

如何设计一个时间片程序:

1.求最小时间片
多个程序对时间的需求是不一样的,要想组合两个程序,就要找到他们的最小时间片。
现在我们有两个程序,按键程序每10ms执行一次,PWM程序每1ms执行一次,所以最小时间片就是1ms!


2.确认系统循环周期
while(1)每循环一次,所有程序执行一遍,相当于系统的一个循环,循环周期就是最小时间片1ms。


3.多程序共用最小时间片
很简单的数学问题,按键程序10ms一次,PWM 1ms一次,只要每执行10次PWM后执行一次按键检测即可。

 

#include<reg51.h>

sbit LED_R=P3^4;//定义红灯
sbit LED_G=P3^3;//定义绿灯
sbit LED_B=P3^2;//定义蓝灯

sbit Key1=P3^0;//定义按键

unsigned char Key1_old;    //定义一个数据,记录过去出现低电平
unsigned char time;        //定义一个数据,记录时间

unsigned char duty;        //定义一个数据,代表占空比
unsigned char count;       //定义一个数据,PWM循环次数


void Delay1ms()                //@12.000MHz
{
        unsigned char i, j;

        i = 12;
        j = 169;
        do
        {
                while (--j);
        } while (--i);
}

void delay_n_ms(unsigned int n) //自己定义的延时n毫秒函数
{
        while(n)         
        {
                Delay1ms();
                n=n-1;//每循环一次n减小1
        }    
}

main()
{
        Key1_old=1;   //进入循环前,先初始化标志位。按键还没按下,old是高电平
        
        while(1)    
        {
                delay_n_ms(1);   //系统周期,每循环一次1ms
                
                count=count+1;   //每过1ms计数+1
                if(count>9)      
                {
                        count=0;       //计数大于9后又变成0!,0~9十毫秒PWM周期
                }

                if(duty>count)   //在count 0~9变化中,duty大于count的次数就是占空比
                {
                        LED_R=1;
                        LED_G=1;
                        LED_B=1;       //改变duty改变高电平时间,亮度变化
                }
                else
                {
                        LED_R=0;
                        LED_G=0;
                        LED_B=0;       
                }

                time=time+1;  //1ms计数
                if(time>9)    //time加到10ms,从0开始
                {
                        time=0;    
                        if(Key1==1)
                        {
                                if(Key1_old==0) //如果本次是高电平,上次是低电平,检测到按键
                                {
                                        duty=duty+1;  //每次按键改变一次亮度
                                        if(duty>9)
                                        {
                                                duty=0;     //10级亮度调节
                                        } 
                                }
                        }

                        Key1_old=Key1;     //保存高低电平        
                }

        }

}
posted @ 2018-03-17 22:53  schips  阅读(419)  评论(0)    收藏  举报