- 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/
前言 众所周知,对于 16 位 I/O 寄存器(定时器计数器、ICR/OCR、ADC...)的原子和同时读/写高和低部分,AVR 使用影子临时寄存器。例如。在 ATmega8 上读取 TCNT1: u
我想使用 avr-gcc 将全局变量绑定(bind)到未使用的 I/O 寄存器(例如 PORTB),以减少代码大小。我在AVR的应用笔记AVR035中学到了这个技巧(第 14 页)。 在应用笔记中,他
我有一个项目,其中 ATtiny2313V 控制 7x5 LED 矩阵以显示滚动文本。为了显示文本,我构建了一个字体,它与程序的其余部分一起存储在闪存中。 整个程序,包括整个字体,占用 1106 字节
我尝试使用 this Code/Guide在 ATmega1284p 上。 我遇到的问题是链接器不工作,执行后出现以下错误消息(代码为 ATmega88 构建良好): avr-ld -o main.
我原以为 8 位 AVR 平台不需要任何对齐。但是,我在 an LLVM commit 中发现了以下评论: The previous data layout caused issues when de
我想生成一个具有可变频率和固定占空比 (50%) 的 PWM 信号。频率应在 0-25KHz 之间变化。这是用于 ATMEGA32U4 微 Controller 的,我正在使用 Atmel Studi
我想生成一个具有可变频率和固定占空比 (50%) 的 PWM 信号。频率应在 0-25KHz 之间变化。这是用于 ATMEGA32U4 微 Controller 的,我正在使用 Atmel Studi
当我尝试使用 AVR studio 4 调试一小段代码时,出现此错误: Build failed... No build tools defined. 有人能给我一些建议吗? 最佳答案 在 AVRSt
我有一个设置为 CodeVision AVR 项目的遗留代码。我想迁移到 AVR Studio 甚至更好的 NetBeans(使用 AVR 工具链或 WinAVR)。 有什么想法吗? 最佳答案 你应该
我在以 AVR 为目标的 C 中遇到毫秒延迟循环的问题。我在从 Ubuntu 存储库获得的 Linux 上使用 avr-gcc 4.7.0,我也有尝试了新编译的 4.7.2。目标硬件是 XMEGA12
如何启用或禁用 IDE 的自动完成功能 AVR-Studio 5或 AVR-Studio 4 ?我是否必须编辑一些安装文件才能做到这一点? 视频中AVR Studio 5: How to use th
我正在尝试用 Arduino Eclipse 插件替换 Arduino IDE。下载所需的一切并尝试编译最简单的“Hello World”程序后,我在 eclipse 中遇到以下错误: 调用时: wh
我继承了一个链接到一个库的应用程序,该库可能是用 gcc3 构建的。或者也许使用 imagecraft 编译器。这些信息现在已经消失在天堂般的位域中,我只剩下一个 libXXX.a 库来链接我的应用程
我正在尝试通过 USBASP 编程器将一些数据从 PC 发送到 ATmega328P 芯片。 它能够通过 SPI 传输最多 4 个字节。这 4 个字节可以在 USB Setup Packet 中设置(
我正在使用 ATMEGA128 与另一台设备进行通信。为此,我使用带有 ATMEGA128 的 SPI 作为从机。我使用 SS、SCK 和 MOSI 引脚。我面临的问题是,当我必须下载程序时,我必须断
我有以下汇编代码: __asm__ __volatile__ ( "1: subi %0, 1" "\n\t" "brne 1b" : "=d" (__count)
大家好! 我的 DIY 洒水器和鱼缸自动化的 AVR 取得了很好的进展,但我遇到了一个问题,这让我很烦恼。 哪个 if 语句在 AVR 上运行得更快?(在更少的时钟周期内)多少? if(temp_se
我见过的所有示例 AVR 程序都以如下代码开头: .org $0000 rjmp Reset ; ... Reset: ; Start of program 如果我不使用任何中
我正在使用avr-gcc 4.8.2对Atmel ATtiny13a微 Controller 进行编程。 这是我的C代码: #include #include int main(void) {
所以,我使用的是 ATMega168与 NerdKits使用两个中断 INT0 和 INT1 设置并连接一个 LCD。我想附上 Grove Heart Rate Monitor ,我已附加到 PCIN
我是一名优秀的程序员,十分优秀!