答案是:是的,URSEL 位。根据数据表:
当对该 I/O 位置进行写访问时,
写入的值,USART 寄存器选择(URSEL)位,控制哪个
将被写入的两个寄存器之一。如果 URSEL 在
写操作,UBRRH 值将被更新。如果 URSEL 是一,
UCSRC 设置将被更新。
这意味着,当您写信给UCSRC 时,无论您要在那里输入什么值,也要设置URSEL 位(确保URSEL 是1):
UCSRC = (1<<URSEL)| ... whatever else ...
当您写入UBRRH 时,请确保URSEL 位必须为零。以下是一些不同的方法:
UBRRH = (0<<URSEL)| ... whatever else ... // just showing that URSEL isn't set
UBRRH = ...some value... // simple not setting URSEL
UBRRH = (someValue)&(~(1<<URSEL) // Ensuring that URSEL isn't set
URSEL 位只是一个高位。因此,无论您向UCSRC 写入什么值,都将(打开,使1)设置为高位(位7)。在写入UBRRH 时,请确保清除第 7 位。另一种思考方式是,您写入 UBRRH 的每个值都必须小于 128。并且您要写入 UCSRC 的每个值都加上 128:这将打开第 7 位。这就像解释方式,上面的代码更清晰。
这是怎么做到的?我不知道,我不是uC设计师。看起来很可能是相同的 IO 位置位置映射到处理器中的两个不同寄存器。假设您有一个名为foo 的寄存器,当您向其写入值时,uC 会检查是否设置了高位。如果是,则将值写入内存位置1,如果不是,则将值写入内存位置2。
如果您正确使用了URSEL 位,那么这些值将被正确写入。您的测试没有显示正确的值,因为您没有正确阅读它们。数据表第 162 页:
对 UBRRH 或 UCSRC 寄存器进行读访问更
复杂的操作。然而,在大多数应用中,它很少
需要读取这些寄存器中的任何一个。
读取访问由定时序列控制。读取 I/O
位置一次返回 UBRRH 寄存器内容。如果登记表
在上一个系统时钟周期中读取位置,读取寄存器
在当前时钟周期内将返回 UCSRC 内容。注意
读取 UCSRC 的时序是原子操作。
因此必须控制中断(例如通过禁用
在读取操作期间全局中断)。
因此,当您第一次阅读UBRRH / UCSRC 时,您会得到UBRRH。如果您立即再次阅读,您会阅读UCSRC。但正如文档所暗示的,没有真正的理由去读取这些寄存器。您似乎不信任数据表,但这是一个错误:数据表是此类问题的最佳信息来源:没有数据表,我们将一事无成。