2 线:发送启动条件后,TWINT 不会在 TWCR 中设置

问题描述 投票:0回答:1

我使用的ATmega328P TWI接口如下。

问题是它进入无限循环来选通LED,并且永远不会关闭LED。如果我将条件更改为

TRUE
,则会关闭 LED 并继续。

我已经明确说明了正在设置哪些位;让我知道更多详细信息会有帮助。

PASS_T twi_master_tx(U8_T addr, U8_T* data, SIZE_T len)
{
    /* Set TWINT, TWSTA, and TWEN */
    TWCR.byte = (1u << 7) | (1u << 5) | (1u << 2);

    /* Wait for start condition to be sent. */
    while (FALSE == TWCR.bits.TWINT) {
        dsc_led_toggle(DSC_LED_CANBOARD_1);
    }
    dsc_led_set(DSC_LED_CANBOARD_1, OFF);
    ...

它编译为

    1dc6:   84 ea           ldi r24, 0xA4   ; 164
    1dc8:   80 93 bc 00     sts 0x00BC, r24 ; 0x8000bc <__DATA_REGION_ORIGIN__+0x5c>
    1dcc:   80 91 bc 00     lds r24, 0x00BC ; 0x8000bc <__DATA_REGION_ORIGIN__+0x5c>
    1dd0:   90 e0           ldi r25, 0x00   ; 0
    1dd2:   87 ff           sbrs    r24, 7
    1dd4:   14 c0           rjmp    .+40        ; 0x1dfe <twi_master_tx.constprop.15+0x38>

所以我们知道寄存器(0x00BC)正在被设置,寄存器正在被读取,并且TWINT位(7)正在被测试。

我错过了什么?我以为我严格遵循数据表(特别是第 185 页),但 TWINT 从未被设置为指示 START 传输结束。

根据数据表(第180页),SCL频率= CPU时钟/(16 + 2 * TWBR * Prescale)。我将 TWBR 和 Prescale 设置为 0,所以我应该得到 16-MHz / 16 = 1-MHz。

注意: 我没有使用 avr-gcc 标准库,我使用自己的标准库,因为这是一个学习练习。我知道不建议使用位字段,但我认为我们看到生成的程序集是正确的。这是我的寄存器的链接方式:

SECTIONS {
  /* TWI */
  TWBR          = 0xB8;
  TWSR          = 0xB9;
  TWAR          = 0xBA;
  TWDR          = 0xBB;
  TWCR          = 0xBC;
  TWAMR         = 0xBD;
  ...
c arduino avr atmega avr-gcc
1个回答
0
投票

查看第 199 页的数据表:

第 5 位 – TWSTA:

TWI 启动条件位 当应用程序希望成为 2 线串行总线上的主设备时,将 TWSTA 位写入 1。 TWI 硬件 检查总线是否可用,如果空闲,则在总线上生成 START 条件。不过,如果巴士不是免费的, TWI 等待直到检测到停止条件,然后生成新的启动条件以声明总线主状态。 当 START 条件发送后,TWSTA 必须由软件清零。

如果您想检查启动条件,您必须轮询此位

while (!TWCR & (1<<TWSTA))
{
  asm volatile("NOP");
}

将启动条件写入总线后,TWSTA 标志表示可以完成传输...

© www.soinside.com 2019 - 2024. All rights reserved.