AVR TWI(I2C)问题:操作数1超出范围

时间:2019-06-16 21:44:35

标签: avr i2c atmega atmelstudio

我正在使用Atmega2560和24c16A EEPROM测试I2C代码。对于每个状态转换,控制器都会通过更改状态寄存器TWSR做出响应。发送启动条件后,EEPROM响应,然后对设备地址和写入指令(SLA + R / W)进行响应,状态寄存器更新正常。但是,当我发送下一个8位而不是ACK(数据字节发送ACK)时,状态将更改为重复开始。代码如下。我永远找不到找到可行的解决方案。

.include "./m2560def.inc"
.list
.cseg
.org 0x00
jmp inicio      ; PC = 0x0000   RESET

inicio:
    LDI R21, HIGH(RAMEND)           ;Set Up Stack
    OUT SPH, R21
    LDI R21, LOW(RAMEND)    
    OUT SPL, R21

    CALL I2C_INIT                   ;Initialize TWI(I2C)
    CALL I2C_START                  ;Transmit START condition
    LDI  R27, 0b11010000            ;SLA(0b1001100) + W(0)
    CALL I2C_WRITE                  ;Write R27 ato the I2C bus
    LDI  R27, 0b11110000            ;Data to be transmitted
    CALL I2C_WRITE                  ;Write R27 ato the I2C bus
    CALL I2C_STOP                   ;Transmit STOP condition

HERE: RJMP HERE

;----------------------------I2C_INIT-----------------------------
I2C_INIT:
     LDI    R21, 0              
     OUT    TWSR, R21           ;Set prescaler bits to 0
     LDI    R21, 0x47           ;R21 = 0x47
     OUT    TWBR, R21           ;Fclk = 50 KHz (8 MHz Xtal)
     LDI    R21, (1<<TWEN)      ;R21 = 0x04
     OUT    TWCR, R21           ;HEnable TWI (I2C)
     RET

;----------------------------I2C_START-----------------------------
I2C_START: 
     LDI    R21, (1<<TWINT)|1<<(TWSTA)|(1<<TWEN)
     OUT    TWCR, R21           ;Transmit START condition
 WAIT1:  
     IN     R21, TWCR           ;Read Control Register TWCR into R21
     SBRS   R21, TWINT          ;Skip the next line if TWINT is 1
     RJMP   WAIT1               ;Jump a WAIT1 if TWINT is 1
     RET  

 ;----------------------------I2C_WRITE -----------------------------
 I2C_WRITE:
     OUT    TWDR, R27           ;Move the byte into TWRD
     LDI    R21,  (1<<TWINT)|(1<<TWEN)
     OUT    TWCR, R21           ;Configure TWCR to send TWDR
  WAIT3:
     IN     R21, TWCR           ;Read Control Register TWCR into R21
     SBRS   R21, TWINT          ;Skip the next line if TWINT is 1
     RJMP   WAIT3               ;Jump a WAIT3 if TWINT is 1
     RET

 ;----------------------------I2C_STOP------------------------------
 I2C_STOP:
     LDI    R21, (1<<TWINT)|1<<(TWSTO)|(1<<TWEN)
     OUT    TWCR, R21           ;Transmit STOP condition
     RET

;----------------------------I2C_READ------------------------------
I2C_READ:
     LDI    R21,  (1<<TWINT)|(1<<TWEN)
     OUT    TWCR, R21   
WAIT2:
    IN      R21, TWCR           ;Read Control Register TWCR into R21
    SBRS    R21, TWINT          ;Skip the next line if TWINT is 1
    RJMP    WAIT2               ;Jump a WAIT2 if TWINT is 1
    IN      R27, TWCR           ;Read received data into R21
    RET

输出为

D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(41,0): error: Operand 1 out of range: 0xb9
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(43,0): error: Operand 1 out of range: 0xb8
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(45,0): error: Operand 1 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(51,0): error: Operand 1 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(53,0): error: Operand 2 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(60,0): error: Operand 1 out of range: 0xbb
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(62,0): error: Operand 1 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(64,0): error: Operand 2 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(72,0): error: Operand 1 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(78,0): error: Operand 1 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(80,0): error: Operand 2 out of range: 0xbc
D:\ATMEL_AVR\I2C_TWI\I2C_TWI.asm(83,0): error: Operand 2 out of range: 0xbc
    Assembly failed, 12 errors, 0 warnings

这些错误涉及的代码行是:

     OUT    TWSR, R21
     OUT    TWBR, R21
     OUT    TWCR, R21
     OUT    TWCR, R21
     IN     R21, TWCR   
     OUT    TWDR, R27
     OUT    TWCR, R21
     IN     R21, TWCR
     OUT    TWCR, R21
     OUT    TWCR, R21
     IN     R21, TWCR
     IN     R27, TWCR

1 个答案:

答案 0 :(得分:1)

在AVR中,通常所有I / O寄存器都从地址0x0020开始映射到内存空间中

inout指令只能与前64个指令一起使用(具有0x20 ... 0x5F的存储器地址)  sbicbisbissbic还有更多限制,只能与前32个I / O注册(内存地址0x20 ... 0x3F)一起使用。请参阅AVR Instruction Set Manual

datasheet to ATmega2560的第33页“寄存器摘要”的第401页中,您可以看到TWI寄存器的地址为0xB8至0xBD,即,无法使用inout来访问它们说明。您必须使用STSLDS。 即LDS R21, TWCR代替IN R21, TWCR等。

此外,访问前64个寄存器时请务必小心。确保相应的名称定义了它们的I / O,而不是RAM地址。即PORTA应该等于0x02(in / out指令的IO地址),而不是0x22(RAM地址或PORTA,当使用inout访问时,其等于到EEARH寄存器)。