男女做那个网站动态图片,四平网站公司,保险销售的建设网站策划书,北京建网站的公司PWM是Pulse Width Modulation的缩写#xff0c;它的中文名字是脉冲宽度调制#xff0c;一种说法是它利用微处理器的数字输出来对模拟电路进行控制的一种有效的技术#xff0c;其实就是使用数字信号达到一个模拟信号的效果。这是个什么概念呢#xff1f;我们一步步来介绍。首… PWM是Pulse Width Modulation的缩写它的中文名字是脉冲宽度调制一种说法是它利用微处理器的数字输出来对模拟电路进行控制的一种有效的技术其实就是使用数字信号达到一个模拟信号的效果。这是个什么概念呢我们一步步来介绍。首先从它的名字来看脉冲宽度调制就是改变脉冲宽度来实现不同的效果。我们先来看三组不同的脉冲信号如图所示。图 10-1 PWM 波形这是一个周期是 10ms即频率是 100Hz 的波形但是每个周期内高低电平脉冲宽度各不相同这就是 PWM 的本质。在这里大家要记住一个概念叫做“占空比”。占空比是指高电平的时间占整个周期的比例。比如第一部分波形的占空比是 40%第二部分波形占空比是 60%第三部分波形占空比是 80%这就是 PWM 的解释。那为何它能对模拟电路进行控制呢大家想一想我们数字电路里只有 0 和 1 两种状态比如我们第 2 章学会的点亮 LED 小灯那个程序当我们写一个 LED 0;小灯就会长亮当我们写一个 LED 1;小灯就会灭掉。当我们让小灯亮和灭间隔运行的时候小灯是闪烁。如果我们把这个间隔不断的减小减小到我们的肉眼分辨不出来也就是 100Hz 以上的频率这个时候小灯表现出来的现象就是既保持亮的状态但亮度又没有 LED 0;时的亮度高。那我们不断改变时间参数让 LED 0;的时间大于或者小于 LED 1;的时间会发现亮度都不一样这就是模拟电路的感觉了不再是纯粹的 0 和 1还有亮度不断变化。大家会发现如果我们用 100Hz 的信号如图 10-1 所示假如高电平熄灭小灯低电平点亮小灯的话第一部分波形熄灭 4ms点亮 6ms亮度最高第二部分熄灭 6ms点亮 4ms亮度次之第三部分熄灭 8ms点亮 2ms亮度最低。那么用程序验证一下我们的理论我们用定时器T0 定时改变 P0.0 的输出来实现 PWM与纯定时不同的是这里我们每周期内都要重载两次定时器初值即用两个不同的初值来控制高低电平的不同持续时间。为了使亮度的变化更加明显程序中使用的占空比差距更大。#includesbit PWMOUT P0^0;sbit ADDR0 P1^0;sbit ADDR1 P1^1;sbit ADDR2 P1^2;sbit ADDR3 P1^3;sbit ENLED P1^4;unsigned char HighRH 0; //高电平重载值的高字节unsigned char HighRL 0; //高电平重载值的低字节unsigned char LowRH 0; //低电平重载值的高字节unsigned char LowRL 0; //低电平重载值的低字节void ConfigPWM(unsigned int fr, unsigned char dc);void ClosePWM();void main(){unsigned int i;EA 1; //开总中断ENLED 0; //使能独立 LEDADDR3 1;ADDR2 1;ADDR1 1;ADDR0 0;while (1){ConfigPWM(100, 10); //频率 100Hz占空比 10%for (i0; i40000; i);ClosePWM();ConfigPWM(100, 40); //频率 100Hz占空比 40%for (i0; i40000; i);ClosePWM();ConfigPWM(100, 90); //频率 100Hz占空比 90%for (i0; i40000; i);ClosePWM(); //关闭 PWM相当于占空比 100%for (i0; i40000; i);}}/* 配置并启动 PWMfr-频率dc-占空比 */void ConfigPWM(unsigned int fr, unsigned char dc){unsigned int high, low;unsigned long tmp;tmp (11059200/12) / fr; //计算一个周期所需的计数值high (tmp*dc) / 100; //计算高电平所需的计数值low tmp - high; //计算低电平所需的计数值high 65536 - high 12; //计算高电平的重载值并补偿中断延时low 65536 - low 12;//计算低电平的重载值并补偿中断延时HighRH (unsigned char)(high8); //高电平重载值拆分为高低字节HighRL (unsigned char)high;LowRH (unsigned char)(low8); //低电平重载值拆分为高低字节LowRL (unsigned char)low;TMOD 0xF0; //清零 T0 的控制位TMOD | 0x01; //配置 T0 为模式 1TH0 HighRH; //加载 T0 重载值TL0 HighRL;ET0 1; //使能 T0 中断TR0 1; //启动 T0PWMOUT 1; //输出高电平}/* 关闭 PWM */void ClosePWM(){TR0 0; //停止定时器ET0 0; //禁止中断PWMOUT 1; //输出高电平}/* T0 中断服务函数产生 PWM 输出 */void InterruptTimer0() interrupt 1{if (PWMOUT 1){ //当前输出为高电平时装载低电平值并输出低电平TH0 LowRH;TL0 LowRL;PWMOUT 0;}else{ //当前输出为低电平时装载高电平值并输出高电平TH0 HighRH;TL0 HighRL;PWMOUT 1;}}需要提醒大家的是由于标准 51 单片机中没有专门的 PWM 模块所以我们用定时器加中断的方式来产生 PWM而现在有很多的单片机都会集成硬件的 PWM 模块这种情况下需要我们做的就仅仅是计算一下周期计数值和占空比计数值然后配置到相关的 SFR 中即可既使程序得到了简化又确保了 PWM 的输出品质(因为消除了中断延时的影响)。大家编译下载程序后会发现小灯从最亮到灭一共 4 个亮度等级。如果我们让亮度等级更多并且让亮度等级连续起来会产生一个小灯渐变的效果与呼吸有点类似所以我们习惯上称之为呼吸灯程序代码如下这个程序用了 2 个定时器 2 个中断这是我们第一次这样用大家可以学习一下。我们来试试这个程序试完了大家一定要能自己把程序写出来切记。#includesbit PWMOUT P0^0;sbit ADDR0 P1^0;sbit ADDR1 P1^1;sbit ADDR2 P1^2;sbit ADDR3 P1^3;sbit ENLED P1^4;unsigned long PeriodCnt 0; //PWM 周期计数值unsigned char HighRH 0; //高电平重载值的高字节unsigned char HighRL 0; //高电平重载值的低字节unsigned char LowRH 0; //低电平重载值的高字节unsigned char LowRL 0; //低电平重载值的低字节unsigned char T1RH 0; //T1 重载值的高字节unsigned char T1RL 0; //T1 重载值的低字节void ConfigTimer1(unsigned int ms);void ConfigPWM(unsigned int fr, unsigned char dc);void main(){EA 1; //开总中断ENLED 0; //使能独立 LEDADDR3 1;ADDR2 1;ADDR1 1;ADDR0 0;ConfigPWM(100, 10); //配置并启动 PWMConfigTimer1(50); //用 T1 定时调整占空比while (1);}/* 配置并启动 T1ms-定时时间 */void ConfigTimer1(unsigned int ms){unsigned long tmp; //临时变量tmp 11059200 / 12; //定时器计数频率tmp (tmp * ms) / 1000; //计算所需的计数值tmp 65536 - tmp; //计算定时器重载值tmp tmp 12; //补偿中断响应延时造成的误差T1RH (unsigned char)(tmp8); //定时器重载值拆分为高低字节T1RL (unsigned char)tmp;TMOD 0x0F; //清零 T1 的控制位TMOD | 0x10; //配置 T1 为模式 1TH1 T1RH; //加载 T1 重载值TL1 T1RL;ET1 1; //使能 T1 中断TR1 1; //启动 T1}/* 配置并启动 PWMfr-频率dc-占空比 */void ConfigPWM(unsigned int fr, unsigned char dc){unsigned int high, low;PeriodCnt (11059200/12) / fr; //计算一个周期所需的计数值high (PeriodCnt*dc) / 100; //计算高电平所需的计数值low PeriodCnt - high; //计算低电平所需的计数值high 65536 - high 12; //计算高电平的定时器重载值并补偿中断延时low 65536 - low 12; //计算低电平的定时器重载值并补偿中断延时HighRH (unsigned char)(high8); //高电平重载值拆分为高低字节HighRL (unsigned char)high;LowRH (unsigned char)(low8); //低电平重载值拆分为高低字节LowRL (unsigned char)low;TMOD 0xF0; //清零 T0 的控制位TMOD | 0x01; //配置 T0 为模式 1TH0 HighRH; //加载 T0 重载值TL0 HighRL;ET0 1; //使能 T0 中断TR0 1; //启动 T0PWMOUT 1; //输出高电平}/* 占空比调整函数频率不变只调整占空比 */void AdjustDutyCycle(unsigned char dc){unsigned int high, low;high (PeriodCnt*dc) / 100; //计算高电平所需的计数值low PeriodCnt - high; //计算低电平所需的计数值high 65536 - high 12; //计算高电平的定时器重载值并补偿中断延时low 65536 - low 12; //计算低电平的定时器重载值并补偿中断延时HighRH (unsigned char)(high8); //高电平重载值拆分为高低字节HighRL (unsigned char)high;LowRH (unsigned char)(low8); //低电平重载值拆分为高低字节LowRL (unsigned char)low;}/* T0 中断服务函数产生 PWM 输出 */void InterruptTimer0() interrupt 1{if (PWMOUT 1){ //当前输出为高电平时装载低电平值并输出低电平TH0 LowRH;TL0 LowRL;PWMOUT 0;}else{ //当前输出为低电平时装载高电平值并输出高电平TH0 HighRH;TL0 HighRL;PWMOUT 1;}}/* T1 中断服务函数定时动态调整占空比 */void InterruptTimer1() interrupt 3{static bit dir 0;static unsigned char index 0;unsigned char code table[13] { //占空比调整表5, 18, 30, 41, 51, 60, 68, 75, 81, 86, 90, 93, 95};TH1 T1RH; //重新加载 T1 重载值TL1 T1RL;AdjustDutyCycle(table[index]); //调整 PWM 的占空比if (dir 0){ //逐步增大占空比index;if (index 12){dir 1;}}else{ //逐步减小占空比index--;if (index 0){dir 0;}}}呼吸灯效果做出来后利用这个基本原理其它各种效果的灯光闪烁都应该可以做出来大家看到的 KTV 里边那绚丽的灯光闪烁其实就是采用的 PWM 技术控制的。1.零基础让普通MCU跑人工智能法国AI创企开发无监督学习软件系统2.反对人工智能的九条意见3.看直播赢好礼丨各路大咖为您解读《疫情当下物联网与嵌入式系统的思考》4.STM32系统中的2种数据掉电保护方法5.如何学会所有的编程语言6.VSCode和SourceInsight到底哪个看源码爽免责声明本文系网络转载版权归原作者所有。如涉及作品版权问题请与我们联系我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。