我已经阅读了数据表和谷歌,但我仍然不明白。
就我而言,我将 PIC18F26K20 的 PIN RC6 设置为 INPUT 模式:
TRISCbits.TRISC6 = 1;
然后我用 PORT 和 LATCH 读取值,我有不同的值!
v1 = LATCbits.LATC6;
v2 = PORTCbits.RC6;
v1 给我 0,而 v2 给我 1。
正常吗?在哪种情况下我们必须使用 PORT,在哪种情况下使用 LATCH?
锁存器是写入值的输出锁存器。端口是实际引脚上的电压。
在某些情况下,它们可能会有所不同。我最常遇到的一种情况是,如果您有一个引脚(意外地)接地短路。如果您将锁存器设置为高电平,则锁存器将读取为高电平,但端口将读取为低电平,因为引脚上的电压仍接近接地。
导致您所描述的另一种情况是端口引脚配置不正确。我(和我一起工作的每个人)都花了很多时间试图弄清楚为什么我们的 PIC 没有达到预期的效果,最终发现我们掩盖了关闭模拟模块的问题。确保查看 I/O 端口 -> PORT?、TRIS? 和 LAT? 部分。数据表中的寄存器。您可以在Microchip wiki 页面中获得更多信息,该 页面解释了在连接到容性负载的引脚上写入输出后立即读取错误值的信息。
该维基页面还解释了:
读取端口锁存寄存器会返回输出驱动器的设置,而读取端口寄存器会返回在引脚上看到的逻辑电平。
此外,这是 18F14K50 的 I/O 端口部分的片段(应该与 18F 系列的其余部分相同):
每个端口都有三个用于操作的寄存器。这些寄存器是:
- TRIS 寄存器(数据方向寄存器)
- PORT 寄存器(读取器件引脚上的电平)
- LAT 寄存器(输出锁存器)
所以在大多数情况下,您将写入锁存器并从端口读取。
我将改编电气工程的答案。
让我们使用手册中的图片:
当您在 I/O 引脚中写入一个位时,您正在将该位从数据总线存储到数据寄存器 ( D-FlipFlop )。如果该位的 TRISx 为 0,则来自数据寄存器 Q 的数据将在 I/O 引脚中。写入 LATx 或 PORTx 是一样的。见下图红色:
另一方面,从 LATx 读取不同于从 PORTx 读取。
当您从 LATx 读取数据时,您正在读取数据寄存器 ( D-FlipFlop ) 中的内容。见下图绿色:
当您从 PORTx 读取数据时,您正在读取实际的 I/O 引脚值。见下图蓝色:
PIC 使用 read-modify-write 来写操作,这可能是个问题,所以他们使用这个影子寄存器来避免它。
这是数据表中的有用摘要。
11.2.3 LAT 寄存器
与I/O 引脚相关的LATx 寄存器消除了读-修改-写指令可能出现的问题。读取 LATx 寄存器会返回端口输出锁存器中保存的值,而不是 I/O 引脚上的值。与 I/O 端口关联的 LAT 寄存器上的读-修改-写操作避免了将输入引脚值写入端口锁存器的可能性。写入 LATx 寄存器与写入 PORTx 寄存器的效果相同。
PORT和LAT寄存器的区别可以总结如下:
是的,读取 PORTx 和 LATx 并偶尔发现它们具有不同的值是正常的。
当您想读取某个外部硬件是否将某个引脚驱动为高电平或低电平时,您必须将引脚设置为输入模式(使用 TRIS 或 DIR 寄存器),并且您必须读取 PORTx。该读数告诉您引脚上的实际电压是高还是低。
当你想驱动一个引脚为高电平或低电平时,你必须将这个引脚设置为输出(用TRIS或DIR寄存器);您应该将该位写入 LATx 寄存器。
(将该位写入 PORTx 寄存器可能看起来是正确的:该引脚最终会按照命令变为高电平或低电平。但在很多情况下,例如当该端口上的某个其他引脚连接到集电极开路总线——写入 PORTx 寄存器的一位会扰乱该端口上其他引脚的状态,从而导致难以调试的问题)。
我的建议是将 PORT 值视为只读的。可以读取或写入 LAT 值,但读取的值将是最后写入的值,而不是引脚的输入值。
在较旧的 PIC 上,LATx 值不存在;写入端口的唯一方法是通过 PORTx 寄存器。奇怪的是,从通用仪器(Microchip 之前)时代回来的一些真正老的 PIC 支持 LATx,但 Microchip 直到 PIC18x 系列才添加该功能。
写入PORTx
寄存器会将数据值写入端口锁存器。
写入LATx
寄存器会将数据值写入端口锁存器。
读取PORTx
寄存器会读取 I/O 引脚上的数据值。读取LATx
寄存器会读取端口锁存器上的数据值。
使用LATx
:写入输出引脚
使用PORTx
:读取输入引脚
对于所有带有LATx
寄存器的 PIC,所有 INPUT 必须是 fromPORTx
并且所有 OUTPUT 都应该是 to LATx
,这完全避免了当您写入端口的单个位时翻转位的问题。
我最近体验到,当另一个 PORTx Rj(例如 PORTC RC0)已经设置时,在 PIC18F14K50 的 PORTx Ri(例如 PORTC RC1)上写入是无效的。我在 PORTx Ri 上的示波器中看到了一瞥,但我无法维持输出。当我在 LATx 上写作时,这个问题就消失了。
LATx 写入在 PIC18 上看起来是强制性的,而 PORTx 写入是禁止的。
总是推荐写LAT,读PORT,原因是当端口用作输出时,PORT的位操作会做read modify write指令。
Read modify write 指令存在一些缺陷,基于输出电容(端口引脚的上升时间),当执行两个连续的 READ modify WRITE 指令时,可能会将端口引脚设置为错误值。
所以总是写入 LAT 并从 PORT 读取(输入引脚)