如何在16位P& F校正PWM中设置Timer1的频率和占空比

时间:2018-02-24 08:45:25

标签: timer frequency avr 16-bit

我正在使用328P(在内部8mhz上运行)以大约111Khz或120Khz产生方波,并且具有可调节的占空比。

我很擅长这种级别的硬件操作,所以请原谅我的无知,我花了3天时间在线查看并在数据表中查看,但我担心我对缩略语和缩写词含义的理解仍然太有限。

到目前为止,我在网上和数据表中进行了研究后得出了以下代码。但我觉得我错过了什么,什么寄存器操纵频率和寄存器操作占空比(数据表20.12.5)相位和频率校正PWM模式?

void setup(){
    DDRB |= (1 << DDB1); //Set PB1 as output
    OCR1A = (Unsure of what TOP should be here);
    TCCR1A = (1 << WGM10) | (1 << COM1B0) | (1 << COM1A0);
    TCCR1B = (1 << CS10) | (1 << WGM13);
}
void loop(){
    //manipulate duty cycle with other code here
}

我错过了什么或者我应该做些什么呢? 我尝试使用在线AVR Timer Calc帮助我获得该频率所需的时钟滴答。它表示共有72个定时器滴答,没有预分频器,16位定时器会产生111Khz(近似)方波。跳到73或71跳频率超出所需范围。有没有什么方法可以在AVR上更接近?

2 个答案:

答案 0 :(得分:1)

在标题中,您询问“ATMega328P如何设置TIMER1 PWM频率”。您可以通过将TOP值设置为您想要的值来调整频率。较小的TOP值意味着计数器更快到达TOP,因此频率更高。用于定时器的预分频器和时钟源决定了它的计数速度,因此也会影响频率,可能的频率范围以及设置频率所需的分辨率。 TOP值也决定了设置占空比时的分辨率,因为占空比应该是小于或等于TOP的整数。

在你帖子的底部附近,你问“有没有办法让你更接近AVR?”由于您的AVR以8 MHz运行,因此您使用其定时器生成的每个频率将采用(8 MHz)/ N的形式,其中N是某个整数。那是因为定时器无法做任何事情或在您提供给他们的时钟源的滴答之间做任何改变。定时器1将获得每微秒8次的时钟滴答,并且每次发生时钟滴答时,它可以提前计数和/或控制PWM引脚和/或触发中断。我想你已经使用在线AVR计时器计算器来解决这个问题了。以下是在8 MHz运行的AVR上可以获得的一些可实现的PWM频率:

  • 8000 kHz / 73 = 109.6 kHz
  • 8000 kHz / 72 = 111.1 kHz
  • 8000 kHz / 71 = 112.7 kHz

如果您需要更精确的频率调谐,您需要以这种或那种方式在系统中获得更快的时钟源。您可以获得更快的微控制器,或者想出如何提供更快的时钟作为微控制器上定时器的输入。

答案 1 :(得分:0)

经过大量研究,我的一位朋友也是EE,并使用嵌入式系统,我们找到了最好的解决方案,以便从328p中获得我需要的东西。我将在下面发布解决方案给任何感兴趣并且需要类似内容的人。

void setup() {
  // put your setup code here, to run once:
  //Set Timer1 for around 109Khz signal
  cli();//stop interrupts
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  //Set register bits 
  TCCR1A = _BV(COM1A1) | _BV(WGM11);
  TCCR1B = _BV(CS10) | _BV(WGM12) | _BV(WGM13);
  ICR1 = 73; // frequency = 8000000/73 = 109.589 kHz
  OCR1A = 0; //0% Duty Cycle or Full Off.
  sei();//allow interrupts
}

void loop() {
  // put your main code here, to run repeatedly:
  OCR1A = 36; //50% Duty Cycle 73/2 = 36.5 Can be changed as needed.
}

此代码设置定时器1的寄存器,因此它不应干扰Arduino库中的millis或其他定时功能。无论如何我需要操纵一个特定的引脚,PB1(OC1A)(或Arduino数字引脚9)是它将振荡的引脚。

您可以根据一些简单的数学运算将ICR1更改为您需要的任何值, 您的时钟频率除以计数器的值等于产生的近似频率。 OCR1A设置信号的占空比。

您的确切频率有限,但根据我的需要,这个确定无误。 我仍然可以用它来驱动我正在使用的传感器。

这是对初始问题的快速回答,并允许我将工作周期更改为奖励。我不记得我们设置的寄存器的确切信息。当我有时间时,我将使用与此相关的数据表中的信息更新此答案。