极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 113013|回复: 13

Arduino系列教程之 – PWM的秘密(上)(转)

[复制链接]
发表于 2011-9-23 10:26:50 | 显示全部楼层 |阅读模式
原文地址:http://www.diy-robots.com/?p=814

今天是3.8妇女节,我也沾了点光,提前开溜了(公司的mm们都放假了,大家工作没动力啊)。呵呵,在此祝福所有的美女们节日快乐!

前几天在微博上看到了flamingoeda小盆友提到了PWM,毕竟微博只能有一百多字,没法详细的介绍清楚,特此补充一下。

PWM是啥玩意儿?
PWM是“怕玩命”的缩写,英文写法是“Pulse-width modulation”,也有些外行人士把它翻译成“脉冲宽度调制”。Arduino有很多种版本,这篇文章里是以ATmega168为例,有用过其他型号的兄弟请补充。
对于没有听说过PWM的同学,请先参考一下我的另一篇博客Arduino的模拟输入和输出。

PWM是用占空比不同的方波,来模拟“模拟输出”的一种方式。靠,这个太拗口了,简而言之就是电脑只会输出0和1,那么想输出0.5怎么办呢?于是输出01010101….,平均之后的效果就是0.5了。早这么说就了然了嘛。

PWM有神马作用?
举几个例子说明:
1.通过简单的滤波电路,就可以生成真正的模拟输出量;
2.控制灯光亮度,调节电机转速;请注意这和1不是重复的,因为不需要滤波就可以实现
3.控制舵机角度,这个请参考 Arduino开发板实验三:舵机控制
4.输出信号,例如接喇叭的时候可以发声

如何产生PWM?
Arduino有三种方式可以产生PWM。第一种:

用analogWrite(pin, val)命令
其中pin是腿的编号,传说中只能用3,5,6,9,10,11这几条;val是0~255的整数值,对应电压从0到+5V。注意,那几个脚的编号,指的是ATmega168的pin编号,Arduino的板子会用这几个管脚支持更多路的PWM输出,例如我的Arduino Mega168就支持0~13共14个PWM输出。
具体的使用可以看下面的示例代码:
  1. int pin = 8; //0~13

  2. void setup()
  3. {
  4.     pinMode(pin, OUTPUT);
  5. }   

  6. void loop()
  7. {
  8.     analogWrite(pin, 128);
  9.     delay(500);
  10. }
复制代码
这种方式产生的方波周期大概是20ms左右(50Hz),不需要占用额外的cpu命令时间。据说99%的同学看到这里就可以下课了,技术宅请继续看第二种方式:

手动用代码实现PWM
  1. int pin = 38;  //这个可以随意点

  2. void setup()
  3. {
  4.     pinMode(pin, OUTPUT);
  5. }

  6. void loop()
  7. {
  8.   digitalWrite(pin, HIGH);
  9.   delayMicroseconds(100);
  10.   digitalWrite(pin, LOW);
  11.   delayMicroseconds(1000 - 100);
  12. }
复制代码
上面这段代码会产生一个PWM=0.1的,周期为1ms的方波(1000Hz),这种方式的优缺点很明显:
1,PWM的比例可以更精确;
2,周期和频率可控制;
3,所有的pin脚都可以输出,不局限于那几个脚;
4,缺点:CPU干不了其他事情了;
好吧,缺点只有一个,却非常致命,以至于上面这些基本都是废话。但是对于周期比较大的PWM,可以用算法模拟CPU的多任务系统,从而在输出PWM的同时做点兼职。

那么能不能既调节PWM的频率和周期,又不要占用额外的CPU时间呢?请看第三种方式:

使用PWM寄存器

ATmega168有三个时钟,名字分别叫Timer0, Timer1和Timer2。每个时钟都使用了两个寄存器,其中一个是设定值例如128,另一个则从0开始不断递增,到1024之后溢出回到0。那么当两个值相同的时候,Timer就会把某个管脚反相。不同的Timer之间频率是相同的,占空比则根据设置值不同。
占空比有了,那么周期怎么控制呢?有一种叫做时钟控制器的东东,这个控制器可以设置周期为CPU周期的某个倍数,例如1,8,64,256,1024等等,Timer0和Timer1共用一个控制器,Timer2和它们是独立的。

今天先写这些,明天继续…..
本文内容基本都是参考自Arduino官网教程,心急的同学请看英文原版:
http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2012-1-12 09:33:56 | 显示全部楼层
受益匪浅。
回复 支持 反对

使用道具 举报

发表于 2012-1-12 14:54:35 | 显示全部楼层
今天是3.8妇女节,我也沾了点光...
回复 支持 反对

使用道具 举报

发表于 2012-5-17 10:13:32 | 显示全部楼层
后面的呢??想知道第三种的编程方式啊
回复 支持 反对

使用道具 举报

发表于 2014-7-18 23:10:13 | 显示全部楼层
第一个例子错误,不能改变频率,改变的是占空比,
回复 支持 反对

使用道具 举报

发表于 2014-7-20 11:37:58 | 显示全部楼层
impressive 。占空比和频率是不一样的,同一个周期内高电平的持续时间是占空比not 频率
回复 支持 反对

使用道具 举报

发表于 2014-9-21 22:42:37 | 显示全部楼层
传说中只能用3,5,6,9,10,11这几条  ~~亲测,,其他确实不能用,  
回复 支持 反对

使用道具 举报

发表于 2014-11-20 20:05:05 | 显示全部楼层
请问第二种方法如何改变输出pwm波的频率啊?新手不太了解。。。是要改变哪些参数?
回复 支持 反对

使用道具 举报

发表于 2015-10-20 12:21:00 | 显示全部楼层
analogWrite()
The frequency of the PWM signal is approximately 490 Hz.
PWM的信号频率约为490赫兹~~~
回复 支持 反对

使用道具 举报

发表于 2015-10-22 08:23:30 | 显示全部楼层
学习了!
经典就是经典
回复 支持 反对

使用道具 举报

发表于 2015-12-19 20:05:50 | 显示全部楼层
老文翻出来看看,还挺有意思。
回复 支持 反对

使用道具 举报

发表于 2016-3-29 16:32:33 | 显示全部楼层
你好   我用的是mega 2560,有15个pwm引脚,2~13 、44~46,我想问一下mega2560 有几个定时器,分别控制哪几个引脚,然后 哪些引脚频率是980hz,哪些是490hz
回复 支持 反对

使用道具 举报

发表于 2018-5-18 20:34:21 | 显示全部楼层
怎么改变周期呢?例如100us 200us 500us 1ms 2ms 5ms 10ms 20ms 50ms 100ms 200ms 500ms

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-20 03:51 , Processed in 0.049335 second(s), 32 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表