我们现在有一个 Github 讨论部分。当一个问题肯定是核心缺陷时,如果你创建了一个问题,那么你会减少修复它所需的时间,因为我优先考虑问题而不是赶上讨论。
这纠正了 2.6.x 中存在的许多错误
2.6.x 显着改进了串行闪存占用空间,同时添加了功能,线路可以将从设备从睡眠状态唤醒而不会损坏数据,等等,请参阅变更日志。
只能使用从 arduino.cc 下载的 Arduino IDE 版本,切勿使用从 Linux 包管理器下载的版本。包管理器通常有 Arduino IDE,但对其进行了修改。尽管他们总体上对 Arduino 或嵌入式开发一无所知,更不用说他们成功修改它所需的知识了。这些版本因这些不明智的修改引起的微妙但严重的问题而臭名昭著。不应期望该核心在此类版本上工作,并且不会为了修复来自包管理器的 IDE 版本而进行任何修改。
这是 Arduino 客户端中的一个错误。
1.8.13 和 2.x 之间的 IDE 版本出现了重大的新缺陷。然而,IDE 版本 1.8.2 及更早版本具有未修复的严重缺陷。我相信他们终于推出了 IDE 的工作版本,并且我相信最新版本能够正确安装我的核心。
在 megaTinyCore 2.6.0 之前,当您在 arduino 文件夹中手动安装 core 时,手动安装 megaTinyCore 会导致 IDE V1.8.14 由于此错误而崩溃。 1.8.14及更高版本的用户必须使用megaTinyCore 2.6.0版本。
我在速卖通上买了很多电子产品。对于中国公司制造的产品来说,这是一个很好的市场,而且大部分都是通用的,包括大量西方国家的个人无法以任何其他方式获得的组件(例如,最小订单是卷轴或类似的东西 - 如果你甚至可以找到一个)与无名中国芯片制造商合作的组件供应商)。对于西方主要制造商的最新半导体产品线来说,这并不是一个好地方,特别是在上述芯片历史性短缺的情况下。现代 AVR 设备在通过这些渠道可用时,经常被报告为假冒或有缺陷(例如 ATtiny412 认为自己是 416,可能无法正确执行开机复位)。就这一点而言,您可能不想在速卖通上购买任何 AVR 微控制器……如果您避免使用第三方 LGT8 芯片并留意使用 ATmega168p 的主板,那么组装板(如 Arduino Nano 克隆版)通常可以工作。而不是 '328p - 但有很多关于假微控制器作为裸芯片出售时的报道(我听说过假 ATtiny85,实际上被标记为假冒 ATtiny85) ATtiny13s;不仅仅是现代 AVR 被伪造)。关于这些假芯片的来源有很多有趣的理论,而 Microchip 在这个问题上完全保持沉默。
本文档最好在线查看(而不是在您喜欢的文本编辑器中打开 Markdown 文件),以便可以单击链接并显示内联图像,并且可能最重要的是,有时可以使表格正确呈现。同样,这个[文档可以在 github 上找到](https://github.com/SpenceKonde/megaTinyCore)(https://github.com/SpenceKonde/megaTinyCore)
旧版本无法在工具 -> 程序员菜单中正确处理程序员,这会随着安装的内核数量的增加而迅速降低用户体验。他们不合适。从 1.8.14 开始的最新版本(包括 1.8.17、1.8.18 和 1.8.19)可能会生成“恐慌:未找到主要版本”错误,因为它们无法正确解析 platform.txt。从 2.6.0 开始,我们在发布之前直接手动修改 platform.txt,所以这不是一个问题
当通过板管理器安装megaTinyCore时,会自动安装所需版本的工具链。所有 0/1/2 系列部件均受支持,无需额外步骤。在 2.2.7 之前,我们使用 Arduino7 版本的 avr-gcc(gcc 7.3.0 和 avrlibc 3.6.1)以及截至 2020 年 6 月的最新 ATpack。从 2.2.7 开始,我们开始使用我的 Azduino 版本的工具链,其中已更新所有新支持部件的 ATpack。 2.2.7 使用 Azduino3,2.3.0+ 使用 Azduino4,从 2.6.0 开始,我们使用 Azduino5(尽管它对我们没有任何好处,除了节省四分之一 GB 的 HDD 空间和 40mb 的下载带宽(如果同时安装) megaTinyCore 和 DxCore 通过董事会经理。
手动安装更加复杂 - 特别是如果您想要支持 2 系列;有关详细信息,请参阅安装指南。
适用于 tinyAVR 0 系列、1 系列和现在的 2 系列的 Arduino 内核。与“经典”tinyAVR 部件(由 ATTinyCore 支持)相比,这些部件具有改进的架构,具有改进的外设和改进的某些指令的执行时间(这些部件在两个方面与高级 AVR Dx 系列相似,以及megaAVR 0 系列芯片(如官方 Nano Every 和 Uno Wifi Rev. 2 上使用的 ATmega4809 - 尽管 Arduino 团队已尽最大努力限制它们)以低成本、小型化ATtiny 系列的典型封装。所有这些部件都具有至少一个硬件 UART、一个 SPI 和 TWI 接口(没有像 ATtiny85 那样的 USI 垃圾)、一个强大的事件系统、可配置的自定义逻辑、至少一个片上模拟比较器,一个令人惊讶的精确内部振荡器,对于 1 系列来说,是一个实际的 DAC 输出通道,对于 2 系列来说,是一个奇特的差分 ADC。
此外,tinyAVR 0/1/2 系列部件价格便宜- 最高端部件 3226 和 3227,具有 32k 闪存和 3k SRAM(相对于 Uno/Nano/ProMini 中使用的 ATmega328p 的 2k SRAM)运行数量略高于 1 美元 - 少于许多 8k 经典 AVR ATtiny 部件(“AVR 指令集,PIC 价格”)。所有这些部件的额定运行频率为 16 MHz 或 20 MHz(4.5-5.5v),无需外部晶体,并且内部振荡器对于 UART 通信来说足够准确。
这些使用 UPDI 编程,而不是像经典 ATtiny 部件那样的传统 ISP。请参阅下文了解更多信息。获得 UPDI 编程器很简单 - 您可以使用基于 328p 的经典 Arduino 作为使用 jtag2updi 的编程器 - 或者为了使用更便宜的硬件获得更好的结果,您可以使用任何 USB 串行适配器和电阻器(最好是二极管),使用随附的 SerialUPDI工具,或者您可以将 AVRdude 与 Microchip 编程器之一(其开发板上基于 mEDBG/nEDBG/EDBG 的编程器、Atmel-ICE 或 SNAP)或任何UPDI 编程工具模拟其中之一(据我所知,它们都支持 - 如果 avrdude 支持其中一个,而我的核心不支持,请打开一个问题让我知道!)。
这些部件支持串行引导加载程序 Optiboot_x(基于与经典 Arduino Uno 引导加载程序相同的代码库,但经过了很大改动)(0/1 系列支持目前已上线,2 系列预计在 5 月第一周提供) ;对新部件的调整是微不足道的),允许它们通过传统的串行端口进行编程。有关此内容以及相关选项的更多信息,请参阅下面的 Optiboot 部分。安装引导加载程序确实需要 UPDI 编程器。我在 Tindie 上销售的组装分线板可以预先引导加载(它们是根据需要引导加载的)。话虽这么说, 0/1 系列部件以及 14 引脚 2 系列部件的 Optiboot 用户体验有点令人失望,因为它们缺少可与通常的自动重置电路一起使用的硬件重置引脚当串行端口打开时自动重置到引导加载程序。您需要完全禁用 UPDI 编程(如果在初始引导加载后需要更改保险丝设置或引导加载程序,则需要 HV 编程器)或保持 UPDI 启用,但在通电后 8 秒内开始任何上传。 20 引脚和 24 引脚 2 系列部件支持“备用重置引脚”,使它们的行为更像传统的 Arduino。
UPDI 编程接口是用于编程(和调试 -通用编程和调试接口)的单线接口,用于 tinyAVR 0/1/2 系列以及所有其他现代 AVR 微控制器。虽然人们总是可以从 Microchip 购买专用的 UPDI 编程器,但当您使用 Arduino IDE 而不是 Microchip 的(极其复杂的)IDE 时,不建议这样做。关于 Microchip 官方程序员在 Linux 上出现问题的广泛报道。有两种非常低成本的替代方法来创建 UPDI 编程器,Arduino 社区在这两种方法上比官方编程器拥有更多的经验。
在 megaTinyCore 出现之前,有一个名为 pyupdi 的工具 - 一个简单的 Python 程序,用于使用通过添加单个电阻修改的串行适配器上传到配备 UPDI 的微控制器。但 pyupdi 无法在 Arduino IDE 中轻松使用,因此这不是一个选择。从 2.2.0 开始,megaTinyCore 引入了可移植的 Python 实现,这打开了许多大门;最初我们计划改编 pyupdi,但在其作者和几位 Microchip 员工的敦促下,我们将此功能基于 pymcuprog,这是一个“更强大”的工具,由 Microchip 开发和维护,其中包括相同的串行端口上传功能,仅没有性能优化。如果手动安装,您必须添加适合您的操作系统的 Python 包才能使用此上传方法(系统 Python 安装是不够的,也不是必要的)。
有关接线的信息,请阅读SerialUPDI 文档。
从 2.3.2 开始,随着性能的显着改进,以及使用二极管代替电阻器的接线方案的可靠性得到验证,并且考虑到 jtag2updi 固件的不稳定,现在这是推荐的编程方法。从此版本开始,编程速度提高了 20 倍,现在远远超过了 jtag2updi 的速度(通过 jtag2updi 进行编程的速度大致与通过“SLOW”速度选项上的 SerialUPDI 进行编程相当,57600波特率;正常的 230400 波特率版本程序大约比 SLOW 版本或 jtag2updi 快三倍,而“TURBO”选项(运行于460800 波特率,上传速度比普通版本提高约 50%。TURBO 速度版本仅适用于运行电压为 4.5v 或更高的设备,因为我们必须更快地运行 UPDI 时钟才能跟上(这也是不期望的)。与所有串行适配器兼容 - 这是提高性能的有意权衡),但它允许在 4 秒内上传和验证 32kB 草图。
正在迭代三种设计:双端口串行适配器,其中两个端口都是串行端口,双端口串行适配器,其中一个端口始终为 UPDI,以及单端口一个,其中一个开关用于选择模式,以及一个可选的附加板LED 指示调制解调器控制线路的状态。
这些将允许使用 SMT JST-XH 连接器或杜邦连接器 - 无论哪种方式都有 6 个引脚用于串行(FTDI 引脚排列如所标记)和 3 个引脚(用于 UPDI)。
所有这三个都能够提供 3.3 或 Vusb(标称值 5V),或者断开 Vusb 和 3V3 的电源,并期望目标设备的供电电压为 5.5V > Vdd > 1.8V。在这种情况下使用的逻辑电平将是所施加的电压。请注意,在双串行设备上,VccIO 电源轨是共享的!它们必须运行在相同的电压下,是同一设备,或者必须将适配器设置为为它们供电并断开电源。
根据适配器型号和操作系统的不同,需要不同的计时设置;然而,在 Linux/Mac 上,即使是 230400 波特率也需要进行设置才能避免失败,大多数适配器在 Windows 上会造成更大的时间损失,其中操作系统的串行处理速度足够慢,不需要任何延迟......
这里所说的“写延迟”是为了让页擦写命令执行完成;这需要非零时间。根据适配器、USB 延迟和隐式 2 或 3 字节缓冲区(它就像 USART,并且可能在内部实现为一个。到达的第三个字节无处可去,因为硬件缓冲区只有 2 字节深)可能是足以让它在没有明显延迟的情况下工作。或者,它可能会中途失败并报告“Error with st”。适配器的延迟超时越快,操作系统的串行处理越快,出现问题的可能性就越大。如果手动执行 prog.py,则由-wd
命令行参数控制。从 2.5.6 开始,此写入延迟更接近请求的实际时间(以毫秒为单位),以前它的粒度为几毫秒,而 1 就足够了,因此,它施加的惩罚是残酷的,特别是在视窗。
选型指南:
FTDI 适配器(FT232、FT2232 和 FT4232 等),包括在 eBay/AliExpress 上以 2 美元左右的价格出售的假冒适配器,在 Windows 上默认有 16 毫秒的长得令人难以忍受的延迟。即使我们为了限制必须等待的延迟时间而设置的长度,这也会将 2.2 秒的上传时间延长到超过 15 秒。您必须更改此设置才能获得可接受的上传速度:
一个可以由经典的 AVR Uno/Nano/Pro Mini 制作;廉价的 Nano 克隆是通常的选择,因为价格足够便宜,可以将其连接起来然后就这样离开。我们不再提供此过程的详细文档; jtag2updi 已弃用。如果您仍在使用它,您应该从工具->程序员菜单中选择 jtag2updi。这是我们之前推荐的选项。由于持续存在 jtag2updi 错误,以及它对很大程度上未维护的“avrdude”工具的依赖(该工具会在使用它进行的所有 UPDI 上传中插入虚假错误消息),因此不再建议这样做。
显然 Arduino 没有打包最新 avrdude 的 32 位版本。我定义了一个新的工具定义,它是 arduino18(最新)的副本,只不过它在 32 位 Linux 上引入版本 17,因为这是该平台可用的最佳版本。 arduino17版本无法正确支持使用某些Microchip编程工具进行上传。
目前,这仅用于最后几个版本,并且应该修复 avrdude 不适用于此平台错误。
请参阅此文档,涵盖所有现代 AVR
特征 | 0系列 | 1系列 | 1+系列 | 2系列 |
---|---|---|---|---|
闪光 | 2k-16k | 2k-8k | 16k/32k | 4k-32k |
针数 | 8-24 | 8-24 | 14-24日 | 14-24日 |
静态随机存储器 | 128b-1k | 128b-512b | 2k | 512b-3k |
TCD | 不 | 是的 | 是的 | 不 |
TCB | 1 | 1 | 2 | 2 |
模数转换器 | 1x10位 | 1x10 位 | 2x10 位 | 1x12 位 带PGA |
VREF引脚 | 不 | 不 | 是的 | 是的 |
交流电 | 1 | 1 | 3 | 1 |
事件 * | 3 陈 | 6 陈 | 6 陈 | 6 陈 |
覆铜板** | 2个查找表 | 2个查找表 | 2个查找表 | 4个查找表 |
*
除 2 系列 tinyAVR(以及所有非微型现代 AVR)外,事件通道分为两种类型 - 同步(针对系统时钟)和异步。并非所有生成器都可以使用同步通道,并且某些事件用户只能使用同步通道,并且通道列表不太一致且较多。这种疯狂的做法一有机会就被放弃了——甚至连 mega0 也取消了这种区别。
**
只有 2 系列和非小型部件可以根据 CCL 状态触发中断。
所有器件的大多数引脚上都提供模拟输入(PORTA 和 PORTB 0-1 和 4-5 上的所有引脚)。 1-series+ 上的第二个 ADC 也可以使用 PORTC 上的引脚作为输入(有关使用这些引脚的信息,请参阅模拟参考)。
这些是预算选项。尽管它们受到支持,但不建议使用。这些永远不会获得tinyAVR 1系列在16k时获得的“提升”,在任何配置中都没有第二个TCB,没有TCD,只有3个事件通道,其中没有一个可以承载RTC事件输出。这些器件与 1 系列一样具有 2 个 CCL LUT,并可在 14、20 和 24 引脚配置中配备高达 16k 的闪存(8 引脚器件仅为 4k)以及高达 1k SRAM。
这些具有 2k、4k 或 8k 闪存以及 128、256 或 512b 内存,就像 0 系列一样。他们没有第二个 ADC、三重 AC 配置或第二个 TCB,尽管他们有 TCD。
突然之间,在 16k 时,1 系列零件变得更加有趣。伴随更大的闪存的是一系列外围设备,似乎适合更大的芯片,无论是 16k 还是 32k,它们都具有 2k 的 SRAM。整个第二个 ADC 在 AVR 中是独一无二的。它似乎是许多功能的测试场,这些功能以精致的形式出现在 AVR Dx 系列上。定价似乎并未考虑到 16k 1 系列上极其优越的外设,
从上表中可以看出,2 系列几乎更像是一个侧级产品,而不是升级产品。他们有一个更好的 ADC,事件系统和 CCL 是“正常的”,并且他们有更多的 RAM,14 针部分可使用 32k 闪存(3214 显然是计划中的,但后来被取消了;它已经足够远了在被删除之前在 ATPACK 中存在一段时间)
如果现在还不清楚正确的选择,我已经写了一个简短的总结,说明您何时想使用哪个系列。
在其“megaavr”硬件包的官方 Arduino 板定义中,他们暗示 megaAVR 0 系列部件上的新架构(与tinyAVR 0 系列和 1 系列上使用的几乎相同)被称为“megaavr” “ - 这不是一个官方术语。 Microchip 使用术语“megaAVR”来指代任何“ATmega”部件,无论它具有旧式外设还是现代外设。没有官方术语来指代一个系列或另一个系列的所有 AVR 部件,一位 Microchip 员工甚至否认内部有这样一个术语。我不知道如何制造两套零件,每套零件之间有很多共同点,而与另一套零件却很少有共同点,没有人创造一个短语来指代它们中的任何一个。
在本文档中,在 2.0.2 之前,我们使用 Arduino 约定,尽管从那时起已经过去了一年多,我仍然不断寻找我称之为 megaAVR 的地方。如果您发现任何问题,请使用 github 问题报告此问题。请注意,术语avr
和megaavr
仍在内部使用(例如,在库中,标记给定库与哪些部分兼容,或者根据文件将运行的内容分隔文件的不同版本)。这将继续下去 - 我们必须坚持这一点,以便与 Arduino 团队从 Uno WiFi Rev. 2 和 Nano Every 的核心开始的兼容性。
无论如何,需要一些词来指代这两个群体,而 Microchip 没有提供任何词。在没有官方术语的情况下,我将 2016 年之前的 AVR 设备(带有 PORTx、DDRx 等引脚寄存器)称为“经典 AVR ”,将 Arduino 称为 megaavr 的设备称为“现代 AVR ”。还有一些部件的 I/O 模块在很大程度上更像经典的 AVR,但其指令集版本也明显较差,并且典型的闪存大小为 1k 或更小。它们使用 AVR 的 AVRrc(用于精简核心)变体,而大多数经典 AVR 使用 AVRe 或 AVRe+,而现代 AVR 使用 AVRxt。该核心不支持 AVRrc 部件,并且在不幸的情况下,我需要讨论这些非常令人失望的部件,我将它们称为“精简核心 AVR ”部件,因为这是它们的官方名称,尽管我有很多为他们提供更多丰富多彩的短语。建议任何设计都不要使用精简核心 AVR 。并不是说它们过时了,而是它们很糟糕。建议所有新设计使用“现代 AVR ”(具有新外设和AVRxt指令集的 AVR) - Ex 系列、Dx 系列、tinyAVR 0/1/2 或 mega0
新的tinyAVR 2系列的数据表 - 虽然数据表仅“涵盖”16k部件,但它们明确指出具有相同引脚数的部件之间在功能上没有差异(也就是说,不存在像16k/32k 1 系列),仅在具有不同引脚数的部件之间,并且仅由引脚数决定(即 24 引脚部件上的功能将在 14 引脚部件上使用,除非14针的没有它需要的引脚,而且是没有引脚就不能使用的东西)。 14、20、24针零件均列出4k、8k、16k、32k闪存;这些闪存大小选项分别配备 512、1024、2048 和 3072 字节的 SRAM(即 4k 和 8k 部件具有双倍的 SRAM),4/8k 部件获得 128 字节 EEPROM,较大的部件获得 256 字节14 引脚器件采用 SOIC 和 TSSOP,20 引脚器件采用(宽)SOIC、SSOP 等。像 1616 一样的小 QFN(这次他们也给了我们该封装中的 32k 部件,但祝你好运,得到一个,它到处都缺货 - 我无法获得一个)和 24 引脚与 1616 相同的 VQFN 3217.
TWI、SPI、USART0、AC0 未更改,NVMCTRL 也未更改(引导加载程序所需的更改仅与支持第二个 USART 有关)。时钟选项不变。 TCB0 和 TCB1 已升级到 Dx 系列中的版本:时钟关闭事件选项、级联以及用于 OVF 和 CAPT 的单独 INTCTRL 位(很好的补充,但与内核本身无关),并且所有部件都具有 TCB。我们现在有 4 个 CCL LUT 和 2 个定序器,而不是 2 个和 1 个 - 并且它们可以像其他具有 CCL 的部件一样触发中断(与tinyAVR 0/1 系列不同)。最令人兴奋的功能之一是,正如预期的那样,它们有第二个 USART(您听到的噪音是 ATtiny841 和 ATtiny1634 在角落里哭泣)。 PORTMUX 寄存器现在的命名与其他现代 AVR 类似 - 但我们并没有失去对每个 TCA WO 通道引脚的单独控制。 EVSYS 现在的工作方式就像在非微型 AVR-0/1 系列部件上一样(这是一个值得欢迎的变化 - 0/1 系列是奇特的,并且他们的 EVSYS 的一些不同之处被吸收了)。 TCD0、AC1/2、DAC0 和 ADC1 的 1 系列功能已消失。取而代之的是,ADC0 更加精美,几乎无法辨认,这是自收购以来发布的第一个具有真正差分 ADC 的新 AVR。 (可怜的'841又发出一声痛苦的哀嚎,它也有一个令人难以置信的奇特ADC,具有出色的差分选项,但与新的ADC相比,它看起来完全过时了)……从我已经发表的不同主题的帖子数量来看看来,我有一种感觉,差分 ADC 并不是您大多数愿望清单中的首选 - 但它却位于主要芯片客户的首选清单中,所以这就是我们所得到的。我们很快就需要一款合适的差分 ADC,而不是 Dx 系列上的 ADC。它真的非常非常奇特。见下文。
megaTinyCore 提供了analogRead() 实现,以及使用过采样和PGA 的更强大的功能(请参阅下面的模拟功能部分)。
哦,还有一件事...UPDI 引脚配置有旧选项 - UPDI、I/O 或复位...以及一个新选项:PA0 上的 UPDI,PB4 上的硬件 RESET 引脚! Optiboot 最终将成为一个可行且舒适的选择,至少对于具有 PB4 的部件而言,即不是 14 针部件。这也恰好是(如果我的 Tindie 商店销售额有任何迹象的话)最受欢迎的一种。
你觉得会有3系列吗?我不知道。 DD 和 EA 显然正在追随他们,并在tinyAVR 领域占据战略地位。我认为这个品牌被淘汰只是时间问题,就像他们在 megaAVR 0 系列之后对 megaAVR 所做的那样。这不一定是坏事:所有 Dx 和 EA 系列部件在引脚映射和行为方面都非常相似,这非常好。尽管它们将引脚分配给更多的外围设备,但它们的系统性较差。指导原则似乎是“不遗漏任何外围”。与 Dx 和 EA 系列的引脚映射形成对比,其中一切都遵循固定的总体规划。零件要么有要么没有给定的引脚,如果没有,则不具有可用的功能。在这两个广泛的群体中,我认为都有一个产品经理,他的工作就是对那些想对神圣引脚分配制定“例外”的工程师进行鞭打(因为这些例外不可避免地会激增,这也是我们最终蒙上眼睛的飞镖板引脚分配的原因)在经典的tinyAVR上)
tinyAVR 上的引脚编号很奇怪,这是 Microchip 的错 - 他们对端口内的引脚进行了奇怪的编号:它按顺序开始,除了 PA0 是 UPDI 并且通常不可用,然后 PORTB 的引脚以相反的顺序编号,然后 PORTC 回到与 PORTA 相同的逆时针编号。让我休息一下吧!因为传统上是使用引脚 0 作为第一个引脚,最后一个数字是如果不设置保险丝就无法使用的引脚,这会使芯片难以编程。我更希望能够从 A0 开始逆时针编号,而不破坏 Arduino 代码的不成文约定。有人可能会说我在引脚映射上做出了一个糟糕的决定——也许他们应该从 PA0(除非设置保险丝否则不可用,在这种情况下芯片很难编程)作为引脚 0 开始,然后按逆时针方向对引脚进行编号。但是,如果所有端口都按顺序排列,您仍然无法实现这种技巧,除非您将 PORTB 引脚向后编号。如果您能够摆脱所有引脚按顺序编号的期望(并且仅使用 PIN_Pxn 表示法),则可以实现显着的节省
我预测,在 2-4 年内,将会出现 AVR DA、DB、DD。 DU(USB 之一)、EA 和 D/E/F 系列器件的引脚数降至 8(或至少 14),以及具有 128k 闪存和新 ADC 的 64 引脚器件。没有其他任何品牌的 ATtiny。剩下的最大问题可能是他们是否会用总引脚数为 100 个(可能其中 80-88 个是 I/O)且闪存选项高达 256k 的现代 AVR 来取代 ATmega2560;这将带来三个问题 - 首先,过去 56 个 I/O 引脚不再剩下 VPORT 寄存器 - 低 I/O 空间已满,有 28 个 VPORT 和 4 个 GPIOR。他们将如何处理这 4 个额外的端口? (在 2560 上,它们只是访问速度较慢且没有单周期访问的二类端口。我对此有一些思考,以及附录 A 中可用操作码的可行性。第二,违反闪存中的 128k 屏障,您必须转到 17 位程序计数器 所有跳转都需要一个额外的周期,并且所有返回都需要一个额外的周期。 最后,如果保留 AVR DB ram 比率,则此“D X部分”。现在,256K的闪光灯将有32k的RAM回想一下,Progmem在DX上的工作原理 - 他们不能一直到32。24KRAM肯定是可能的,甚至可能是28没有SFR的空间,在相同的地址空间中。
我在Tindie Shop以及Baare Boards上使用监管机构,Updi标头和串行标头出售突破板。从我的商店购买有助于支持核心的进一步发展,这是开始使用Arduino使用这些令人兴奋的新部分的好方法。目前可以使用Attiny1624板,但是直到新修订的PCB设计从董事会返回以启用Autoreset上的Alt-Reset PIN,才能将20和24针零件作为组装板出售。还有一个14针板修订 - 认为它在很大程度上是化妆品。黄色焊料面膜必须走,因为在最后几批批次中的可读性似乎变得更糟。新板还标准化了一排针之间的0.6“间距,而不是当前的0.7”间距,因此您将可以将加工的销钉标头放在它们上,并将其插入宽dip插座或将它们与针对该行间距进行优化的原型板一起使用。组装的0系列板正在停止,一旦售罄,就不会被补货。一旦有32k的零件,16k 2系列的零件也会发生同样的情况。
在2系和EA系列的ADC是现代AVR时代在AVR上发布的最好的ADC。除了这两个。最接近的比较是经典的AVR,它具有具有顶级功能的差异ADC(T841,Mega2560和(令人惊讶的是)T861是最强大的竞争对手)。虽然在经典的AVR时代某些部分吹嘘的是疯狂的100倍和200倍,但对我来说,放大的内容中的多少是噪音(考虑到我公认使用差异ADC的经验有限的经验,我要说的是“大概大部分,如果您让我设计硬件,我不知道模拟!”)。这个新的ADC当然具有很高的能力,具有真正的差异能力(与DA和DB系列不同),并且迄今为止其他任何现代AVR上可用的任何东西都抬高了头和肩膀。可编程增益放大器是一种新功能,人们能够摆脱模拟测量的壮举是什么样的;当然,这似乎很有希望。了解使用PGA以1倍增益,与不使用PGA的差异以及这样做的益处和缺点之间的差异将非常有趣。 (在一般情况下,Microchip将由一份文档进行良好的服务,该文件讨论了如何为任务选择正确的ADC配置;我已经对Microchip和我交谈的人提出了这种关注,并表示这是一个很高的优先级;而这是一个很高的优先级;而这种情况得到了极大的改善,看来DOC组被专门指示不要对任何类型的任何实际具体建议。
出于过度采样和拆卸的目的增加了1024个样本的积累是一个受欢迎的补充,尽管这也有可能低估了偏移误差的幅度和相关性。 (取1024个样本(所有均具有给定的偏移错误),然后删除总和以产生17位ADC测量,可以轻松地想象任何错误都将局限于最低的几个位。但是,如果错误是,在单个测量中说5 LSB,当您累积1024个样品并脱节时,您的偏移误差为160,很容易看到它,并认为它是信号而不是噪声。
带有新ADC的第一个完整尺寸(非小)芯片可在28-48 PIN包中提供,最多可容纳64K闪光灯。通常有人猜测是否会有什么变化从两个系列变为EA系列:似乎答案是,一个令人困惑的旋钮被删除了,并且自动签名砍伐以进行累积的测量(
D Type D计时器仅在默认的PWM PIN设置上的20/24 PIN 1-SERIES零件上用于PWM。在较小的零件上,它不会让我们增加PWM引脚的总数。仅WOC和WOD引脚(分别在PC0和PC1上)上没有TCA驱动的PWM。因此,由于AnalogWrite()不支持通过关闭拆分模式(例如16位PWM)或通过使用D Type D Timer(例如调整频率)来增强的任何功能,因此会更糟,因为它需要额外的空间来存储例程以从两种类型的计时器而不是一个类型的PWM打开和关闭PWM。这在较小的闪光零件上不可忽略。它的订单为600个字节。 150对于DigitalWrite(),对于AnalogWrite(),如果曾经在TCD PWM引脚上调用这些()。在这种情况下,优化器应该能够优化这些功能的部分,只要这些功能与这些功能使用的引脚不包括任何TCD PWM引脚。请注意,优化器将独立考虑它们,也就是说,DigitalWrite()将包含代码以关闭TCD PWM,如果它与PIN一起使用,该PIN使用TCD用于PWM,无论您是否曾在该引脚上调用AlaigWrite()。
与几乎所有其他AVR不同(我可以想到3个示例,其中只有一个是“奖金”不是“ unbonus”),基于家庭中零件的闪光灯,还有其他“奖励”功能。 16K和32K版本(仅)具有一些额外的功能(似乎也没有考虑到定价) - 它们都有2K RAM,无论是16K还是32K,它们都有3个模拟比较器(包括窗口模式选项),第二个 - 迫切需要的 - B型计时器 - 最奇怪的是,它们具有第二个ADC,仅在销售频道对应的销钉中有所不同!
与经典的AVR不同,在这些部分上,闪光灯映射到与其余内存的地址空间相同的地址空间。这意味着不需要直接从Flash读取pgm_read_*_near()
。因此,编译器会自动将所有声明const
的变量放入progmem中,并适当地访问它 - 您不再需要明确将其声明为Progmem。这包括引用的字符串文字,因此不再需要f()宏,尽管为了保持与某些第三方库的兼容性,但F()仍然声明其参数progmem。
但是,请注意,如果您明确声明可变的progmem,则必须像在经典AVR上一样使用pgm_read
函数来读取它。当变量在带有内存映射闪光灯的零件上声明变量时,指针被偏移(地址相对于闪存的开始,而不是地址空间的启动);使用pgm_read_*_near()
宏时,也会应用相同的偏移量。请注意,声明progmem并使用pgm_read_*_near
访问功能的内容虽然效果很好,但较慢,并且浪费了少量的闪存(与简单地声明变量const相比);对于2.1.0和更高版本的F()宏的F()宏也是如此(在2.1.0之前的一段时间内, F()
什么也没做 - 但这引起了第三方库的问题)。作者坚持认为,问题与核心有关,而不是库,我的选择是接受较低的效率,或拒绝我的用户访问流行的库)。使用F()
宏可能是与某些第三方库的兼容(迫使F()
向我们返回的具体情况并非如此)可能是必需的f() - AS-NOOP代码,因此它们少了几个字节)。
汽车版本也应起作用。您必须始终在这些零件上选择16个MHz衍生的时钟速度。它们不支持20 MHz操作,不应使用调谐的时钟选项。
现在,我们可以在这里谈论MegatinyCore如何暴露这一切。我们将从如何参考PIN以获取最佳结果的问题开始,然后转到核心功能,菜单选项,然后再以一系列链接到文档的链接,并提供有关各种子系统的详细信息。
如何指代Alagread()和DigitalRead()的PIN(尤其是在非标准硬件上)的简单问题一直是Arduino用户混淆的持续来源。我认为,大部分责任都取决于Arduino团队(以及在他们面前的布线作者)所做的关于针刺的决定的决定;将某些引脚称为“模拟别针”使人们认为这些销钉不能用于数字操作(它们可以更好地认为是“具有模拟输入的销钉”,例如有“可以输出PWM”的“销钉”)。传统上销售销钉的事实进一步使水混淆了。对于非标准的经典AVR零件,多年来,由多个作者创建的多个不兼容的“ PIN映射”通常使事情变得更糟以这种方式混乱,某些部分具有三个完全不同的引脚映射,在至少一种情况下,其中一种替代映射是一部受魔鬼启发的纯粹邪恶的作品,不需要额外的查找表即可将模拟销转换为数字引脚)。
该核心使用一个简单的方案来分配Arduino引脚编号:PIN从最接近VCC的I/O引脚开始编号为引脚0,然后逆时针继续执行,然后跳过(主要是)不可用的Updi Pin。然后将UPDI PIN分配给最后一个引脚号(如上所述,即使不是将其设置为GPIO,也可以读取Updi Pin(模拟和数字读取工作)。我们建议这样做是最后的度假胜地:Updi Pin在未设置为GPIO PIN时始终启用其引体式,并且看起来太像Updi启用序列的信号会导致不希望的操作。
为了防止所有有关引脚身份的混乱并消除歧义,我们建议使用PIN_PXN符号来指示引脚,除非您使用具有不同数字或名称的开发板上打印的引脚。这将使您的代码的可移植性最大化到其他类似的硬件,并使您在相关数据表中使用的引脚上查找信息,如果有必要的话。
这是指参考#defines
的推荐方法,其中PIN_Pxn
的形式为x, x
是a,b或c,而n
为a number 0-7-(不要与下面描述的PIN_AN定义相混淆)。这些只是解决了相关PIN的数字引脚编号 - 它们不会经历其他代码路径或其他任何内容。但是,它们在编写代码方面具有特殊的实用性,这些代码与大多数外围设备一样,与与某些引脚相关的外围设备(通过端口)链接的外围设备。文档中的几个演示代码利用了这一点。直接的端口操纵也是可能的 - 实际上,它可以使用几种强大的其他选项 - 请参阅直接端口操纵。
PIN_Pxn
不是Pxn
,而不是PIN_xn
这些意思是不同的东西!
当单个数字用于引用PIN时 - 在文档中或您的代码中 - 始终是“ Arduino Pin Number”。这些是橙色(适用于Analogread())和蓝色(针对未销钉的销钉的销钉)的引脚编号。参考引脚的所有其他方法均定义为相应的Arduino Pin编号。
核心还提供An
和PIN_An
常数(其中n
是0到11的数字)。与官方核心一样, PIN_An
被定义为与模拟通道共享的PIN的数字引脚编号,这些n是指ADC0通道编号。这个命名系统类似于许多经典的AVR核心上使用的命名系统,但是在这里,它们只是#DEDINES作为相应的Arduino Pin编号。如果您需要在数字引脚上获取模拟通道编号,请使用digitalPinToAnalogInput(pin)
宏 - 但是,只有在编写高级ADC库时才需要它。
这些零件(嗯,至少是1/2系列 - 0系列是预算选项,除了它们未能缩小预算,而且它们只有几美分便宜)提供了一种出色的工具箱和强大的外围设备;高端与经典的Megaavr零件相当或更好 - 价格为Tinyavr。与我的其他核心一样,MegatinyCore设计的指导原则之一是允许受支持的部分发挥其全部潜力 - 或在Arduino的局限性内尽可能接近它。该部分(非常大)涵盖了这些部分的特征以及它们如何被MegatinyCore揭露,以及核心本身的特征。这个(非常大)的部分试图覆盖每个特征区域。如果您想使用一些芯片功能并遇到麻烦,请尝试找到正在使用的功能!
我们对超频零件的电压或温度范围没有任何要求 - 我们声称的是,我们至少在室温下以这种速度工作的芯片中的至少有一个芯片,在5V时运行特定的草图。您的里程预计会有所不同,但通常使用F规格与N或U规格部分更好。
重要的 - 在选择任何调整选项之前,请阅读有关调整的信息!
有关这些时钟速度的更多信息可以在时钟参考中找到
显示的电压是制造商规格保证工作的电压(除非按下操作温度范围的边界,否则这些零件通常会做得更好(通常在32 MHz和5V @室温下,即使从内部振荡器则可以工作; 0 /1系列同样,如果电源为稳定的5.0-5.5V,则通常在32 MHz的情况下使用32 MHz。
当草图通过UPDI上传时,无需采取任何措施来设置OSCCFG
保险丝。当通过Optiboot上传时,将无法更改保险丝,因此在燃烧引导加载程序时选择的任何选择是所使用的,并且只有“燃烧启动加载程序”或通过UPDI上传素描才能改变。
除非选择“调谐”选项,否则所有内部振荡器时钟速度选项都使用出厂默认校准,在这种情况下,按照调整参考中的记录进行了调整校准。这可用于在20 MHz的Optiboot芯片上进行16 MHz操作,反之亦然。
有关制造商的速度等级的更多信息,请参见速度等级参考。请注意,这些是保证它可以正常工作的电压和时钟速度。这些零件旨在适合在应用程序中使用,在某种程度上出乎意料的故障可能会对人或财产构成危害(例如汽车,工业设备,飞机,核反应堆 - 如果零件发生故障,人们可能死亡)和我仅出于相反的原因,也相信军事应用具有相似的可靠性要求。典型的爱好用户将在稳定问题的潜力上更加放松,崩溃只不过是一个麻烦,而且延长温度范围零件的极端远远超出了我们所需要的。假设板上有防水涂层,则n等级零件应能够在一锅沸水中每个速度等级起作用。那只是n-spec。 F-Spec应该好至125!
已经确定,延长的温度零件越过超频,这是有道理的。预计将在125C下以20 MHz运行的部分在室温下以32 MHz运行的机会比仅在105C下以20 MHz运行的机会更高
从2.4.0版开始,我们现在提供“官方微芯片板”选项。除了将LED_BUILTIN
定义为具有LED在该板上而不是A7的PIN之外,并定义一个宏PIN_BUTTON_BUILTIN
定义为带有用户按钮的PIN并用非非载荷“上载”,这无需做任何特别的事情。 -Optiboot版本始终使用板载程序员/调试器;工具 - >程序员将仅用于“ Burn Boot Loader”和“使用程序员上传”。对于Attiny416 Xplained nano,它还选择了使用替代引脚的引导加载程序的版本,该销售端端端口 - 它不会自动使用usart0的备用销钉,就好像您完成了serial.swap(1)一样 - 支持串行引脚的默认交换的功能将在以后的更新中进行,以及PINSWAP机制基础机械的其他一些更改,这也有望减少闪光使用。
如上所述,这些可能无法在32位Linux平台上正确工作。这是我无法控制的;我不构建Avrdude二进制文件AMD,我也没有承担该任务。我已经太多了。
blink()
在Xpl的Mini和Xplained Pro上会闪烁更多?两者都有相同的attiny817!它们如何与众不同?
出于同样的原因,如果将闪光更改为使用PIN_PC0
而不是Xplained mini上使用的PIN_PB4
:PC0,则需要更多的闪光灯,而Xplained Pro使用的PB4则不是。由于这是使用DigitalWrite()使用的唯一PIN,因此编译器可以免费优化该PIN上DigitalWrite()不需要的任何内容,包括在支持PWM的PIN上关闭PWM输出的功能。 。如果digitalwrite()也用于支持两个设备上的PWM(导致较高的闪光使用结果)或DigitalWrite()替换为DigitalWriteFast(),那么差异就会消失。 't将其称为销输出PWM)。
每当使用UPDI程序员上传代码时,所有可以“安全”设置的保险丝(如,如果没有砖头的风险,或者如果无法访问HV程序员,则可以将董事会进行砖块),并且具有任何内置配置选项将设置。因此,除了注意到,行为始终将与所选工具菜单匹配。总而言之,这些处理如下:
WDTCFG will not be changed - it is not configured by megaTinyCore except to reset it to the factory default when doing "burn bootloader".
BODCFG will not be changed - not safe, you could set the BOD level to 4.3 on a 3.3v system, and then it would need to get > 4.3v applied to reprogram it. If it is on the same circuit board as parts that would be damaged, this is a difficult situation to recover from.
OSCCFG will be set
TCD0CFG will not be changed - it is not configured by megaTinyCore except to reset it to the factory default when doing "burn bootloader".
SYSCFG0 will not be changed - not safe
SYSCFG1 will be set
APPEND will not be changed - it is not configured by megaTinyCore. There is insufficient demand to justify the development effort.to make use of this as DxCore does
BOOTEND will be set
LOCKBIT will not be changed - it is not configured by megaTinyCore; supporting the lockbits presents several additional complications, and commercial users with need of this facility are unlikely to be using the Arduino IDE to program production units.
BODCFG
并不安全,因为将其设置为高于板的电压,并使板将其“砖”“砖”板“砖”,直到提供更高的操作电压为止;如果将其焊接到与无法忍受这些电压的设备相同的PCB上,这可能会特别尴尬。
SYSCFG0
不安全,因为这是RSTPINCFG
所居住的地方。除了通过HV Updi编程外,更改此操作可能会使董事会无法编程,而且并不是每个人都有HV Updi程序员。将来,如果/当保证可以选择作为程序员选择的HV Updi功能的程序员(即,可以使用仅与HV程序员一起使用的工具 - >程序员选项)将在使用时自动设置此保险丝那个程序员。
结果,在2.2.0和更高版本中,您不再需要“燃烧启动加载器”才能在使用UPDI上传时在16 MHz衍生和20 MHz衍生的速度之间切换
该核心始终使用链接时间优化来减少闪光使用 - 支持TinyAVR 0/1/2系列零件的所有版本也支持LTO,因此无需像AttinyCore那样使其可选。这是在引入时的代码方面的巨大改进,通常以5-20%的订单!
这些部分都有大量的模拟输入 - DA和DB系列具有多达22个模拟输入,而DD系列的每个引脚都在不用于驱动HF晶体的每个引脚上输入模拟输入(尽管Portc上的PINS是仅当关闭MVIO时才支持)。可以像在正常的AVR上一样用analogRead()
读取它们,我们默认为10位分辨率。您可以使用analogReadResolution()
更改为完整的12位,并使用增强的分析函数自动进行过度采样,衰减的读数,以进行更高的分辨率并进行差异测量。 1.024、2.048、4.096和2.5V中有4个内部电压参考,加上对外部参考电压的支持(当然是VDD)。 ADC读数的速度比经典的AVR快3倍,如果您的测量值是低阻抗,或者将采样时间扩展到了一个因素,则可以将速度再次加倍,以读取非常高阻抗来源。这在模拟参考中详细介绍。
DX系列零件具有10位DAC,可以生成真实的模拟电压(请注意,这提供了低电流,并且只能用作电压参考或控制电压,不能用于为其他设备供电)。这会在0和选定的VREF
之间产生电压(与Tinyavr 1系列不同,可以是VCC!)。通过DACR reference()
函数设置DAC参考电压 - 将其传递上述ADC部分中列出的任何ADC参考选项(包括VDD!)。在DAC PIN(PD6)上调用analogWrite()
,以将DAC输出的电压设置(以8位模式使用)。要关闭DAC输出,请在该PIN上调用digitalWrite()
或turnOffPWM()
。
可能还有其他选项可以在EA系列上配置DAC。
有关全部详细信息,请参见ADC和DAC参考。
使用An
常数进行模拟引脚 - 建议的做法是仅使用数字引脚号,或者更好,或者在调用analogRead()
时使用PIN_Pxn
符号。
与经典AVR相比,要重置的选择要多,包括是否以某种方式挂起代码。看门狗计时器只能重置(使用RTC和PIT进行定时中断)。
请参阅重置和看门狗(WDT)参考和核心辅助库MegatinyCore
该核心添加了许多新功能包括快速数字I/O(根据编译时间已知的数字i/o(1-14个时钟,以及2-28个字节的闪存(必须在编译时知道________Fast()
函数的编译时间,并且用于配置硬件具有pinConfigure()
所有PIN设置。
请参阅改进的数字I/O参考。
所有0/1系列零件都有一个硬件串行端口(UART或USART);两个系列零件有两个。它的工作原理与官方Arduino董事会上的一个完全一样,除非没有自动排量,除非您是通过将Updi Pin纳入RESET(需要HV-UPDI或Optiboot Bootloader来上传代码)或设置的。如本文档中其他地方所述,上述一个“ ersatz重置销”。有关串行引脚的位置,请参见PINOUT图表。
在将零件放入睡眠模式或以其他方式禁用传输能力之前,请确保通过调用Serial.flush()
完成将数据发送到缓冲区中的数据,否则序列端口将发出损坏的字符和/或失败完成消息的传输。
有关选项的完整列表,请参见串行参考。截至2.5.0,支持串行硬件可以执行的几乎每种类型的功能都得到支持,包括RS485模式,半双链(通过LBME和ODME),甚至是同步和主SPI模式,以及2.6.0以及2.6.0将添加Autobaud,即使不是很有用。
所有这些零件都有一个硬件SPI外围设备。它的工作方式与使用SPI.H库在官方Arduino板上的官方一样工作。有关这些引脚的位置,请参见PINOUT图表。在8针零件上,SS PIN的唯一选择是PA0(UPDI/RESET PIN);不过,这并不重要,因为与官方图书馆一样,这仅作为主人运作,而SS PIN仅在可能充当奴隶时才使用。
在除14针零件以外的所有零件上,SPI引脚都可以移动到替代位置(注意:在8针零件上,SCK引脚无法移动)。这是使用SPI.swap()
或SPI.pins()
方法配置的。他们俩都达到了同一件事,但是在指定要使用的引脚组的方式上有所不同。在调用SPI.begin()
之前,必须调用这一点。
SPI.swap(1)
或SPI.swap(0)
将将映射设置为备用( 1
)或默认( 0
)引脚。如果这是一个有效的选项,它将返回true,如果不是这样,则false(您不需要检查此问题,但在开发过程中可能很有用)。如果指定了无效的选项,则将设置为默认选项。
SPI.pins(MOSI pin, MISO pin, SCK pin, SS pin);
- 这将将映射设置为具有指定引脚的任何映射。如果这不是有效的映射选项,它将返回false并将映射设置为默认值。这比SPI.swap()
使用更多的闪光灯,因此该方法是首选的。 SS pin
参数是可选的,因为当充当SPI主人时没有使用PIN,并且该图书馆或官方SPI.H库支持充当奴隶。
当可以确定传递给SPI.swap()
或SPI.pins()
参数在编译时间(最常见的是,当参数是常数(几乎总是它们总是))时,核心将生成一个编译,该效果的错误。这旨在帮助防止此类可检测的问题需要在硬件上调试时间。
该核心禁用SS PIN,这意味着可以将“ SS”引脚用于您想要的任何目的,并且只有在制作SPI奴隶时才与PIN相关(这要求您自己实施与SPI外围的互动火箭科学或任何东西)。在经典的AVR上,如果SS是输入,并且启用了SPI,则它是SS PIN,如果它变低,它将将设备切换到从属模式(SPI.H将无法运行,直到将设备运行到Master中模式,这不是自动完成的)。
所有这些零件都有一个硬件I2C(TWI)外围。它提出了与标准Arduino实现兼容的API,但是在对多个从属地址的增加支持,回答一般的呼叫地址,最令人兴奋的是 - 同时使用的主和从属操作! (2.5.0中的新)。
有关完整的描述和详细信息,请参见Wire.H文档。硬件I2C是更复杂的外围设备之一。最近,Wire有很多热门新的增强功能检查了一下。
核心通过标准analogWrite()
函数提供硬件PWM。在8针零件(412、212、402、204)上,有4个PWM引脚。在所有其他零件上,除了具有20或24个销钉的1系列零件外,有6个PWM引脚可用,全部由计时器A(TCA0)驱动。 20和24引脚1系列零件有两个由TCD0驱动的销钉。这两个系列显然将TCD0交换为第二个串行端口和一个超级美食ADC-这些零件也有6个PWM引脚。 B型(TCBN)计时器不能用于其他PWM引脚 - 它们的输出引脚与计时器A可用的引脚相同,并且通常太有用了,无法证明使用整个TCB的合理性。但是,如果您需要以不同的频率生成PWM,则可以将它们接管,尽管预先计算机与计时器类型也限制了此用途的事实。有关引脚支持PWM的列表,请参见PINOUT图表。
从2.6.8开始,添加了一个工具子菜单以使您从合理的有用的PWM映射中进行选择,并且(在1系列上)禁用TCD PWM以节省闪存。
请注意,所有零件上的TCA0(A型计时器)均由启动时的Core配置,以在拆分模式下操作,以支持使用analogWrite()
可能提供的最多的PWM引脚。从2.2.x版本开始,已经添加了takeOverTCA0()
函数,可以调用该功能以指示核心不写入TCA0-Registers,也可以对TCA0进行任何特定模式或行为。 analogWrite()
不会生成PWM,除非在20/24针零件上由TCD0驱动的引脚上, digitalWrite()
如果要为其他目的重新配置TCA0,请将其关闭,请参阅下面的指南和“硬重置”指南”。计时器返回到库存配置。
3216、1616、816、416和3217、1617和817具有由计时器D驱动的两个额外的PWM引脚(X17上的X16、12和13和13)。计时器D是异步(异步)计时器,如果不简短停止计时器,就无法启用或禁用输出。这会导致另一个PWM引脚(如果当前输出PWM)的短暂故障,并且需要更长的时间 - 尽管该小故障的持续时间低于1。 If TCD is used as the millis timer - which is the default on any part that has a type D timer (in order to keep the timers that are more readily repurposed available - TCD0 is not an easy peripheral to work with), this will result in millis()
losing a very small amount of time (under 1 us) every time PWM is turned on or off on a TCD pin.
As of 2.2.0, analogWrite()
of 0 or 255 on a TCD-driven PWM pin does not disconnect the pin from the timer - instead it results in a constant HIGH
or LOW
output without disconnecting the timer (use digitalWrite()
for that )。 This means that analogWrite(PIN_PC0, 0)
or analogWrite(PIN_PC1, 0)
can be used to connect the timer to the pin without outputting PWM (yet) - doing this on both pins prior to setting any other duty cycles would allow one to ensure that no glitch of any sort occurs on the other TCD0 pin when the second pin is connected to it. Only digitalWrite()
or turnOffPWM()
will disconnect the timer from the pin . When outputting a HIGH
in this way, the pin is "inverted"; this means that digitalRead()
on it will return 0, not 1 (if you're digitalRead()
'ing a pin, which you have set to output a constant HIGH
, using analogWrite()
, and it's one of those two pins, it will read LOW
. However, if you are using digitalRead()
on a pin that you've set to output a constant value, you may be doing something wrong in general.
Because TCD is async, and can run from the unprescaled internal oscillator, that means you can lower the system clock frequency without affecting the speed of the PWM. While there is a difference in PWM frequency between 16-MHz derived and 20-MHz derived clocks, there is no change in frequency for different system clock speeds for the TCD-controlled pins (the TCA-controlled pins will vary by a factor of two) The exception to this is when TCD0 is used as the millis/micros timing source at 1 MHz - running at full speed there resulted in spending an unreasonable fraction of runtime in the millis()
ISR (tens of percent of the time).
TCD0 is used for millis()
/ micros()
by default on parts that have it. Be aware that this does have a small flash penalty, so you can save flash by switching to use TCA or a TCB as the timer. That will also make micros()
return faster. There is a shortage of timers on most of these parts, and I have not seen anyone talking about or posting code that reconfigures the TCD. Meanwhile everyone seems to be reconfiguring the TCA and many libraries need a TCB. These factors have been the impetus for making TCD0 the default for millis()
/ micros()
: it is least likely to directly interfere.
On some versions of megaTinyCore prior to 2.2.0, PWM on the TCD0 pins was entirely broken.
For general information on the available timers and how they are used PWM and other functions, consult the guide: This also covers the PWM frequencies that these timers will give you at various system clocks. Timers and megaTinyCore
Support for tone()
is provided on all parts using TCB0, unless TCB1 is present and TCB0 is set as millis()
source. This is like the standard tone()
function. Unlike on some classic AVRs, it does not support use of the hardware 'output compare' to generate tones; due to the very limited PWM capabilities and restricted prescaler selection for the TCB timers, this is not practical. See caveats below if using TCB0 or TCB1 for millis()
/ micros()
settings. See the timer reference for more information
tone()
can only play a tone on one pin at a time. In theory you can play one tone per Type B timer, simultaneously, without anything more exotic than what tone()
does now other than adding a capability to manage the multiple pins. It is my opinion that those belong in a library, not the core. See comments in tone.cpp
for some thoughts if you want to implement something like that - I'd be happy to give more thoughts if you have questions.
megaTinyCore provides the option to use any available timer on a part for the millis()
/ micros()
timekeeping, controlled by a Tools submenu. It can be disabled entirely if needed to save flash, allow use of all timer interrupts or eliminate the periodic background interrupt. By default, TCD0 will be used by on parts that have one - otherwise TCA0 will be used (in versions prior to 1.1.9, TCA0 was used by default on parts that could output PWM with TCD0 on pins not available for TCA0 PWM). All timers available on the parts can be used: TCA0, TCD0 (on parts that have it), TCB0, TCB1 (where present) and the RTC. Many of these - particularly the non-default options, involve tradeoffs. In brief, TCA0 is a very versatile timer that users often want to reconfigure, TCD0 loses a small amount of time when PWM is turned on or off on the two TCD0 PWM pins (10,11 on 20-pin parts, 12,13 on 24-pin parts), TCB0 conflicts with Servo
and tone()
on parts that don't have TCB1, and when the RTC is used micros()
is not available at all because the clock isn't fast enough. With these limitations in mind, the timer selection menu provides a way to move millis()
/ micros()
to the timer most appropriate for your needs.
For more information, on the hardware timers of the supported parts, and how they are used by megaTinyCore's built-in functionality, see the Timers and megaTinyCore Reference .
2.3.0 fixed a long-standing (though surprisingly low impact) "time travel" bug.
millis()
If the RTC is selected as the timer for millis()
timekeeping, micros()
will not be available. Additionally, this timer will be configured to run while in STANDBY sleep mode. This has two important consequences: First, it will keep time while in sleep. Secondly, every 64 seconds, the RTC overflow interrupt will fire, waking the chip - thus, if you are using the RTC for millis()
and putting the part into sleep, you should declare a volatile global variable that you set in the ISR that is supposed to wake the part, eg volatile boolean ShouldWakeUp=0;
, set it to 1 in the ISR, and when you put the ATtiny to sleep, have it check this immediately after waking, going back to sleep if it's not set, and clearing it if it is set, eg:
void GoToSleep () {
do {
sleep_cpu ();
} while (!ShouldWakeUp)
ShouldWakeUp= 0 ;
}
This functionality will be made easier to use via ModernSleep when that library is available.
This board package also supports using an external 32.768khz crystal as the clock source for the RTC (not supported on 0-Series or 8-pin parts - not our fault, the hardware doesn't support it). If this is used, make sure that the crystal is connected between the TOSC1 and TOSC2 pins (these are the same as the TX and RX pins with the default pin mapping - very convenient right?), that nothing else is, that no excessively long wires or traces are connected to these pins, and that appropriate loading capacitors per crystal manufacturer datasheet are connected (and that it's not a full moon - I found the 32k crystal to be extremely uncooperative. To reduce power usage, they try to drive the crystal as weakly as they can get away with, which in turn makes it more susceptible to interference.
Yes, you can use an external oscillator for the RTC, at least on 1 and 2 series parts. When it's an oscillator not a crystal, it can be fed to either TOSC0 or EXTCLK; better support for this will come in the future. Note that while TOSC0 won't let you run the RTC at widlly faster speeds. EXTCLK will.
printf()
Support for "printable" Class Unlike the official board packages, but like many third party board packages, megaTinyCore includes the printf()
method for the printable class (used for UART serial ports and most everything else with print()
methods); this works like sprintf()
, except that it outputs to the device in question;例如:
Serial.printf( " Milliseconds since start: %ld n " , millis());
Note that using this method will pull in just as much bloat as sprintf()
and is subject to the same limitations as printf - by default, floating point values aren't printed. You can use this with all serial ports You can choose to have a full printf()
implementation from a Tools submenu if you want to print floating point numbers, at a cost of some additional flash.
printf()
and Variants Thereof Have Many Pitfalls There are a considerable number of ways to screw up with printf()
. Some of the recent issues that have come up:
printf()
- printf()
bugs are a common cause of software bugs in the real world. Be aware that while you can use F() on the format string, there are no warnings for invalid format strings in that case ; a conservative programmer would first make the app work without F() around the format string, and only switch to F() once the format string was known working.From cplusplus.com:
The length sub-specifier modifies the length of the data type. This is a chart showing the types used to interpret the corresponding arguments with and without length specifier
(if a different type is used, the proper type promotion or conversion is performed, if allowed): Strikethrough mine 'cause that don't work here (and it's not my fault nor under my control - it's supplied with avrlibc, and I suspect that it's because the overhead of implementing it on an 8-bit AVR is too large). When incorrect length specifiers are given (including none when one should be used) surprising things happen. It looks to me like all the arguments get smushed together into a group of bytes. Then it reads the format string, and when it gets to a format specifier for an N byte datatype, it grabs N bytes from the argument array, formats them and prints them to whatever you're printing to, proceeding until the end of the format细绳。 Thus, failing to match the format specifiers' length modifiers with the arguments will result in printing wrong data, for that substitution and all subsequent ones in that call toprintf()
.
The table below comprises the relevant lines from that table - many standard types are not a thing in Arduino (their original was several times longer, but including that mess would just complicate this discussion.
长度 | 迪 | uox X | f F e E g G a A | c | s | p | n |
---|---|---|---|---|---|---|---|
(没有任何) | 整型16 | uint16 | 漂浮 | 整数 | 字符* | 空白* | int* |
呵呵 | int8 | uint8 | 字符* | ||||
我 | 整型32 | uint32 | int32_t* |
Notice that there is no line for 64 bit types in the table above; these are not supported (support for 64-bit types is pretty spotty, which is not surprising. Variables of that size are hard to work with on an 8-bit microcontroller with just 32 working registers), and using uint64's is something you should try to avoid, similar to driving on the wrong side of the road, flying kites during thunder storms, or drinking bleach. While all have been suggested (Europe is really persistent about the side of the road; As far as I'm concerned, it comes down to physics; mirror image symmetry i. This applies to all versions of printf()
- the capability is not supplied by avr-libc.
There are reports of memory corruption with printf, I suspect it is misunderstanding of above that is actually at hand here.
printf()
Implementation A Tools submenu lets you choose from three levels of printf()
: full printf()
with all features, the default one that drops float support to save 1k of flash, and the minimal one drops almost everything and for another 450 bytes flash saving (will be a big deal on the 16k and 8k parts. Less so on 128k ones). Note that selecting any non-default option here will cause it to be included in the binary even if it's never called - and if it's never called, it normally wouldn't be included. So an empty sketch will take more space with minimal printf()
selected than with the default, while a sketch that uses printf()
will take less space with minimal printf()
vs default.
所以:
菜单选择 | printf() or similar used? | 开销 |
---|---|---|
默认 | 不 | 0 by definition |
默认 | 是的 | apx 1500 |
最小 | 不 | apx 1000 |
最小 | 是的 | apx 1100 |
满的 | 不 | apx 2800 |
满的 | 是的 | apx 3000 |
Notice how when not using printf or similar functions, you are far better off leaving it on the default, as opposed to switching to minimal thinking you'll save flash, because you you'll use more flash not less.
All pins can be used with attachInterrupt()
and detachInterrupt()
, on RISING
, FALLING
, CHANGE
, or LOW
. All pins can wake the chip from sleep on CHANGE
or LOW
. Pins marked as Async Interrupt pins on the megaTinyCore pinout charts (pins 2 and 6 within each port) can be used to wake from sleep on RISING
and FALLING
edges as well. Those pins are termed "fully asynchronous pins" in the datasheet.
Advanced users can instead set up interrupts manually, ignoring attachInterrupt()
, manipulating the relevant port registers appropriately and defining the ISR with the ISR()
macro - this will produce smaller code (using less flash and RAM) and the ISRs will run faster as they don't have to check whether an interrupt is enabled for every pin on the port.
For full information and example, see the Interrupt Reference.
Like my other cores, Sketch -> Export compiled binary will generate an assembly listing in the sketch folder. A memory map is also created. The formatting of the memory map leaves something to be desired, and I've written a crude script to try to improve it, see the Export reference for more information. see Exported Files documentation
The EESAVE fuse can be controlled via the Tools -> Save EEPROM menu. If this is set to "EEPROM retained", when the board is erased during programming, the EEPROM will not be erased. If this is set to "EEPROM not retained", uploading a new sketch will clear out the EEPROM memory. Note that this only applies when programming via UPDI - programming through the bootloader never touches the EEPROM.
You must do "burn bootloader" in order to apply changes after modifying this setting, as EESAVE is on the same fuse as one the one that can be used to disable UPDI, making it an "unsafe" fuse (one that if written with the wrong options, can make the device difficult to reprogram). We don't write "unsafe" fuses like that when uploading sketches, because it should never be possible to brick your board just by uploading, which you can do without opening the tools menu and seeing that you forgot to change the options back to the intended ones for the current project.
These parts officially support BOD trigger levels of 1.8V, 2.6V, and 4.2V, with Disabled, Active, and Sampled operation options for when the chip is in ACTIVE and SLEEP modes - Disabled uses no extra power, Active uses the most, and Sampled is in the middle. As of 2.1.0, the ACTIVE/SLEEP modes have been combined into a single menu, the nonsensical options (such as using more aggressive BOD while sleeping than while awake) were removed, and the previously unexposed options were added. Sampled mode is now available with two sample rates (the faster one uses ever so slightly more power, as you would expect) and "Enabled hold wake": in that mode, BOD is disabled in sleep, enabled when not sleeping, and when waking up, code execution does not begin until the BOD is ready. See the datasheet for details on power consumption and the meaning of these options.
You must do Burn Bootloader to apply this setting. This fuse is considered "unsafe" as you can set the BOD level to a voltage higher than the highest voltage tolerated by other chips soldered to the same pcb and sharing a power rail with the AVR, and this will then prevent reprogramming without desoldering things (because you'll either be unable to program the AVR because it's in brownout reset, or if you power it at a high enough voltage to leave BOR, you would damage the afore-mentioned low voltage parts).
Between the initial header file and preliminary datasheet release, and the more recent versions of each, several BOD settings were removed from the tinyAVR 0/1-Series datasheets, and the atpack release notes described them as "unqualified" - (I understand that this has something to do with the factory testing process and possibly the vetting process for the safety critical applications these parts are certified for. ). The three official BOD levels are the voltages that the chip is guaranteed (Yup, they use that word in the datasheet!) to work at, within the manufacturer specified temperature range and running at a system clock frequency no higher than specified at that voltage. Nevertheless, the other 5 BOD levels are believed to work as one would expect (I have used them successfully), but Microchip does not provide any guarantee that they'll work, even if all other operating requirements are met, and I do not believe they are tested in production. These "not guaranteed" voltages are still supported by the megaTinyCore BOD dropdown menu, but (as of 2.0.4 - the first version that has the new headers) are marked as "(Unofficial)" in the submenu. Note that the new headers no longer provide the *_gc
enum entries for these BOD level.
| BOD level
0/1-series| BOD level
2-series |保证速度
Normal temp. range |保证速度
Elevated temp. range) |-----------|------------------|---------------- --| | 1.8V | 1.8V | 5 MHz | 4 MHz | | 2.1V | 2.15V | unofficial | unofficial | | 2.6V | 2.6V | 10 MHz | 8 MHz | | 2.9V | 2.95V | unofficial | unofficial | | 3.3V | 3.3V | unofficial | unofficial | | 3.7V | 3.7V | unofficial | unofficial | | 4.0V | 4.0V | unofficial | unofficial | | 4.2V | 4.3V | 20 MHz | 16 MHz |
Normal temperature range is -40-105C on 0/1-series parts and -40-85C on 2-series parts. These parts have a letter N (0/1-series) or U (2-series) at the end of the part number; this is marked on the physical chip as well on 0/1-series, but not on 2-series.
Extended temperature range is -40-125C, and these parts are denoted with the F temperature spec. The extended temperature range column applies when the temperature range is above the normal range and below 125C on F-spec parts. The normal temperature range column still applies to F-spec parts if they are running in the normal temperature range.
Most existing Arduino libraries work. See the Supported Libraries List for a more complete list and discussion of what kinds of libraries might have issues. Of the few libraries that don't work, a handful happened to also be extremely popular and heavily used, such that it was felt necessary to include a compatible version with megaTinyCore. In addition to these, libraries which expose hardware that is only present on the modern AVRs, are also included. These libraries are listed below.
This library supplies two functions to check tuning status of the chip it's running on, and now adds two software reset functions (via WDT or via software reset). It also holds the massive keywords.txt file that highlights register names and core-specific functions.
megaTinyCore helper library docs
The usual NeoPixel (WS2812) libraries, including the popular FastLED as well as AdafruitNeoPixel, have problems on these parts - they depend on hand-tuned assembly, but the execution time of several key instructions has been improved. The improvements enable significant simplification of the code for driving these LEDs. This core includes a compatible version of the tinyNeoPixel library for interfacing with these ubiquitous addressable LEDs. There are two versions, both tightly based on the Adafruit_NeoPixel library. One implements a truly identical API, differing only in name (and obviously the fact that it works on tinyAVR and Dx-Series and megaAVR 0-Series parts at clock speeds from 8 MHz to 48 MHz, instead of on most classic AVRs at 8, 12, and 16 MHz). The other version makes a slight change to the constructor and drops support for changing length at runtime, in order to realize significant flash savings (around 1k). See the tinyNeoPixel documentation and included examples for more information.
The standard EEPROM.h is available here - it works like it does on any AVR. USERSIG.h
(from "User Signature" which the datasheet has sometimes called the USERROW
) it has the same API as EEPROM, though there may be future additions to harmonize with Dx-friendly functions for updating multiple bytes. The Dx-Series parts can only erase the whole USERROW, so potentially each byte written could involve erasing and rewriting it all - the question of how to deal with that is why DxCore doesn't have a USERSIG library yet). The name "USERSIG" refers to the alternate name of the USERROW, the "User Signature" space - the name USERROW could not be used because it is defined by the io headers (it's the struct
of type USERROW_t
, made up of USERROW.USERROW0
through USERROW.USERROW31
. Not the most useful thing, but we never override the io header file definitions unless working around a bug.
Note: Prior to 2.1.0, we tried to get clever with supporting the USERROW
through the EEPROM library; that not only was shortsighted (as it's logically inconsistent on anything with more than 256b of EEPROM), it also introduced some serious bugs. Use the USERSIG.h
library for that instead.
The usual Servo library from library manager is incompatible with these parts (minor changes could make it "work", but with glaring issues and a dependence on the configuration of TCA0). This core provides a version of the Servo library which will select an appropriate timer (TCB0 is the only option on most parts, on parts with a TCB1 (2-Series and 3216, 3217, 1617, 1616 and 1614), TCB1 will be used instead, provided it's not being used for millis()
). Except on parts with a TCB1, Tone cannot be used at the same time as the Servo library. Servo output is better at higher clock speed; when using servos, it is recommended to run at the highest frequency permitted by the operating voltage, to minimize jitter.
Warning If you have installed a version of the Servo library to your /libraries folder (including via library manager), the IDE will use that version of the library (which is not compatible with these parts) instead of the one supplied with megaTinyCore (which是)。 As a workaround, a duplicate of the Servo library is included with a different name - to use it, just #include
instead of #include
- no other code changes are necessary.
Note that the Servo libraries were only fixed in version 2.2.0 - prior to that we had a Servo library, but it didn't work due to an astonishingly large number of bugs (I swear I tested it - apparently not well enough).
Written by @MCUDude, this provides a more accessible (much more accessible!) wrapper around the optiboot.h library (which was written by the famous @westfw) . This supports writing to the flash of any device using Optiboot, by having the application code call routines in the bootloader to write to the flash. All modern AVRs have built-in flash protection mechanisms that permit only code executing from the bootloader section ( BOOTCODE
, in their terminology) to write to the application section ( APPCODE
). While the hardware does support a third flash section ( APPDATA
) which can be written by code running in APPCODE
this is only usable if there is also a BOOTCODE
section defined (otherwise the entire flash is treated as BOOTCODE
which can never be self-programmed), and would require a separate implementation of this library to use. It would also be possible to get flash-write-from-app without use of an actual bootloader through an analog of the trick used by the DxCore Flash.h for this. Since there appears to be little demand for such a thing, that functionality is not currently implemented (they were implemented on DxCore's flash writing library because the additional effort was virtually nil, and because there was a user with a particular interest in that feature). If someone wants this, and will adapt the library, I can add the entry point to the core and give you little chunks of inline assembly that will call it. Note on terminology: on AVR Dx-Series, the fuses are called BOOTSIZE
and CODESIZE
whereas on 0/1-Series tinyAVRs they're called BOOTEND
and APPEND
. I'm not quite sure how they didn't foresee customer confusion when they called the "APPlication END" that... Regardless of the names they do the same thing, although the granularity on tinyAVRs is finer, as you would expect.
Optiboot_flasher documentation
Warning As noted above, there is a library for DxCore that is also named Flash.h
. Both allow an application to write to the flash using Optiboot if present. That is the only similarity they have . The API, NVM hardware, method used to call the bootloader, and basically everything about these libraries is different . Be sure you write code for the one that matches the hardware you're using. While I (Spence Konde) wrote the DxCore one, I don't have a particularly strong opinion about which way is "right". We made them independently, but not because we each thought the other one's idea of how it should be done was wrong. They largely reflect the way the hardware interacts with its flash. For example, the one for megaTinyCore is page-oriented with its own page buffer, and these parts write in a page-oriented manner, while the DxCore library only cares about pages when erasing - on those parts, the flash is written with word or even byte granularity!
All of these parts have at least a pair of Configurable Custom Logic (CCL) blocks; official Microchip terminology calls them "LUTs" in reference to the LookUp Table (aka truth table). We use the term "logic block" instead, to avoid confusion with other kinds of lookup table (the "lookup table" in a logic block is very different from most lookup tables; containing 8 entries, each of which is a 0 or a 1, it is a single byte, which isn't much of a table), and to prevent users who missed this paragraph from being confused by the terminology. Each block allows you to supply an arbitrary 3-input truth table, as well as configuring additional options like a synchronizer, filter, or edge detector. The CCL operates asynchronously (unless you using the synchronizer) - meaning that things can happen faster than the clock speed. Thesynchronizer that will synchronize the CCL output to one of several clock sources (probably the system clock will be what you would synchronize with). The inputs can come from pins, events, or other peripherals. There's a feedback input as well, which allows a great many exciting possibilities, and a "sequencer" that can act like a latch or flip-flop using the outputs of a pair of logic blocks as its inputs. This is an incredibly powerful peripheral - especially on the 2-Series parts, which have a second pair of logic blocks, as well as the capability to trigger an interrupt when the state of one changes.
The Logic ( #include Logic.h
) library provides a simple wrapper around the CCL hardware in the tinyAVR 0/1/2-Series devices. This library is also included in DxCore and MegaCoreX, covering all AVRs with CCL hardware. Written by @MCUDude.
Logic library documentation
These parts have either 1 (everything else) or 3 (1614, 1616, 1617, 3216, and 3217) on-chip analog comparators which can be used to compare two analog voltages, and, depending on which is larger, do one or more of the following: generate an event output, control an output pin, or fire an interrupt. One of the voltages can be the internal reference (0-Series) or an internal reference scaled by an 8-bit DAC (everything else). This library, written by @MCUDude, provides a simple wrapper around the analog comparator(s) which makes their configuration easier and resulting code more readable (also easier on the wrists - less stuff to type in all caps) than manually configuring registers, while exposing nearly the full featureset of the analog comparators on these parts. Do note does not support the Window Comparator option for the parts with 3 comparators; There doesn't exactly seem to be a lot of demand for that one, though!
The Comparator library ( #include Comparator.h
) is also included in DxCore and MegaCoreX, covering all modern AVRs with comparator hardware. Written by @MCUDude.
Comparator library documentation
In general you should expect the following about library compatibility:
__AVR_ARCH__ >= 102
.architectures=*
would suggest that it would work anywhere - all this means is that there are not separate folders with implementations for different architectures. It does not mean that the library does not make assumptions about architecture, test against architecture specific stuff with #ifdef
s and so on. Unfortunately, library authors often use this when they know it works with a couple of architectures, shrug their shoulders and assume it'll work anywhere and put down a * in that field.The amount of effort required to port a given library will vary widely depending on the library. Some are straightforward for anyone reasonably familiar with these parts and what to generally expect and approach it. Any library associated with some peripheral that both classic and modern had, it's probably going to be a straightforward change if you just need to swap out the classic peripheral for the modern one - Yes, every bitfield will be named differently, but only rarely did a modern AVR's peripheral lack a feature the classic version had. The USART on classic AVR has whack stuff like MPCM, and the 9 bit mode - sorry, modes. Even the layout of some of the registers is similar - the parts aren't as different as they appear at first. Another type is the "bitbanger", where they're using direct port writes; the solution to this is cookbook - switch to using the relevant PORT or VPORT registers. Input capture is a little more complicated because you have to set up the event channel, and figure out how to offer that in a library (that is the hard part). But the consistent factor is that generally, none of these things are long slow painful slogs. And as noted above, many libraries will work out of the box, or have already been adapted.
The fact that many libraries can be ported no or little underlines the need for reports from users about incompatible libraries as well as compatible ones not listed on the table linked below. Usually reports of non-working libraries to add to the table result in the library getting fixed , and the fixed library being added to the table; Almost all of the fruit here low hanging. So when you come upon incompatible libraries report it to me! Many libraries that were initially incompatible were fixed up in under 10 minutes. Porting typical libraries from classic AVRs requires a fraction of the effort that the "tar pit" libraries included with this core take to port to new modern AVR families (these are Comparator, Logic, Event: Logic and Event are both, on their own, large, complicated, "system-like" peripherals. The CCL is just complex in general, and has seen relatively modest changest between families, except for the t0/1. Event is simple in theory and much more complicated in practice, in no small part because the implementation on the 0-series, 1-series, mega0, 2-series/DA/DB/DD, EA and the EB are each different. And a single library has to support all of them with a consistent interface and paper over all the差异。
I know lots of people use libraries that aren't on that list, and I fully expect that there is a great number of libraries that work and are not listed, and I'd love to hear about them. Use the "discussions" or email me, or even submit a PR to add a line to the table. I want to hear about working libraries so others will know they work and not hesitate, and I'm even more interested in ones that don't work so they can be fixed - or determined to be unfixable)
For more information on resetting from software, using the Watchdog Timer, the causes of unexpected resets and how to prevent them, and generally all things reset-related, see the Reset Guide.
It is often useful to identify what options are selected on the menus from within the sketch; this is particularly useful for verifying that you have selected the options you wrote the sketch for when opened later by yourself or someone who you shared it with. Or, you can use such in-sketch identification, combined with preprocessor #if
macros, to select the appropriate code depending on the part or options at hand.
There are a great number of #define
s provided to get information about the hardware in-use, in order to write portable and flexible code in your sketch or, especially, library code.
Note : You cannot distinguish an extended temperature range part from a normal one from software. For 0/1-series, most packages mark the temperature grade. this is no longer true on the 2-series, nor on any part released after the 1-series - So better make sure you mark those parts if you unpack them, because the only alternative is to give the lot number to Microchip support, and they'll tell you if it's an F, a U, or an N (FUN letters - but notice that you can't turn any letter into any other letter without both erasing and adding lines. The same is true of the different set of letters they used on automotive parts - BMZ or something - less FUN, but they had the same "modification resistance" (hey, on at least one occasion, a quantity of t13'd had the markings polished off and were remarked as tiny85's and sold as such on aliexpress and ebay - that was worth doing to some criminal in China! Unethical behavior is of course the norm for companies everywhere, but in the US, criminality of the company (as opposed to rogue employees) is not pervasive. When it rises above that, low end of chinese industry - ex, virtually all PVC wire is 2-8 AWG smaller than what is printed on the wire; same with silicone wire (but FEP insulated wire is always spot on, cause it's not at the low end ya see), one has to assume that (well, if they still marked the parts) someone has taken a bunch of parts marked I (vertical line), added 3 horizontal lines to each one (One imagines, with the same sort of automated chip marking method that would be used for putting any other pattern, except here it would just be the missing parts of an E. The consistency of the location of markings on packages is remarkably consistent specimen to specimen, such that you might be able to target by position and get it close enough to be convincing, and with just 3 small marks and no grinding, and significant price difference between I and E spec parts for certain parts (oddly, not for most tinies). Of course when they adopted the I and E when they stopped marking parts at all, so this is academic. But can you seriously imagine anyone inspecting 200 boards and writing down every lot number he saw, and emailing the list to Microchip and asking for confirmation that they're all E's as he ordered?).
A new version of Optiboot (Optiboot_x) now runs on the tinyAVR 0-Series, 1-Series and 2-Series chips. It's under 512 bytes, and works on all parts supported by this core, allowing for a convenient workflow with the same serial connections used for both uploading code and debugging (like a normal Arduino Pro Mini). Note the exception about not having autoreset unless you disable UPDI (except for the 20 and 24-pin 2-Series parts which can put reset on PB4 instead), which is a bit of a bummer.
To use the serial bootloader, select a board definition with (optiboot) after it. Note - the optiboot suffix might be visually cut off due to the width of the menu; the second / lower set of board definitions in the board menu are the optiboot ones). The 2-Series Optiboot definitions and the 0/1-Series Optiboot definitions are separate entries in the board menu.
See the Optiboot referencefor more information.
These guides cover subsystems of the core in much greater detail (some of it extraneous or excessive).
Covering top-level functions and macros that are non-standard, or are standard but poorly documented, and which aren't covered anywhere else.
The API reference for the analog-related functionality that is included in this core beyond the standard Arduino API.
The API reference for the digital I/O-related functionality that is included in this core, beyond the standard Arduino API, as well as a few digital I/O-related features that exist in the hardware which we provide no wrapper around.
Documents the (largely intended for internal use) dirty inline assembly macros that are used by the core to improve performance or reduce code size.
Includes a list of all interrupt vectors that can be used, how the flags are cleared (not a substitute for the datasheet - just a very quick reminder), which parts each vector exists on, and and what parts of the core, if any, make use of a vector. It also has general guidance and warnings relating to interrupts their handling, including estimates of real-world interrupt response times.
The USARTs (Serial) have some greatly enhanced functionality compared to the stock core.
Serial UPDI is our recommended tool for UPDI programming.
Supported clock sources and considerations for the use thereof.
Manufacturer specs for speed at various voltages, and some discussion of BOD thresholds - this is written largely from a very conservative perspective, in contrast to most of the documentation.
These are provided by the core and can be overridden with code to run in the event of certain conditions, or at certain times in the startup process.
The core feature #define
s are used by megaTinyCore and other cores I maintain as well. This also documents what constant values are defined by the core for version identification, testing for features, and dealing with compatibility problems.
Export compiled binary generates both assembly listings and memory maps, in addition to the hex file. The options selected are encoded in the name of the file to help prevent confusion and make it easy to compare two configurations when you are surprised by the differences between them. Also provides links to a script I wrote to reformate memory maps so you can read the damned things.
The sources of reset, and how to handle reset cause flags to ensure clean resets and proper functioning in adverse events. Must read for production systems
The installation and operation of the Optiboot bootloader (for uploading over straight serial (not SerialUPDI)) is described here. Not recommended except on the 20/24-pin 2-Series (since they have the alt reset pin) or for special use cases that demand it.
This contains detailed information on how the timers are used in megaTinyCore, and some background on their capabilities.
These guides are older; some are still relevant.
This has been recently updated and will likely be turned into a Ref_TCA0.
This document describes how (on the 0 and 1 Series only) the ADC can be taken over and reconfigured, with particular attention to free running mode. The 2-Series ADC is different, and it would require changes to reflect those differences.
A delightful, though unfortunately short, document on bare metal programming in C.
The bible of the AVR instruction set. Like any such tome, it is a lengthy document which contains timeless wisdom from the creator(s), written in obtuse and challenging language and a confusing syntax (though you won't go to hell if you don't read it, if you're writing assembly without it, you might not be able to tell the difference).
As promised, a bunch of additional information was released; Unfortunately it leaves some of the key questions unanswered.
printf()
implementation - The default option can be swapped for a lighter weight version that omits most functionality to save a tiny amount of flash, or for a full implementation (which allows printing floats with it) at the cost of about 1k extra flash. Note that if non-default options are selected, the implementation is always included in the binary, and will take space even if not called. This applies everywhere that format strings are used, including Serial.printf()
.attachPortAEnable()
and replace A
with the letter of the port) before attaching the interrupt. This allows attachInterrupt()
to be used without precluding any use of a manually defined interrupt (which is always much faster to respond). Basically any time you "attach" an interrupt, the performance is much worse.millis()
, micros()
and pulseInLong()
will be available. If set to disable, these will not be available, Serial methods which take a timeout as an argument will not have an accurate timeout (though the actual time will be proportional to the timeout supplied); delay()
will still work. Disabling millis()
and micros()
saves flash, and eliminates the millis()
interrupt every 1-2 ms; this is especially useful on the 8-pin parts which are extremely limited in flash. Depending on the part, options to force millis()
/ micros()
onto specific timers are available. A #error
will be shown upon compile if a specific timer is chosen but that timer does not exist on the part in question (as the 0-Series parts have fewer timers, but run from the same variant). If RTC is selected, micros()
and pulseInLong()
will not be available - only millis()
will be.There are however a few cautions warranted regarding megaTinyCore - either areas where the core is different from official cores, or where the behavior is the same, but not as well known.
If you are manually manipulating registers controlling a peripheral, except as specifically noted in relevant reference pages, the stated behavior of API functions can no longer be assured. It may work like you hope, it may not, and it is not a bug if it does not, and you should not assume that calling said API functions will not adversely impact the rest of your application. For example, if you "take over" TCA0, you should not expect that using analogWrite()
- except on the two pins on the 20/24-pin parts controlled by TCD0 - will work for generating PWM. If you reconfigure TCA0 except as noted in Ref_Timers, without calling takeOverTCA0
, both analogWrite()
and digitalWrite()
on a PWM pin may disrupt your changed configuration.
While we generally make an effort to emulate the official Arduino core, there are a few cases where the decision was made to have different behavior to avoid compromising the overall functionality; the official core is disappointing on many levels. The following is a (hopefully nearly complete) list of these cases.
Earlier versions of megaTinyCore, and possibly very early versions of DxCore enabled the internal pullup resistors on the I2C pins. This is no longer done automatically - they are not strong enough to meet the I2C specifications, and it is preferable for it to fail consistently without external ones than to work under simple conditions with the internal ones, yet fail under more demanding ones (more devices, longer wires, etc). However, as a testing aid, we supply Wire. usePullups()
to turn on the weak internal pullups. If usePullups()
ever fixes anything, you should install external pullups straight away. Our position is that whenever external pullups are not present, I2C is not expected to work. Remember that many modules include their own on-board pullups. For more information, including on the appropriate values for pullups, see the Wire library documentation
The official core for the (similar) megaAVR 0-Series parts, which megaTinyCore was based on, fiddles with the interrupt priority (bet you didn't know that!) in methods that are of dubious wisdoom. megaTinyCore does not do this, saving several hundred bytes of flash in the process, and fixing at least one serious bug which could result in the microcontroller hanging if Serial was used in ways that everyone tells you not to use it, but which frequently work anyway 。 Writing to Serial when its buffer is full, or calling Serial.flush()
with interrupts disabled, or during another ISR (which you really shouldn't do ) will behave as it does on classic AVRs and simply block, manually calling the transmit handlers, until there is space in the buffer for all of the data waiting to be written or the buffer is empty (for flush()
). On th stock megaAVR core, this could hang forever.
This is deprecated on the official core and is, and always has been, a dreadful misfeature. Dropped as of 2.3.0.
digitalRead()
Does Not Turn Off PWM On official cores, and most third party ones, the digitalRead()
function turns off PWM when called on a pin. This behavior is not documented by the Arduino reference. This interferes with certain optimizations, makes digitalRead()
take at least twice as long (likely much longer) as it needs to and generally makes little sense. Why should a "read" operation change the thing it's called on? We have a function that alters the pin it's called on: digitalWrite()
. There does not seem to be a logically coherent reason for this and, insofar as Arduino is supposed to be an educational platform it makes simple demonstrations of what PWM is non-trivial (imagine setting a pin to output PWM, and then looking at the output by repeatedly reading the pin).
digitalWrite()
and INPUT
Pins Like the official "megaavr" core, calling digitalWrite()
on a pin currently set INPUT
will enable or disable the pullups as appropriate. digitalWrite()
also supports "CHANGE" as an option; on the official core, this will turn the pullup on, regardless of which state the pin was previously in, instead of toggling the state of it. The state of the pullup is now set to match the value that the port output register was just set to.
This was done because of the huge volume of code that makes use of this behavior. We experimented with making pinMode() do the inverse for INPUT and INPUT_PULLUP, but this was removed by unanimous agreement by everyone in the discussion thread.
analogWrite()
and TCD0 Pins Please see the above PWM feature description if using PWM on those pins and also using digitalRead()
or direct port writes on the same pins (PIN_PC0, and PIN_PC1).
On the official "megaavr" board package, TCA0 is configured for "single mode" as a three-channel 16-bit timer (used to output 8-bit PWM). megaTinyCore always configures it for "Split mode" to get additional PWM outputs. See the datasheets for more information on the capabilities of TCA0. See Taking over TCA0 for information on reconfiguring it. One downside to this is that the compare channels do not support buffering, so changing the duty cycle can cause a glitch lasting up to one PWM cycle (generally under 1 ms).
0 is a count, so at 255, there are 256 steps, and 255 of those will generate PWM output - but since Arduino defines 0 as always off and 255 as always on, there are only 254 possible values that it will use. The result of this is that (I don't remember which) either analogWrite(pin,254)
results in it being LOW
2/256's of the time, or analogWrite(pin,1)
results in it being HIGH
2/256's of the时间。 On megaTinyCore, with 255 steps, 254 of which generate PWM, the hardware is configured to match the API, and this does not occur. As it happens, 255 also (mathematically) works out such that integer math gets exact results for millis()
timing with both 16-MHz-derived and 20-MHz-derived clock speeds, which is relevant when TCA0 is used for millis()
定时。 The same thing is done for TCD0, though to 509, giving 510 steps. analogWrite()
accounts for this, so that we can get the same output frequency while keeping the fastest synchronization prescaler for fastest synchronization between TCD0 and system clock domains.
On the official "megaavr" board package, as well as DxCore, the Type B timers are used to generate 8-bit PWM (one pin per timer). There are very few circumstances where this could increase the number of usable PWM pins. These timers are just too scarce and valuable on these parts. Being minimally useful for PWM, in short supply, and highly desirable for other purposes, support for using Type B timers for PWM was removed in order to save space that would otherwise be used initializing these timers for PWM and handling them in analogWrite()
et 。等人。 If a Type B timer is used for millis()
, it is configured in a radically different way than the official core does it.
They return and expect uint8_t
(byte) values, not enum
s like the official megaavr board package does. Like classic AVR cores, constants like LOW
, HIGH
, etc are simply #define
d to appropriate values. The use of enum
s unfortunately broke many common Arduino programming idioms and existing code (granted, these idioms were poor programming practice - they're also incredibly widespread and convenient), increased flash usage, lowered performance and made optimization more challenging. The enum
implementation made language design purists comfortable and provided error checking for newbies, because you couldn't pass anything that wasn't a PinState to a digital I/O function and would see that error if you accidentally got careless. Nevertheless, due to all the complaints, a compatibility layer was added to the official core, so all the old tricks would work again, it was just less performant. However, that got rid of what was probably the most compelling benefit by allowing the workarounds: the fact that it did generate an error for new users to train them away from common Arduino practices like passing 1 or 0 to digitalWrite()
, if(digitalRead(pin))
and the like. The choice of names of the enum
s also had the perverse effect of making PinMode(pin,OUTPUT)
(an obvious typo of pinMode(pin,OUTPUT)
) into valid syntax (comma operator turns pin,OUTPUT
into OUTPUT
, and it returns a new PinMode
of value OUTPUT
...) and does nothing with it, instead of a syntax error (It took me over an hour to find the erroneous capitalization. That evening, I converted the digital I/O functions to the old signatures and removed the enum
s). Anyway - the enum
s are not present here, and they never will be; this is the case with MegaCoreX and DxCore as well.
There are two classes of significant low level architectural differences (aside from the vastly improved peripherals): the improved instruction set and the unified memory address space.
The classic AVR devices all use the venerable AVRe
(ATtiny) or AVRe+
(ATmega) instruction set ( AVRe+
differs from AVRe
in that it has hardware multiplication and supports devices with more than 64k of flash). Modern AVR devices (with the exception of ones with minuscule flash and memory, such as the ATtiny10, which use the reduced core AVRrc
) all use the latest iteration of the AVR instruction set, AVRxt
. AVRxt
has much in common with AVRxm
(used in XMega parts) in terms of instruction timing - and in the few places where they differ, AVRxt
is faster (SBIC, as well as LDD, and LD with pre-decrement, are all 1 clock slower on AVRxm
vs AVRxt
or AVRe
), however AVRxt
doesn't have the single-instruction-two-clock read-and-write instructions for memory access LAT
, LAC
, LAS
, and XCH
. The difference between subspecies of the AVR instruction set is unimportant for 99.9% of users - but if you happen to be working with hand-tuned assembly (or are using a library that does so, and are wondering why the timing is messed up),变化是:
As you can see, everything that involves writing to the SRAM is faster now; it would appear that any time it is writing to a location based on one of the pointer registers or the stack pointer, it's a single cycle. All the other improvements except CBI
and SBI
can be viewed as a consequence of that. Of course, the variants of CALL
are faster; they have to put the return address into the stack. I can't say I've ever felt like LAT
, LAC
, or LAS
would be terribly useful as they are described in the instruction set manual - those take a register and the address pointed to by the Z register, load the contents of the specified address and toggle, set or clear in that memory address the bits that were set to begin with in the register. If that worked on special function registers, it would be a very useful instruction, taking PERIPHERAL.REGISTER |= SOME_BIT_bm;
from a 5 clock, non-atomic operation to a 2 clock atomic one! But it says they only work on SRAM... so not as much of a loss. XCH
is more obviously useful than the others, but all 4 of them come with the need to set up the Z register... which in many cases would take long enough that it wouldn't be a notable improvement.
Note that the improvement to PUSH
can make interrupts respond significantly faster (since they have to push the contents of registers onto the stack at the beginning of the ISR), though the corresponding POP
s at the end aren't any faster. The change with ST
impacted tinyNeoPixel. Prior to my realizing this, the library worked on SK6812 LEDs (which happened to be what I tested with) at 16/20 MHz, but not real WS2812's. However, once I discovered this, I was able to leverage it to use a single tinyNeoPixel library instead of a different one for each port like was needed with ATTinyCore (for 8 MHz, they need to use the single cycle OUT
on classic AVRs to meet timing requirements, the two cycle ST
was just too slow; hence the port had to be known at compile time, or there must be one copy of the routine for each port, an extravagance that the ATtiny parts cannot afford. But with single cycle ST
, that issue vanished).
Oh, and one other instruction it doesn't have that (some) AVRxm parts have: The hardware DES
encryption instruction - an instruction which is most effective at marking AVRxm as, ah, back from the time when DES
was a big deal.
On all modern AVRs with up to 48k of flash, both the flash and ram reside in the same address space - On tinyAVRs, the program memory starts at 0x8000, while on megaAVR 0-Series, it starts at 0x4000 to leave room for the 48k of flash that they can have, and on the Dx-Series parts with up to 32k of flash, they have the same layout as the tinyAVRs, while Dx-Series parts with 64k or 128k of flash have a 32k section of flash mapped at any given time (how to make sure variables go into this memory mapped flash has been described elsewhere in this document). There is another big and fundamental change to the layout of the address space as well: the registers are organized by peripheral. PORTA is assigned 0x400 to 0x41F. PORTB is the next 32 bytes, and so on - and the address space is far sparser - all the peripherals have multiple "reserved" registers that may or may not get functions added in the future. And each instance of a peripheral on a part that has multiple of them has the same layout. You can, say, pass a pointer to a TCB around without the functions that get it knowing which TCB they'll get, and then access the TCB registers through it. On classic AVRs the names of the registers were consistent, but their locations were all over the place, packed much more tightly, so that sort of trick isn't possible. This also means that the EEPROM (and USERROW) are part of this unified address space (on classic AVRs, reading was accomplished through special function registers, and was far more awkward).
The lowest 64 registers are special - you can read or write them with the IN
or OUT
instructions (hence, "I/O space") in a single clock cycle, without setting up a pointer to them as you would need to with ST
or LD
. The 32 "Low I/O registers" additionally have bit-level access instructions CBI
and SBI
to clear and set bits, and SBIC
/ SBIS
to skip the next instruction if a certain bit is set or cleared. On all AVRxt parts released so far, the low I/O registers are used only for the VPORTs, up to VPORTG or the last port on the part, whichever comes first. This means VPORTG.OUT |= 1 << n
, where n is known at compile-time and constant , is a 1 clock cycle atomic operation , while VPORTG.OUT = 1 << n
(note the =
in lieu of |=
) takes two clock cycles. For the latter, the first cycle is to put the value to be stored into a register, and the second is to write it with an OUT
instruction. The GPIOR0-3 registers occupying the last 4 bytes in the low I/O space (those are user-defined registers to use as you choose. We use GPIOR0 internally during startup to record reset cause, and store two types of warnings applicable to tuning )。 The reset flag register is always cleared very early in startup to prevent dirty resets, and when using a bootloader, so that it can honor bootloader entry conditions on next reset). No other part of this core touches those registers, and we only set GPIOR0; we never read it. So all can be used freely, as long as you remember that GPIOR0 is not empty when you enter setup, and contains the reset cause flags. Other Low I/O registers are not used by the hardware.
The 32 "high I/O registers" are used even less - they only contain the the stack pointer, RAMPZ
on the 128k DA/DB parts, SREG
, and CCP
(Configuration Change Protection - where _PROTECTED_WRITE()
does it's magic to let you write to protected registers. That's all - 5 out of 32 registers are used, the rest are "reserved". On classic AVRs, registers for assorted peripherals that the designers thought would be accessed often were put into the I/O space, so it was a disappointment that they didn't put an alias of any other registers there. I'd vote for the intflags registers to be aliased there
megaTinyCore itself is released under the LGPL 2.1. It may be used, modified, and distributed freely, and it may be used as part of an application which, itself, is not open source (though any modifications to these libraries must be released under the LGPL as well). Unlike LGPLv3, if this is used in a commercial product, you are not required to provide means for users to update it.
The DxCore hardware package (and by extension this repository) contains DxCore as well as libraries, bootloaders, and tools. These are released under the same license, unless specified otherwise . For example, tinyNeoPixel and tinyNeoPixel_Static, being based on Adafruit's library, are released under GPLv3, as described in the LICENSE.md in those subfolders and within the body of the library files themselves.
The pyupdi-style serial uploader in megaavr/tools is a substantially renovated version of pymcuprog from Microchip, which is not open source has now been released under the open source MIT license! 。
Any third party tools or libraries installed on behalf of megaTinyCoreCore when installed via board manager (including but not limited to, for example, avr-gcc and avrdude) are covered by different licenses as described in their respective license files.