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; //保存高低电平 } } }
如果说我的文章对你有用,只不过是我站在巨人的肩膀上再继续努力罢了。
若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
博客地址:https://www.cnblogs.com/schips/
若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
博客地址:https://www.cnblogs.com/schips/

浙公网安备 33010602011771号