没有示波器测量,理论上结果,有示波器的可以测一下,要是不对给我说下把帖子删了(别坑了其他人)。
(1)话不多说直接放程序
//Mega 2560 PWM调频率(通过调节精度来实现)1/8分频
void setPwmFrequency(int pin,int precision){
if(pin == 11 || pin == 12 || pin == 13){ //timer 1(16位)
TCCR1A = _BV(COM1A0)|_BV(COM1B1)|_BV(WGM11)|_BV(WGM10);
TCCR1B = _BV(WGM13)|_BV(WGM12)|_BV(CS11);
OCR1A = precision;
}else if(pin == 10 || pin == 9){ //timer 2(8位)
TCCR2A = _BV(COM2A0)|_BV(COM2B1)|_BV(WGM21)|_BV(WGM20);
TCCR2B = _BV(WGM22)|_BV(CS21);
OCR2A = precision;
}else if(pin == 5 || pin == 2 || pin == 3){ //timer 3(16位)
TCCR3A = _BV(COM3A0)|_BV(COM3B1)|_BV(WGM31)|_BV(WGM30);
TCCR3B = _BV(WGM33)|_BV(WGM32)|_BV(CS31);
OCR3A = precision;
}else if(pin == 6 || pin == 7 || pin == 8){ //timer 4(16位)
TCCR4A = _BV(COM4A0)|_BV(COM4B1)|_BV(WGM41)|_BV(WGM40);
TCCR4B = _BV(WGM43)|_BV(WGM42)|_BV(CS41);
OCR4A = precision;
}else if(pin == 46 || pin == 45 || pin == 44){ //timer 5(16位)
TCCR5A = _BV(COM5A0)|_BV(COM5B1)|_BV(WGM51)|_BV(WGM50);
TCCR5B = _BV(WGM53)|_BV(WGM52)|_BV(CS51);
OCR5A = precision;
}
}
/*输出频率 = 16M(时钟源)/8(分频数)/precision 通过调节precision来调节输出频率
**8位precision调节范围0-255,16位precision调节范围是0-65535
**precision的数值就是函数analogWrite()的上限值,不再是255。
*/
timer0有控制delay()这些计时函数的功能,改了之后会麻烦,就没加上。
寄存器控制引脚分配图:
**引脚中带A的(13引脚 OC0A)输出的频率是其他引脚(计算数值)的一半,占空比一直是50%,不要用analogWrite()调节这个引脚的数值。想知道原因的可以等下看下面链接中的其他帖子。
(2)需要调分频的可以根据这张图调节寄存器设置 ,增加频率的调节范围
调节寄存器中CSn的数值来调节分频数;如上面的CSn1代表(第二位为1,从0开始算第一位)1/8分频,CSn2(第三位为1)1/256分频,以此类推。
寄存器控制图(图中是寄存器3)
(3)示例程序
void setup() {
pinMode(45,OUTPUT);//OC5B
pinMode(46,OUTPUT);//OC5A
setPwmFrequency(45,100);//输出频率 16M/8/100 = 20k,46引脚是10k,
//每个寄存器设置一个引脚就可以
}
void loop() {
//analogWrite(46,50); 不要写类似这样的,和这句OCR5A = precision;冲突
analogWrite(45,40);//测出电压(2.0V) 没有示波器测不了频率,也不知道对不对
}
//Mega 2560 PWM调频率(通过调节精度来实现)1/8分频
void setPwmFrequency(int pin,int precision){
if(pin == 11 || pin == 12 || pin == 13){ //timer 1(16位)
TCCR1A = _BV(COM1A0)|_BV(COM1B1)|_BV(WGM11)|_BV(WGM10);
TCCR1B = _BV(WGM13)|_BV(WGM12)|_BV(CS11);
OCR1A = precision;
}else if(pin == 10 || pin == 9){ //timer 2(8位)
TCCR2A = _BV(COM2A0)|_BV(COM2B1)|_BV(WGM21)|_BV(WGM20);
TCCR2B = _BV(WGM22)|_BV(CS21);
OCR2A = precision;
}else if(pin == 5 || pin == 2 || pin == 3){ //timer 3(16位)
TCCR3A = _BV(COM3A0)|_BV(COM3B1)|_BV(WGM31)|_BV(WGM30);
TCCR3B = _BV(WGM33)|_BV(WGM32)|_BV(CS31);
OCR3A = precision;
}else if(pin == 6 || pin == 7 || pin == 8){ //timer 4(16位)
TCCR4A = _BV(COM4A0)|_BV(COM4B1)|_BV(WGM41)|_BV(WGM40);
TCCR4B = _BV(WGM43)|_BV(WGM42)|_BV(CS41);
OCR4A = precision;
}else if(pin == 46 || pin == 45 || pin == 44){ //timer 5(16位)
TCCR5A = _BV(COM5A0)|_BV(COM5B1)|_BV(WGM51)|_BV(WGM50);
TCCR5B = _BV(WGM53)|_BV(WGM52)|_BV(CS51);
OCR5A = precision;
}
}
**记录学习用,侵权必删
参考链接(建议观看)
arduino官方文档
https://docs.arduino.cc/tutorials/generic/secrets-of-arduino-pwm
动力老男孩
http://www.diy-robots.com/?p=852
arduino中文社区
https://www.arduino.cn/thread-19799-1-1.html