- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想生成一个具有可变频率和固定占空比 (50%) 的 PWM 信号。频率应在 0-25KHz 之间变化。这是用于 ATMEGA32U4 微 Controller 的,我正在使用 Atmel Studio 用 C 语言编写它。我确实阅读了数据表,但我无法理解如何进行计算以及我应该使用哪种模式。在浏览了不同的教程后,我发现最好使用 CTC 模式。
既然频率是一个变量,我该如何选择我应该使用的预分频器?我需要使用中断吗?感谢您提供有关如何设置这些定时器寄存器的任何帮助。
最佳答案
32U4 的定时器与我针对您的问题进行测试的 328P 相同。我使用了提供最佳分辨率的定时器 1。该定时器可以在 CTC 模式下运行,并且 channel A 可以绑定(bind)到比较匹配切换中的固定输出引脚。这使得设置非常简单并且不需要中断逻辑。频率可以简单地通过写入 OCR1A
来控制(该寄存器是双缓冲的,因此频率的变化应该没有毛刺)
*。
在 CTC 模式下,定时器 1 的输出频率为:
f n x = f_cpu / (2 * n * (1 + x))
其中 n 是预分频值,x 是溢出比较寄存器。探索 16MHz 时钟的可能频率范围给出:
| N | f-min | f-max | r-min | r-max | x-100 | x-25k |
+-----+--------+-----------+-----------+-----------+-------+-------+
| 1 | 122.1 | 8,000,000 | 4,000,000 | 0.0019 | n/a | 319 |
| 8 | 15.3 | 1,000,000 | 500,000 | 0.00023 | 9,999 | 39 |
| 64 | 1.91 | 125,000 | 62,500 | 0.000029 | 1,249 | 4 |
| 256 | 0.49 | 31,250 | 15,625 | 0.0000073 | 311 | n/a |
|1024 | 0.12 | 7,812 | 3,906 | 0.0000018 | 77 | n/a |
其中 N 是预缩放设置,f-min 和 f-max 是可实现的最小和最大频率 r-min 和 r-max 是最小和最大频率分辨率,最后是 x-100 和 x-25k 所需的值OCR1A 分别用于 100Hz 和 25kHz 输出。
对于完整的工作示例,这里有一个程序,它以 2 秒的步长循环频率 1Hz、2、5、10...500kHz,足以观察示波器的工作情况:
#include <avr/io.h>
#include <util/delay.h>
struct CTC1
{
static void setup()
{
// CTC mode with TOP-OCR1A
TCCR1A = 0;
TCCR1B = _BV(WGM12);
// toggle channel A on compare match
TCCR1A = (TCCR1A & ~(_BV(COM1A1) | _BV(COM1A0))) | _BV(COM1A0);
// set channel A bound pin to output mode
DDRB |= _BV(1); // PB1 on 328p, use _BV(5) for PB5 on 32U4
}
static void set_freq(float f)
{
static const float f1 = min_freq(1), f8 = min_freq(8), f64 = min_freq(64), f256 = min_freq(256);
uint16_t n;
if (f >= f1) n = 1;
else if (f >= f8) n = 8;
else if (f >= f64) n = 64;
else if (f >= f256) n = 256;
else n = 1024;
prescale(n);
OCR1A = static_cast<uint16_t>(round(F_CPU / (2 * n * f) - 1));
}
static void prescale(uint16_t n)
{
uint8_t bits = 0;
switch (n)
{
case 1: bits = _BV(CS10); break;
case 8: bits = _BV(CS11); break;
case 64: bits = _BV(CS11) | _BV(CS10); break;
case 256: bits = _BV(CS12); break;
case 1024: bits = _BV(CS12) | _BV(CS10); break;
default: bits = 0;
}
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11) | _BV(CS10))) | bits;
}
static inline float min_freq(uint16_t n)
{
return ceil(F_CPU / (2 * n * 65536));
}
};
void setup()
{
CTC1::setup();
}
void loop()
{
for (uint8_t x = 0; x < 6; ++x)
for (uint8_t y = 0; y < 3; ++y)
{
float k = y > 0 ? (y > 1 ? 5 : 2) : 1;
CTC1::set_freq(k * pow(10, x));
_delay_ms(2000);
}
}
int main()
{
setup();
for (;;)
loop();
}
可在 PB1(Arduino Uno 上的数字引脚 9)上观察到信号。请注意,在 32U4 上, channel A 绑定(bind)到 PB5。
正如 Aleksander Z. 善意评论的那样,OCR1A 寄存器在 CTC 模式下不是双缓冲的。当切换频率时,这会导致严重的故障,例如:
根据应用程序,这可以通过忙循环轻松解决(尽管这可能不适用于非常高的频率,或者可能在非常低的频率下导致 Not Acceptable 延迟):
while (TCNT1 > x)
;
OCR1A = x;
制作:
关于avr - 为 AVR 生成变频 PWM 信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38341230/
我有一个关于 Arduino 的一般性问题,如何每秒使用 AnalogRead() 读取一定次数的传感器值。每秒说 10 次,并且还不断地向电机输出 PWM。 如果我尝试延迟循环(),它会影响我与 A
我正在使用 iMX6Q SD 板。而且我必须访问背光驱动程序来控制背光对比度。如何从用户空间或内核空间访问? (背光PWM驱动路径为drivers/video/backlight/pwm_bl.c)。
这应该是一个简单的公式,但我无法理解。 我有一个 16mHZ AVR 芯片。 我需要运行一个 24kHZ 的 PWM 信号.. 决定最佳预分频器的公式是什么。 我正在使用 16 位定时器。 最佳答案
我试图将PWM用于端口B的任何引脚上的ATmega8上的LED。设置计时器一直很烦人,我不知道该如何处理OCR1A。这是我的代码,我希望收到一些反馈。 我只是想弄清楚如何使用PWM。我知道这个概念,O
我一直在 ATMega328P 上试验 PWM 波形生成模式。我得到了一些奇怪的结果,我无法确定是我编写固件的方式有问题还是我解释 datasheet 的方式有问题。 . 这是我为模拟 analogW
我想测量 PWM 信号的频率。为此,我使用了 STM-F401RE 及其 Timer_Input_Capture 函数。 问题是: 输入信号具有相当高的频率(大约 2MHz),并且, STM-F401
我正在使用 MPC 7555 Controller 。它有一个 16 位 Σ-Δ ADC。称为麦克风输入的信号被馈送到该 ADC 引脚。根据该电压,产生与ADC信号采样频率相同的PWM信号。 For
我想创建一个 PWM 信号。我希望频率接近 38 kHz。我的理论计算周期是 26.3 微秒。所以我选择26微秒。我可以观察我的信号。 但我不明白我的代码如何正常工作:) (我的时钟频率是1MHz,所
我正在尝试编写一个程序来生成正弦波,我将通过被动夏季输出这些正弦波,从而在我按下按钮时让微 Controller 播放声音。 我已经让 PWM 正常工作,并且可以使用常量值演奏音符,但我想使用正弦波而
我可能只是在使用这些寄存器之一时遇到了一个看不见森林的时刻,但我无法让 PWM 在 dsPIC33FJ32MC102 上工作微 Controller (警告:大 PDF)我正在玩。我已经遵循了数据表和
如何将字符串输出为列表? (可能很简单,我知道) 我查看了所有 google,NONE 的解决方案有效。 我的代码:(有点意译) import Pmw from tkinter import * ro
我正在尝试为每个对角线(在我的例子中为 PWM1 和 PWM4)使用一个 PWM 发生器来控制 H 桥转换器。 我希望能够同时控制频率和占空比。为此,我在 PWM4 周期开始时生成触发中断,然后更新两
在 Atmel ATmega328P (datasheet) 上,有三个定时器可用于 PWM 生成(定时器 0、定时器 1 和定时器 2)。 我已经有了使用 8 位 timer2 所需的东西,我只关心
我正在尝试用蜂鸣器和 Arduino 制作和弦音乐播放器。我在关注 this教程作为指南,但我无法弄清楚。代码就像: void playTone() { long elapsed_time =
我有一个 STM32F4,我想对一个已与掩码进行“或”运算的 GPIO 端口进行 PWM 处理。 所以,也许我们想要以 200khz 的频率 PWM 0b00100010 一段时间,但是,10khz
我建了this motor shield基于L298N芯片控制坦克的两个电机。一个电机使用引脚 5 和 6,另一个电机使用引脚 10 和 11。 尝试添加TSOP 4838时为了用红外 Remote
我有一个 STM32F4,我想对一个已与掩码进行“或”运算的 GPIO 端口进行 PWM 处理。 所以,也许我们想要以 200khz 的频率 PWM 0b00100010 一段时间,但是,10khz
我是 ARM MCU (STM32F411) 的新手,我一直在尝试使用 STM 的 HAL 库和 STM32Cube 寻找外围设备的方法。 为了使用一些外围设备,我已经配置了我的开发板: Timer
Raspberry pi B+ 有四个硬件 PWM。如何在 C/C++ 中使用它们。解决方案越简单越好。 我用 WiringPi 找到了一个可行的解决方案 gpio mode 1 pwm gpio
我一直在尝试在 PIC16F877 MCU 上使用 PWM 模块,但我得到的只是 CCP1/CCP2 引脚上的平坦低电平。 配置和启动 PWM 模块的代码如下。 // Configure PWM //
我是一名优秀的程序员,十分优秀!