PIC 18F中PORT和LATCH的区别

29

我已经阅读了数据手册和谷歌,但仍然不明白某些内容。

在我的情况下,我将PIC18F26K20的PIN RC6设置为输入模式:

TRISCbits.TRISC6 = 1;

然后我使用PORTLATCH读取该值,但我得到了不同的值!

v1 = LATCbits.LATC6;

 v2 = PORTCbits.RC6;

v1 给我 0,而 v2 给我 1

这正常吗?
在什么情况下我们必须使用 PORT,在什么情况下我们必须使用 LATCH


1
我认为基本上LAT用于在其上编写,而PORT用于从其中读取。您也可以从LAT中读取,但需要满足特定条件。请参考数据表。 - Bernie Loom
8个回答

35
锁存器是写入数值的输出锁存器。端口是实际引脚上的电压。
有几种情况它们可能会不同。我遇到最频繁的一种情况是,如果某个引脚意外短接到地面。如果您将锁存器设置为高电平,锁存器将读取高电平,但由于引脚上的电压仍然接近地面,端口将读取低电平。
另一个导致您所描述问题的情况是端口引脚未正确配置。我和我所有的同事都花费了很多时间试图弄清楚为什么我们的PIC没有按预期工作,最终发现我们忽略了关闭模拟模块之类的细节。请确保查看数据表中的I/O Ports -> PORT?,TRIS?和LAT?寄存器部分。您可以在Microchip wiki页面中获取更多信息,该页面解释了在连接到电容性负载的引脚上写入输出后立即读取错误值的情况。
该wiki页面还解释道:

端口锁存器寄存器的读取返回输出驱动器的设置,而端口寄存器的读取返回设备引脚上的逻辑电平。

此外,下面是18F14K50的I/O Ports部分的一段片段(应该与18F系列的其余部分相同):
每个端口都有三个寄存器,用于其操作。这些寄存器是:
  • TRIS寄存器(数据方向寄存器)
  • PORT寄存器(读取设备引脚上的电平)
  • LAT寄存器(输出锁存器)
因此,在大多数情况下,您将写入锁存器并从端口读取。

如果引脚处于输入模式,我应该使用什么?LATCH 还是 PORT? 如果引脚处于输出模式,我应该使用什么?LATCH 还是 PORT? - acemtp
输入 = 端口,输出 = 锁存器 - Mike

19

我将从电子工程中适应我的答案

让我们使用手册中的图片:

通用IO端口操作

当您在IO引脚中写入位时,您正在将这个位从数据总线存储到数据寄存器(D触发器)。如果该位的TRISx为0,则来自数据寄存器Q的数据将在IO引脚中。写入LATx或PORTx是相同的。请参见下面的红色部分:

通用IO端口操作写入

另一方面,从LATx读取与从PORTx读取不同。

当您从LATx读取时,您正在读取数据寄存器(D触发器)中的内容。请参见下图中的绿色部分:

通用IO端口操作读取LATx

当您从PORTx读取时,您正在读取实际的IO引脚值。请参见下图中的蓝色部分:

通用IO端口操作读取PORTx

PIC使用读-修改-写来进行写入操作,这可能会造成问题,因此他们使用这个影子寄存器来避免这种情况。


1
非常感谢您的解释,我之前对于PORT和LAT的读写操作有些困惑。感谢您提供可视化的PORT读取和LAT写入示意图。 - Kush Singla

11

这是来自数据表的有用摘要。

11.2.3 LAT 寄存器
与 I/O 引脚相关联的 LATx 寄存器消除了可能出现的读取-修改-写入指令所带来的问题。从 LATx 寄存器读取时,返回的是端口输出锁存器中保存的值,而不是 I/O 引脚上的值。与 I/O 端口相关联的 LAT 寄存器进行读取-修改-写入操作,避免了将输入引脚值写入端口锁存器的可能性。向 LATx 寄存器进行写入操作具有与向 PORTx 寄存器进行写入操作相同的效果。

PORT 和 LAT 寄存器之间的区别可以总结如下:

  • 向 PORTx 寄存器进行写入操作会将数据值写入端口锁存器。
  • 向 LATx 寄存器进行写入操作会将数据值写入端口锁存器。
  • 从 PORTx 寄存器读取时,读取的是 I/O 引脚上的数据值。
  • 从 LATx 寄存器读取时,读取的是端口锁存器中保存的数据值。

1
感谢您的回答。我已经阅读了数据表和这个部分,但它并没有回答我的问题:当我需要读取引脚(输入模式)时,我应该使用锁存器还是端口?当我需要写入引脚(输出模式)时,我应该使用锁存器还是端口? - acemtp

4

是的,读取PORTx和LATx时发现它们具有不同的值是正常的。

当您想要读取某些外部硬件是将引脚拉高还是拉低时,必须将引脚设置为输入模式(使用TRIS或DIR寄存器),并且必须读取PORTx。该读取告诉您引脚实际电压是高还是低。

当您想要将引脚拉高或拉低时,必须将引脚设置为输出模式(使用TRIS或DIR寄存器);您应该将位写入LATx寄存器。

(将该位写入PORTx寄存器可能会看起来做正确的事情:该引脚将根据指令最终变为高电平或低电平。但是存在许多情况 - 例如当该端口上的其他引脚连接到开漏总线时 - 写入PORTx寄存器的一个位将破坏该端口上其他引脚的状态,导致难以调试的问题)。

Open Circuits: read before write


3
我的建议是将PORT值视为只读。LAT值可以读取或写入,但读取的值将是最后一个写入的值,而不是引脚的输入值。
在旧的PIC设备上,LATx值不存在;唯一的写入端口的方法是通过PORTx寄存器。有趣的是,一些早期的PIC设备,来自General Instruments(Microchip之前的公司),支持LATx,但Microchip直到PIC18x系列才添加了这个特性。

1

PORTx寄存器的写操作会将数据值写入端口锁存器。
LATx寄存器的写操作会将数据值写入端口锁存器。
PORTx寄存器的读操作会读取I/O引脚上的数据值。
LATx寄存器的读操作会读取端口锁存器上的数据值。

使用LATx:向输出引脚写入数据

使用PORTx:读取输入引脚的数据

对于所有带有LATx寄存器的PIC,所有的输入必须来自PORTx,所有的输出应该是LATx,这完全避免了在写入端口的单个位时翻转位的问题。


0

建议始终写入LAT,从PORT读取,原因是当端口用作输出时,PORT的位操作将执行读取修改写入指令。

读取修改写入指令存在一些缺陷,基于输出电容(端口引脚的上升时间),可能会将端口引脚设置为错误值,当执行两个连续的读取修改写入指令时。

因此,始终从LAT中写入并从PORT(输入引脚)中读取。


0

最近我发现,在PIC18F14K50的PORTx Ri(例如PORTC RC1)上写入时,如果另一个PORTx Rj(例如PORTC RC0)已经设置,则无效。 我在PORTx Ri上观察到了一个峰值,但我无法维持输出。 只要我在LATx上写入,这个问题就消失了。

PIC18上必须使用LATx写入,禁止使用PORTx写入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接