t3486784401 发表于 2016-6-23 01:54:16

【发现】某些 AVR 的 PINx 可用于翻转 PORTx

本帖最后由 t3486784401 于 2016-6-23 01:51 编辑

【背景】
最近在做一个用 ATTINY13 的方波发生器,偶然间发现可以用 PINx 寄存器翻转 PORTx 输出/上拉状态。手册上是这么说的:






【用法】
具体方式为:向 PINx 写逻辑 1 即可实现 PORTx 状态翻转。

【型号】
立即查了查相近型号,并非所有 AVR 都支持这个功能,貌似仅限于较新的 AVR (TINY、xxxPA)。
支持的型号包括:ATTINY13/24/25/2313,ATMEGA48/88/168/328,ATMEGA640/1280/2560
不支持的型号包括:ATMEGA8/16/32/64/128

【猜测】
PINx 本来是用于读取端口状态(输入)的,ATMEL这么设计应该是从硬件层面加快翻转执行速度:

PORTB |= (1<<3);   // PB3=1,SBI指令:2T
PORTB &= ~(1<<3);    // PB3=0,CBI指令:2T
PORTB ^= (1<<3);   // PB3=~PB3,IN/LDI/EOR/OUT指令:4T

一般编译器在端口取反时需要用寄存器异或中转,结果就是略慢(4T),有了 PINx 这个功能后就和置位/复位时间一样了:

PINB |= (1<<3);   // PB3=~PB3,SBI指令:2T

不过即使这么支持,感觉在 C 层面的可读性略差,真要这么用的话估计要写明注释了,省的被移植到不支持的片子里。

jackboy 发表于 2016-6-23 06:38:52

少有的技术贴, 这个先收藏了

粗人 发表于 2016-6-23 07:54:33

新技能GET,虽然有点蛋疼

jetta2014 发表于 2016-6-24 13:42:06

谢谢楼主分享,说不定以后用得上。

huaxiling 发表于 2016-6-24 14:25:02

以前看到手册有标注, 但试了好多老的片子都不支持, 于是放弃
页: [1]
查看完整版本: 【发现】某些 AVR 的 PINx 可用于翻转 PORTx