www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik TWI Slave (Atmega8) erkennt weder GC noch seine Adresse


Autor: Axel Krüger (axel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich beschaeftige mich seit gestern mit diesem Problem und komme nicht 
weiter.

Der Master arbeitet korrekt. Das habe ich geprueft, indem ich einen I2C 
Digitalpoti am Bus gehangen habe und einfach dessen Adresse als 
Zieladresse angegeben habe - Kontrolliert habe ich das durch meine 
StatusLEDs am Master.

Der Slave bleibt in der main() haengen, denn er setzt das TWINT flag 
nicht - auch nicht bei einem GC durch den Master.

Hoffe ihr koennt mir ein paar Anregungen geben. PullUps sind vorhanden.

Atmega8 Master:
#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL     /* Quarz mit 8 Mhz */
#endif
#include <util/delay.h>
#include <util/twi.h> 


void init_twi() {  //ca. 30 kHz
  TWBR = 33;
  TWSR = 1;
}


void send_twi() {
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); 
  while  (!(TWCR & (1<<TWINT)));

  TWDR = 0; //General Call
  //TWDR = 0b00101100; //44

  TWCR = (1<<TWINT) | (1<<TWEN);
  while (!(TWCR & (1<<TWINT)));
  if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
  //if ((TWSR & 0xF8) != TW_MT_SLA_NACK)
  PORTD |= (1 << PD3); //LED leuchtet

  TWDR = 0x03; //Testdatenbyte
  TWCR = (1<<TWINT) | (1<<TWEN);
  while (!(TWCR & (1<<TWINT)));
  if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
  PORTD |= (1 << PD4); //LED leuchtet

  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
  PORTD |= (1 << PD2); //LED leuchtet
}


int main (void) {

  DDRD |= (1 << PD2 | 1 << PD3 | 1 << PD4 ); //StatusLEDs
  _delay_ms(1000); //Zeit fuer Slave lassen
  _delay_ms(1000);
  init_twi();

  while (1) {
    send_twi();
    
    _delay_ms(1000);  
 
    PORTD &= ~(1<<PD2 | 1<<PD3 | 1<<PD4); //Status LEDs loeschen
    _delay_ms(1000); 

  } //End while
  return 0;
} //End main





Atmega8 Slave:
#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL     /* Quarz mit 8 Mhz */
#endif
#include <util/twi.h> 


void init_twi() {
  TWAR = 0b01011001; //Eigene Adresse 44 + TWGCE gesetzt
  TWCR = (1<<TWEA | 1<<TWEN);
}


