答案是:是的, URSEL 位。根据数据表:
URSEL
在对此I / O位置进行写访问时,该位的高位 写入的值,USART寄存器选择(URSEL)位,控制哪个 将要写入的两个寄存器之一。如果URSEL在期间为零 写操作时,UBRRH值将被更新。如果URSEL是一个, UCSRC设置将更新。
这意味着,当你写信给 UCSRC ,无论你想放在什么价值,也设置了 URSEL 位(确保 URSEL 是 1 ):
UCSRC
1
UCSRC = (1<<URSEL)| ... whatever else ...
当你写信给 UBRRH ,确保 URSEL bit必须为零。以下是一些不同的方法:
UBRRH
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 。
foo
2
如果你正在使用 URSEL 正确位,然后正确写入值。您的测试没有显示正确的值,因为您没有正确阅读它们。数据表的第162页:
对UBRRH或UCSRC寄存器进行读访问更多 复杂的操作。然而,在大多数应用中,它很少 必须阅读任何这些寄存器。 读访问由定时序列控制。读I / O. 位置一旦返回UBRRH寄存器内容。如果是注册 在先前的系统时钟周期读取位置,读取寄存器 在当前时钟周期中将返回UCSRC内容。注意 读取UCSRC的定时序列是原子操作。 因此必须控制中断(例如通过禁用 在读操作期间全局中断。
对UBRRH或UCSRC寄存器进行读访问更多 复杂的操作。然而,在大多数应用中,它很少 必须阅读任何这些寄存器。
读访问由定时序列控制。读I / O. 位置一旦返回UBRRH寄存器内容。如果是注册 在先前的系统时钟周期读取位置,读取寄存器 在当前时钟周期中将返回UCSRC内容。注意 读取UCSRC的定时序列是原子操作。 因此必须控制中断(例如通过禁用 在读操作期间全局中断。
所以当你读 UBRRH / UCSRC 这是你第一次得到 UBRRH 。如果你 立即 再读一遍你看了 UCSRC 。但正如文档所示,没有真正的理由来阅读这些寄存器。您似乎不相信数据表,但这是一个错误:数据表是关于此类事项的最佳信息来源:没有数据表,我们将无处可去。