将ATtiny13编程为具有可变频率和脉冲宽度的音频振荡器


8

我想创建一个类似于555的简单方波振荡器,但是我想使用基于中断的PWM支持来控制脉冲宽度和频率。

我一直在研究数据表,AVR API和我能找到的任何PWM示例,但是我还不能完全将它们放在一起。

是否可以使用内置的AVR PWM功能创建这样的振荡器?如果可以,怎么做?我的一个朋友用8针PIC做过类似的事情。

我的理由是,通过更改脉冲宽度以及给定频率下的波形,我将获得有趣的声音。与Atari Punk Console的工作方式类似,但希望以更稳定的方式进行,即更改脉冲宽度,但保持频率恒定,反之亦然。


2
请问您的问题是什么?
杰森S

我不确定它们会是多么有趣,但是尝试起来很容易,您就可以判断了。随着脉冲变窄,谐波的幅度增加。不断收窄脉冲,会产生白噪声。我认为您在做数控振荡器时会有更多有趣的选择。您可以更改加载到波表中的波形。
jluciani

Answers:



4

PWM的周期由定时器的溢出率决定。在“操作模式”部分需要考虑很多设置。如果您要做的只是生成具有可变占空比的恒定周期方波,我想您将要使用CTC(比较匹配时清除计时器)模式。基本思想是将OCR0A设置为计时器的滴答数,直到您希望引脚下次切换为止,然后使用“比较匹配”中断在下一次更改该值。因此在avr-gcc中,它看起来像:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

// global variables defining number of ticks on and off
uint8_t on_time_ticks, off_time_ticks, csxx_bits=0; 


void setup_timer(double p_ms, double duty){
  TCCR0A = _BV(COM0A0) // toggle OC0A on Compare Match
  TCCR0B = _BV(WGM02); // set CTC mode WGM0[2,1,0] = 0b100

  // ... do some stuff based on your CPU frequency
  // to define the csxx_bits of TCCR0B when the timer is running
  // and consequently, to set on_time_ticks and off_time_ticks
  OCR0A = on_time_ticks;
  TCCR0B |= your_settings_here;
}


void start_timer(){
  //start the timer running at the desired rate
  TCCR0B |= csxx_bits; 
}


int main(int argc, char **argv){
  double period_ms, duty_cycle;
  setup_timer(period_ms, duty cycle);
  start_timer();  
  for(;;){
    //spin or sleep or whatever
  }
}


ISR(TIM0_COMPA_vect){
  if(OCR0A == on_time_ticks){
    OCR0A = off_time_ticks;
  }
  else{
    OCR0A = on_time_ticks;
  }
}

警告,这是未经测试的代码,但我认为这个想法是正确的。这绝不是唯一的方法。

顺便说一句,您应该了解ATTiny13一件事。内部RC振荡器仅保证在出厂时的精度在10%以内。您可以执行一个用户校准过程(由atmel 应用笔记进行描述),以使ATTiny13的准确度提高2%。如果您想做得更好,则可能需要使用可容纳外部晶体的芯片...


1
您的回答有助于弄清我遇到的类似问题-谢谢。一点(对于任何在原始线程之后很久才读的人):对于WGM0 [2,1,0]选择的0b100不会设置CTC模式。(实际上,它将设置Atmel保留的模式。)ATtiny13数据表指出CTC模式需要值为 2;CTC模式需要为2。您不小心给了它bit_number 2(即值4)。因此,不仅有必要更改(即清除)TCCR0B中的WGM02,而且还需要分别将WGM01和WGM00位设置为1和0。这些位在TCCR0A中,因此仅设置TCCR是不够的

3

不是您问题的直接答案,但这可能是适当的,并提供了一些提示-

我刚刚使用ATmega uC和DAC创建了一个数控振荡器(NCO)。整数数组用于存储一个波形周期(波形表)。相位累加器(long int)用于确定波表中输出数据的地址。每个定时器中断都会使相位累加器增加一个固定值。相位增量确定频率。

在我的应用程序中,我使用了一个包含一个正弦波周期的64字节波表。扩展波表并为样本增加分辨率更容易。我的应用笔记位于http://wiblocks.com/docs/app-notes/nb1a-nco.html


1

基本上,PWM不会改变频率。PWM通常用于控制信号的“强度”。

要生成不同频率的中断,建议您在CTC模式下使用计时器。

它会运行到您的比较值,切换中断,清除并自行重启-直到再次运行到您的比较值...

每次中断时,您都可以切换一个或多个端口,其余时间(计时器仍会自动运行),您可以观察任何类型的输入...

您仍然可以使用PWM“调制”方波来控制“增益”。但是其中之一必须“手动”完成,因为ATtiny13只有一个硬件计时器...


1
大多数硬件PWM外设可让您选择频率;如果您保持占空比恒定,那么PWM仍然可以为您提供变频控制
Jason S

1
改变脉冲宽度不会改变基频,但会改变谐波。
jluciani
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.