int main(void) {

  DDRD |= (1 << PD0 | 1 << PD1 | 1 << PD2); //StatusLEDs
  init_twi();

  while(1) {
    PORTD |= (1 << PD0); //LED leuchtet
    while  (!(TWCR & (1<<TWINT)));
    PORTD |= (1 << PD1); //LED leuchtet nicht
  }
  return 0;


gruss Axel

Autor: Axel Krüger (axel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm werde mir mal ne testpaltine aetzen nach diesem muster: 
Beitrag "TWI / I2C einf. MASTER SLAVE Beispiel(Assembler) ATmega8"

denke mal alles andere hat kein Sinn

Autor: Axel Krüger (axel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich werde verrueckt!

Die Testplatine ist aufgabaut und funzt auch mit dem Assembler Code - 
jetzt habe ich den Code fuer den Slave 1zu1 von Assembler in C 
uebersetzt und nix geht bzw. Leuchtet - so als ob der IC garnicht im 
Sockel stecken wuerde. Sowohl c als auch asm code bearbeite ich mit AVR 
studio4.

Funktionierender Assemblercode:
; TWI I2C SLAVE                    
; 10/2005                        
; Bernhard.Erfurt@gmx.de        
;                                
; TAKT=1.0 MHZ                    
;                                
.include "m8def.inc"


; TWI Slave Receiver Codes
.equ TW_SR_SLA_ACK            = 0x60; x60    01100000 (SLA+W wurde empfangen-ACK wurde zurückgesendet)                                                    
.equ TW_SR_ARB_LOST_SLA_ACK = 0x68; x68    01101000 (Arbitration verloren in SLA+R/W als MASTER;  SLA+W wurde empfangen;  ACK wurde zurückgesendet        
.equ TW_SR_GCALL_ACK          = 0x70; x70    01110000 (General call address wurde empfangen;  ACK wurde zurückgesendet                                    
.equ TW_SR_ARB_LOST_GCALL_ACK=0x78; x78    01111000 (Arbitration verloren in SLA+R/W als MASTER;General call address wurde empfangen; ACK wurde zurückgesendet
.equ TW_SR_DATA_ACK          = 0x80; x80    10000000 (die vorher adressierten (SLA+W) Daten wurden empfangen;  ACK wurde zurückgesendet                    
.equ TW_SR_DATA_NACK          = 0x88; x88    10001000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde nicht zurückgesedet                
.equ TW_SR_GCALL_DATA_ACK   = 0x90; x90    10010000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde zurückgesendet            
.equ TW_SR_GCALL_DATA_NACK  = 0x98; x98    10011000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde nicht zurückgesendet    
.equ TW_SR_STOP                = 0xA0; xA0    10100000 (STOP wurde empfangen, oder wiederholter Start)                                                    
; TWI Slave Transmitter Codes
.equ TW_ST_SLA_ACK            = 0xA8; xA8 10101000 (SLA+R wurde empfangen; ACK wurde zurückgesendet)                                                
.equ TW_ST_ARB_LOST_SLA_ACK = 0xB0; xB0 10110000 (Arbitration verlor SLA+R/W als MASTER, ACK wurde zurückgesendet)                                
.equ TW_ST_DATA_ACK          = 0xB8; xB8 10111000 (TWDR ist übertragen worden;  ACK ist empfangen worden                                            
.equ TW_ST_DATA_NACK          = 0xC0; xC0 11000000 (TWDR ist übertragen worden;  ACK ist NICHT empfangen worden                                    
.equ TW_ST_LAST_DATA          = 0xC8; xC8 11001000 (Letztes Datenbyte in TWDR ist übertragen worden (TWEA = "0");  Ack ist empfangen worden        
.equ TW_NO_INFO                = 0xF8; xF8 11111000 (Keine relevanten Zustandinformationen vorhanden;  TWINT = "0" keine TWDR-Tätigkeit             
.equ TW_BUS_ERROR            = 0x00; x00 00000000 (Bus-Error wegen ungültige STARToder STOP BEDIgung; keine TWDR-Tätigkeit                         

; TWI SLAVE EINSTELLUNGEN
.equ TWI_SLAVE_ADRESSE        = 127    ; eigene SLAVE ADRESSE 1...127            
.equ TWI_GENERAL_CALL_enable        = 1        ; 1=Generral Call enabled / 0=disabled    
; REGISTER
.def DATA=R15

.def TEMP = R16
.def TEMP1= R17
.def TEMP2= R18
.def TEMP3= R19
.def TEMP4= R20


.cseg                    ;Beginn eines Code-Segmentes
.org 0                    ;Startadresse=0

rjmp RESET      ; Reset Handler                           
reti ;rjmp EXT_INT0   ; IRQ0 Handler                      
reti ;rjmp EXT_INT1   ; IRQ1 Handler                      
reti ;rjmp TIM2_COMP  ; Timer2 Compare Handler            
reti ;rjmp TIM2_OVF   ; Timer2 Overflow Handler           
reti ;rjmp TIM1_CAPT  ; Timer1 Capture Handler            
reti ;rjmp TIM1_COMPA ; Timer1 CompareA Handler           
reti ;rjmp TIM1_COMPB ; Timer1 CompareB Handler           
reti ;rjmp TIM1_OVF   ; Timer1 Overflow Handler           
reti ;rjmp TIM0_OVF   ; Timer0 Overflow Handler           
reti ;rjmp SPI_STC    ; SPI Transfer Complete Handler     
reti ;rjmp USART_RXC  ; USART RX Complete Handler         
reti ;rjmp USART_UDRE ; UDR Empty Handler                 
reti ;rjmp USART_TXC  ; USART TX Complete Handler         
reti ;rjmp ADC        ; ADC Conversion Complete Handler   
reti ;rjmp EE_RDY     ; EEPROM Ready Handler              
reti ;rjmp ANA_COMP   ; Analog Comparator Handler         
rjmp TWSI             ; Two-wire Serial Interface Handler 
reti ;rjmp SPM_RDY    ; Store Program Memory Ready Handler





RESET:                        
    
;STACK initialisieren        
    ldi temp, LOW(RAMEND)
    out SPL, temp
    ldi temp, HIGH(RAMEND)
    out SPH, temp
; PORT B + D alles AUSGÄNGE    
    ldi temp, 0b11111111
    out DDRB, temp
    out PORTB,temp
    out DDRD, temp
    out PORTD,temp
; PORT C alles EINGÄNGE        
    clr TEMP
    out DDRC,temp
; TWI INITIALISIERUNG        
    rcall TWI_INI
; STARTWERTE                
    clr DATA
; alle Interrupts freigeben
sei 


LOOP:


rjmp LOOP


; #############################################################################
; #############################################################################
; #############################################################################
; TWI INTERRUPPT-Routine        
TWSI:
    push temp           ; temp auf dem Stack sichern            
    in TEMP,SREG        ; Einlesen des SREG 
    push TEMP            ; Schreiben von  SREG  im Stack (KOPIE)
;-------
    
    in temp, TWSR        ; Status-Register abfragen                        
    andi temp, 0xF8        ; Bit0...2 ausblenden (Prescaler und Reserve-Bit)
    
    cpi temp, TW_SR_SLA_ACK                 ; x60    
    breq TWSI_TW_SR_SLA_ACK
    cpi temp, TW_SR_ARB_LOST_SLA_ACK     ; x68    
    breq TWSI_TW_SR_ARB_LOST_SLA_ACK
    cpi temp, TW_SR_GCALL_ACK            ; x70    
    breq TWSI_TW_SR_GCALL_ACK
    cpi temp, TW_SR_ARB_LOST_GCALL_ACK    ; x78    
    breq TWSI_TW_SR_ARB_LOST_GCALL_ACK
    cpi temp, TW_SR_DATA_ACK              ; x80    
    breq TWSI_TW_SR_DATA_ACK          
    cpi temp, TW_SR_DATA_NACK              ; x88    
    breq TWSI_TW_SR_DATA_NACK
    cpi temp, TW_SR_GCALL_DATA_ACK       ; x90    
    breq TWSI_TW_SR_GCALL_DATA_ACK   
    cpi temp, TW_SR_GCALL_DATA_NACK        ; x98    
    breq TWSI_TW_SR_GCALL_DATA_NACK
    cpi temp, TW_SR_STOP                ; xA0    
    breq TWSI_TW_SR_STOP            
;     
    cpi temp, TW_ST_SLA_ACK                ; 0xA8     
    breq TWSI_TW_ST_SLA_ACK    
    cpi temp, TW_ST_ARB_LOST_SLA_ACK    ; 0xB0     
    breq TWSI_TW_ST_ARB_LOST_SLA_ACK
    cpi temp, TW_ST_DATA_ACK              ; 0xB8    
    breq TWSI_TW_ST_DATA_ACK
    cpi temp, TW_ST_DATA_NACK              ; 0xC0    
    breq TWSI_TW_ST_DATA_NACK
    cpi temp, TW_ST_LAST_DATA              ; 0xC8    
    breq TWSI_TW_ST_LAST_DATA 
    cpi temp, TW_NO_INFO                ; 0xF8    
    breq TWSI_TW_NO_INFO
    cpi temp, TW_BUS_ERROR                ; 0x00    
    breq TWSI_TW_BUS_ERROR 
    rjmp TWSI_TW_BUS_ERROR                ; nicht behandelte Status-Zustände    

; SLAVE RECEIVER                
TWSI_TW_SR_SLA_ACK:                        ; x60    01100000 (SLA+W wurde empfangen-ACK wurde zurückgesendet)
    ldi temp, 255
    out PORTB,temp    ; LED's alle aus
    cbi PORTB,0
    rjmp TWSI_w
TWSI_TW_SR_ARB_LOST_SLA_ACK:            ; x68    01101000 (Arbitration verloren in SLA+R/W als MASTER;  SLA+W wurde empfangen;  ACK wurde zurückgesendet
    cbi PORTB,1
    rjmp TWSI_w
TWSI_TW_SR_GCALL_ACK:                    ; x70    01110000 (General call address wurde empfangen;  ACK wurde zurückgesendet        
    cbi PORTB,2
    rjmp TWSI_w
TWSI_TW_SR_ARB_LOST_GCALL_ACK:            ; x78    01111000 (Arbitration verloren in SLA+R/W als MASTER;General call address wurde empfangen; ACK wurde zurückgesendet
    cbi PORTB,3
    rjmp TWSI_w
TWSI_TW_SR_DATA_ACK:                    ; x80    10000000 (die vorher adressierten (SLA+W) Daten wurden empfangen;  ACK wurde zurückgesendet    
    cbi PORTB,4
    in DATA, TWDR    ; DATA
    rjmp TWSI_w
TWSI_TW_SR_DATA_NACK:                      ; x88    10001000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde nicht zurückgesedet
    cbi PORTB,5
    rjmp TWSI_w
TWSI_TW_SR_GCALL_DATA_ACK:                ; x90    10010000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde zurückgesendet    
    cbi PORTB,6
    rjmp TWSI_w
TWSI_TW_SR_GCALL_DATA_NACK:                ; x98    10011000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde nicht zurückgesendet    
    cbi PORTB,7
    rjmp TWSI_w
TWSI_TW_SR_STOP:                        ; xA0    10100000 (STOP wurde empfangen, oder wiederholter Start)
    cbi PORTB,7
    rjmp TWSI_w
;    SLAVE TRANSMITTER        
TWSI_TW_ST_SLA_ACK:                        ; xA8     10101000 (SLA+R wurde empfangen; ACK wurde zurückgesendet)        
    ldi temp,255
    out PORTB,temp        ; LEDs alle aus
    cbi PORTB,0    
    OUT TWDR, DATA        ; DATA
    rjmp TWSI_w
TWSI_TW_ST_ARB_LOST_SLA_ACK:            ; xB0     10110000 (Arbitration verlor SLA+R/W als MASTER, ACK wurde zurückgesendet)    
    cbi PORTB,1
    rjmp TWSI_w
TWSI_TW_ST_DATA_ACK:                    ; xB8    10111000 (TWDR ist übertragen worden;  ACK ist empfangen worden
    cbi PORTB,2    
    OUT TWDR, DATA        ; DATA
    rjmp TWSI_w
TWSI_TW_ST_DATA_NACK:                    ; xC0    11000000 (TWDR ist übertragen worden;  ACK ist NICHT empfangen worden
    cbi PORTB,3    
    OUT TWDR, DATA        ; DATA
    rjmp TWSI_w
TWSI_TW_ST_LAST_DATA:                    ; xC8    11001000 (Letztes Datenbyte in TWDR ist übertragen worden (TWEA = "0");  Ack ist empfangen worden
    cbi PORTB,4    
    rjmp TWSI_w
TWSI_TW_NO_INFO:                        ; xF8    11111000 (Keine relevanten Zustandinformationen vorhanden;  TWINT = "0" keine TWDR-Tätigkeit 
    cbi PORTB,5    
    rjmp TWSI_w
TWSI_TW_BUS_ERROR:                        ; x00    00000000 (Bus-Error wegen ungültige STARToder STOP BEDIgung; keine TWDR-Tätigkeit 
    rcall TWI_ERROR    

    rjmp TWSI_w

;-------
TWSI_w:    
    
    rcall wait_1s        ; diese Warteschleife ist nicht nötig, kann entfernd werden

;das TWINT-Flag löschen ((logisch 1)    
    ldi temp, 1<<TWINT|1<<TWEA|1<<TWEN|1<<TWIE
    out TWCR,temp


;-------
        pop    TEMP            ; LESEN von SREG vom STACK (KOPIE)
        out    SREG,TEMP        ; Wiederherstellen von SREG       
        pop temp              ; temp wiederherstellen                    

reti
; #############################################################################
; #############################################################################
; #############################################################################
TWI_INI:
    ; TWI TWAR (nur SLAVE)     Adress-Register        
    ldi temp,(TWI_SLAVE_ADRESSE<<TWA0 | TWI_GENERAL_CALL_ENABLE<<TWGCE)
    out TWAR,temp
    ; TWI TWCR                 Control-REGISTER    
    ldi temp, 1<<TWINT|1<<TWEA|0<<TWSTA|0<<TWSTO|0<<TWWC|1<<TWEN|1<<TWIE
    out TWCR,temp
ret
; #############################################################################
; #############################################################################
; #############################################################################
TWI_ERROR:

    cbi PORTD,0

; TWI STOP                
    ldi r16, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
    out TWCR, r16
; TWI aus                
    ldi r16, (0<<TWEN)
    out TWCR, r16
; TWI INITIALISIERUNG    
     rcall TWI_INI
    
    rcall wait_1s
    
    sbi PORTD,0


ret
; #############################################################################
; #############################################################################
; #############################################################################
; Wait for TWINT Flag set. 
TWI_TWINT_wait:
    in temp, TWCR
    sbrs temp, TWINT
    rjmp TWI_TWINT_wait
ret
; #############################################################################
; #############################################################################
; #############################################################################
WAIT_1s:
    push temp1           ; temp1 auf dem Stack sichern            
    push temp2           ; temp2 auf dem Stack sichern            
    push temp3           ; temp3 auf dem Stack sichern            

;------------
    ldi    temp3,5            
    clr temp2
    clr    temp1            
wait1s_w:    
    dec    temp1
    brne    wait1s_w
    dec    temp2        
    brne    wait1s_w
    dec    temp3
    brne    wait1s_w
;------------
    pop temp3              ; temp3 wiederherstellen                    
    pop temp2              ; temp2 wiederherstellen                    
    pop temp1              ; temp1 wiederherstellen                    
ret

Mein nicht funktionierende C-Code:
#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 1000000UL     /* Quarz mit 1 Mhz */
#endif
#include <util/twi.h> 
#include <util/delay.h>
#include <avr/interrupt.h>

//TWI SLAVE EINSTELLUNGEN
#define TWI_SLAVE_ADRESSE 127  //eigene SLAVE ADRESSE 1...127
#define TWI_GENERAL_CALL_enable 1 //1=Generral Call enabled / 0=disabled


void init_twi() {
  TWAR = (TWI_SLAVE_ADRESSE << 1 | TWI_GENERAL_CALL_enable << TWGCE);  
  TWCR = (1<<TWINT | 1<<TWEA | 1<<TWEN | 1<<TWIE);
}


void TWSI_w(){
  _delay_ms(1000); //diese Warteschleife ist nicht nötig, kann entfernd werden
  
  TWCR = (1<<TWINT | 1<<TWEA | 1<<TWEN | 1<<TWIE); //das TWINT-Flag löschen ((logisch 1)
}

void TWI_ERROR (){
  PORTD &= ~(1 << PD0);
  
  //TWI STOP
  TWCR = (1<<TWINT | 1<<TWEN | 1<<TWSTO);

  //TWI aus
  TWCR = 0x00;
  
  //TWI INITIALISIERUNG
  init_twi();

  TWSI_w();

  PORTD &= ~(1<<PD0);
}

ISR(TWI_vect){ //Two-wire Serial Interface Handler
  
  switch (TWSR & 0xF8){

  //SLAVE RECEIVER
    
    case TW_SR_SLA_ACK:
      PORTB = 0xFF;
      PORTB &= ~(1<<PB0);
      TWSI_w();
      break;
 
    case TW_SR_ARB_LOST_SLA_ACK:
      PORTB &= ~(1<<PB1);
      TWSI_w();
      break;
    
    case TW_SR_GCALL_ACK:
      PORTB &= ~(1<<PB2);
      TWSI_w();
      break;

    case TW_SR_ARB_LOST_GCALL_ACK:
      PORTB &= ~(1<<PB3);
      TWSI_w();
      break;

    case TW_SR_DATA_ACK:
      PORTB &= ~(1<<PB4);
      TWSI_w();
      break;

    case TW_SR_DATA_NACK:
      PORTB &= ~(1<<PB5);
      TWSI_w();
      break;

    case TW_SR_GCALL_DATA_ACK:
      PORTB &= ~(1<<PB6);
      TWSI_w();
      break;

    case TW_SR_GCALL_DATA_NACK:
      PORTB &= ~(1<<PB7);
      TWSI_w();
      break;

    case TW_SR_STOP:
      PORTB &= ~(1<<PB7);
      TWSI_w();
      break;

  //SLAVE TRANSMITTER

    case TW_ST_SLA_ACK:
      PORTB = 0xFF;
      PORTB &= ~(1<<PB0);
      TWDR = 0x11;  //Testbyte
      TWSI_w();
      break;

    case TW_ST_ARB_LOST_SLA_ACK:
      PORTB &= ~(1<<PB1);
      TWSI_w();
      break;

    case TW_ST_DATA_ACK:
      PORTB &= ~(1<<PB2);
      TWDR = 0x12; //Testbyte
      TWSI_w();
      break;

    case TW_ST_DATA_NACK:
      PORTB &= ~(1<<PB3);
      TWDR = 0x13; //Testbyte
      TWSI_w();
      break;

    case TW_ST_LAST_DATA:
      PORTB &= ~(1<<PB4);
      TWSI_w();
      break;

    case TW_NO_INFO:
      PORTB &= ~(1<<PB5);
      TWSI_w();
      break;

    case TW_BUS_ERROR:
      TWI_ERROR();
      TWSI_w();
      break;
  }
    
}





int main(void) {

  DDRB = 0xFF;  //Alle Pins auf Ausgang
  PORTB = 0xFF;
  DDRD = 0xFF;  //Alle Pins auf Ausgang
  PORTD = 0xFF;
  DDRC = 0x00;  //PORT C alles EINGÄNGE
  
  init_twi(); //TWI INITIALISIERUNG

  sei(); //alle Interrupts freigeben

  while(1) {

  }
  
  return 0;

}

Autor: Axel Krüger (axel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unter "Configuration Options" stand ein ATmega128....... grrrr

Alles bestens! :)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.