Forum: Mikrocontroller und Digitale Elektronik ATXMEGA, TWI und die internen pullups


von Holger M. (_holger)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich habe die AppNote "AVR1308: Using the XMEGA TWI" auf meinem 
ATXMEGA32A4U installiert und ein wenig damit rumgespielt.
Die erfreuliche Nachricht ist, dass ich Daten über den BUS rausschicken 
kann.
Die unerfreuliche Nachricht ist, dass ich auf meinem Board (eigentlich) 
keinen Platz für externe Pullup-Widerstände vorgesehen habe, in der 
Hoffnung, das es die Internen schon richten werden.

Im Beispielprogramm läuft die CPU mit 2MHz und generiert einen SCL von 
100kHz.
Am BUS hängt bislang noch gar nichts und die SDA/SCL Testpins sitzen an 
zwei parallelen, je rund 2cm langen, 10mil dicken Leiterbahnen, die zur 
Masse-Plane und zueinander je 10mil Abstand haben... also bildlich 
geschrieben:

GND, 10mil Luft, 10mil SCL, 10mil Luft, 10mil SDA, 10mil Luft, GND

Ich rechne also mit vernachlässigbar kleinen Leitungskapazitäten. 
Dennoch kommt da beileibe kein Rechteck aus dem Port... bei 100kHz ist 
das Signal sogar komplett unbrauchbar. (siehe Foto)

ATMEL wird das sicher nicht so geplant haben.
Mit 4,7k Pullups parallel zu den internen wirde es besser, aber immer 
noch nicht gut.

Wenn ich die internen Pullups ausschalte bekomme ich gar kein Signal 
mehr, aber das mag schlicht an meinen Programmierkünsten liegen.

Die Frage ist: Kann man die internen TotemPole with Pullup Widerstände 
überhaupt so hinbiegen, dass sich daran ein 400kHz TWI Bus betreiben 
lässt, oder sollte man ohnehin lieber zu externen greifen?

Gruß,

Holger

von spess53 (Gast)


Lesenswert?

Hi

>Die Frage ist: Kann man die internen TotemPole with Pullup Widerstände
>überhaupt so hinbiegen, dass sich daran ein 400kHz TWI Bus betreiben
>lässt, oder sollte man ohnehin lieber zu externen greifen?

Lies mal ab S.55

http://www.google.de/url?sa=t&rct=j&q=i2c%20spezifikation&source=web&cd=2&ved=0CGgQFjAB&url=http%3A%2F%2Fwww.nxp.com%2Fdocuments%2Fuser_manual%2FUM10204.pdf&ei=0eAGUIaWDNDgtQb815HdBg&usg=AFQjCNG5emVs3tU5RbGVKjblTMFgLLHdqg&cad=rja

MfG Spess

von Timmo H. (masterfx)


Angehängte Dateien:

Lesenswert?

Sieht bei mir auch so aus (mit 4.7k und 3 Slaves dran). Funktioniert 
aber einwandfrei mit den I²C -Slaves :D

von Stefan F. (sfrings)


Lesenswert?

Ohne Pull-Ups funktioniert es deswegen nicht, weil der Mikrocontroller 
die Ausgänge auf Low zieht, aber es ist nichts da, wass sie auf High 
zieht.

Die internen Pull-Ups reichen nicht aus, sie sind zu hochohmig. I2C wird 
normalwerweise mit 4,7k oder 10k Ohm terminiert. Die Pull-Ups im AVR 
haben bei 5 Volt ungefähr 50-100k Ohm.

Du hast zwar keine Last bewusst angeschlossen, aber dein Oszilloskop ist 
eine signifikante Last. Oszilloskope haben eine nicht zu unterschätzende 
Eingangskapazität. Deswegen fallen Quarz-Taktgeber auch ab und zu aus, 
sobald man ein Oszilloskop anschießt.

von Holger M. (_holger)


Lesenswert?

spess53 schrieb:
> Lies mal ab S.55

Hab ich ja.
In der Spezifikation steht auch, dass das die rise time bei 100kHz von 
30%-70% maximal 1000ns betragen sollte... mit den internen Pullups lande 
ich bei 100kHz aber schon bei 5000ns. Bei 400kHz kommt das Signal gar 
nicht erst in die nähe von 70% Vcc.

Timmo H. schrieb:
> Funktioniert
> aber einwandfrei mit den I²C -Slaves :D

Aber nur bei 200kHz... oder auch bei 2MHz?! :O

Stefan Frings schrieb:
> Ohne Pull-Ups funktioniert es deswegen nicht, weil der Mikrocontroller
> die Ausgänge auf Low zieht

Ich meinte ohne Interne, aber dafür mit externen Pullups funktionierte 
es nicht. Da bin ich aber scheinbar noch zu doof den Port vernünftig zu 
konfigurieren.

> Die internen Pull-Ups [...] haben bei 5 Volt ungefähr 50-100k Ohm.
Wo steht denn das? Angaben zu den tatsächlichen Werten habe ich bislang 
nirgends gefunden.

Nach nochmaligem Lesen steht im Manual aber tatsächlich explizit, dass 
für TWI externe pullups benötigt werden :/
Ich ging vorher davon aus, dass die automatisch in dem Wertebereich 
liegen, der auf Seite 112 "Value of pull-up resistor" im A4U Datenblatt 
angegeben ist... dabei sind dort nur die Anforderungen für einen TWI-Bus 
aufgelistet... herrje...

> Oszilloskope haben eine nicht zu unterschätzende
> Eingangskapazität.

Die von meinem schätze ich immer auf 100-200pF. Genau richtig um den Bus 
um seinen Arbeitspunkt rum zu belasten ;)



Was ich allerdings noch nicht verstehe ist, wie der XMEGA problemlos 
ohne externe Beschaltung einen 48MHz USB-Bus betreiben kann, und im 
Gegenzug beim 100kHz TWI so ins straucheln kommt?

von Konrad S. (maybee)


Lesenswert?

TWI/I²C arbeitet mit Open-Collector (Wired-AND). Pull-Up/Pull-Down gibt 
es nur bei Input-Pins. Daraus ergibt sich, dass es nur mit externen 
Pull-Ups funktionieren kann. Totem-Pole kann nicht gehen, weil sonst die 
Gegenstelle keinen Einfluss auf den Protokoll-Ablauf nehmen kann und 
somit das Handshake nicht mehr funktioniert.
Ich habe auf die Schnelle keine Aussage im Datenblatt gefunden, aber ist 
wohl so, dass durch die Aktivierung der TWI-Schnittstelle die 
zugehörigen Pins automatisch konfiguriert werden.

von Aktion gerade Kamera (Gast)


Angehängte Dateien:

Lesenswert?

Holger M. schrieb:
> atxmega_twie_slew_rate.JPG

TWI heißt der Bus

von Timmo H. (masterfx)


Lesenswert?

Holger M. schrieb:
> Timmo H. schrieb:
>> Funktioniert
>> aber einwandfrei mit den I²C -Slaves :D
>
> Aber nur bei 200kHz... oder auch bei 2MHz?! :O
Also der Beschleunigungssensor liefert bei 2 MHz noch Daten :D Sehe aber 
keinen Sinn darin das in der Praxis so schnell laufen zu lassen. Für 
schnellere Übertragungsraten ist eher SPI oder so angesagt.

von Pako (Gast)


Lesenswert?

Holger M. schrieb:
> Ich meinte ohne Interne, aber dafür mit externen Pullups funktionierte
> es nicht. Da bin ich aber scheinbar noch zu doof den Port vernünftig zu
> konfigurieren.

Zeig doch mal her.

Im Grunde mußt Du:
1. Bei einer logischen 0 das DDR-Bit setzen und das PORT-Bit löschen.
-> Es wird eine starke 0 "getrieben".
2. Bei einer logsichen 1 das DDR-Bit löschen (und ggf. das PORT-Bit 
setzen).
-> Der Ausgang wird abgeschaltet und der Pullup oder ein Slave kann ihn 
treiben.

von spess53 (Gast)


Lesenswert?

Hi

>Zeig doch mal her.

>Im Grunde mußt Du:
>....

Bei Hardware-TWI muss er das nicht.

MfG Spess

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

spess53 schrieb:
>>Im Grunde mußt Du:
>>....

Beim XMEGA ist eh alles anders, da werden die PULLUPs nicht über DDR 
sondern über das PORTCFG-Register ein- und ausgeschaltet. Und das 
unabhängig von über die Portpins geroutete Hardware. Letzlich helfen 
aber in diesem Fall nur externe PULLUPs. In 0402 sind die auch ziemlich 
unauffällig.

von Holger M. (_holger)


Lesenswert?

Konrad S. schrieb:
> Daraus ergibt sich, dass es nur mit externen
> Pull-Ups funktionieren kann.

Ich bin mir da noch nicht ganz sicher, schließlich wird in der AppNote 
ein Codeschnipsel zum Einkommentieren angeboten, falls man gerade keine 
eigenen Pull-Ups zur Hand hat. (Siehe Zeile 55f.)

Ich hab nun aber schon an mehreren inoffiziellen Stellen gelesen, dass 
die ~100kOhm groß sein sollen und damit einfach unpassend für TWI>10kHz.

Aktion gerade Kamera schrieb:
> TWI heißt der Bus

Danke für's geradebiegen :)
Mit TWIE ist übrigens der Bus an Port E und nicht etwa der an Port C 
gemeint.

Timmo H. schrieb:
> Sehe aber
> keinen Sinn darin das in der Praxis so schnell laufen zu lassen.

Ein bißchen Spielraum nach oben kann aber auch nie schaden :)
Mein Respekt ist jedenfalls dir!

Pako schrieb:
> Zeig doch mal her.

Siehe unten.
Den oben erwähnten Atmel Kot habe ich letztendlich angewiedert in die 
Ecke geworfen und mir was eigenes gebastelt.
Bislang kann es nichts außer sinnlose Daten auf Port E auswerfen.
Sobald ich die (N)ACKs richtig verteilt habe und weiß, dass es 
funktioniert werde ich es in Funktionen und Interrupts verpacken, aber 
falls schon jetzt jemandem grobe oder feine Schnitzer auffallen sollten, 
nur raus damit!

Es läuft jetzt, nach dem neu Programmieren auch problemlos an schlampig 
verlöteten, externen Pull-Ups.
Nicht ganz so steil wie ich mir erhofft hatte, aber 400kHz sollten denke 
ich drin sein... 100kHz sind flankentechnisch auf jeden Fall Normgerecht 
:)
1
// Define desired CPU-Speed for delay.h
2
#define F_CPU 32000000
3
4
// Include dependencies
5
#include <avr/io.h>
6
#include <avr/delay.h>
7
#include <avr/interrupt.h>
8
9
// Define TWI parameters
10
#define CPU_SPEED F_CPU
11
#define TWI_SPEED 100000
12
#define TWI_BAUD_RATE ((CPU_SPEED / (2 * TWI_SPEED)) - 5)
13
#define TWIM_WRITE_BUFFER_SIZE 8
14
#define TWIM_READ_BUFFER_SIZE 8
15
#define SLAVE_ADDRESS 0xAA
16
17
// Define global variables
18
int tcc0_cca_interrupt_counter = 100;      
19
20
int main(void) {
21
  // Setup CPU clock
22
  OSC.CTRL = OSC_RC32MEN_bm;        // Enable internal 32MHz RC oscillator
23
  while(!(OSC.STATUS & OSC_RC32MRDY_bm));  // Wait for stable operation
24
  CCP = CCP_IOREG_gc;            // Gain access to the protected ConfigRegister for 4 clock cycles
25
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;    // Set the internal 32MHz RC oscillator as system clock
26
  
27
  // Define local variables
28
  int i = 0; // Loop counter
29
  unsigned char twi_data[TWIM_WRITE_BUFFER_SIZE]; // TWI send buffer
30
  
31
  // Fill the TWI send buffer with dummy bytes
32
  for (i=0;i<TWIM_WRITE_BUFFER_SIZE;i++) twi_data[i] = i*i;
33
  
34
  // Setup interrupts
35
  sei(); // Enable interrupt handler
36
  PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; // Enable high, medium and low level interrupts
37
  
38
  // Setup Timer/Counter
39
  TCC0.INTCTRLA = TC0_OVFINTLVL_gm;   // Enable overflow interrupt
40
  TCC0.INTCTRLB = TC0_CCAINTLVL_gm;   // Enable compare interrupt A
41
  TCC0.CCA = 100;            // Compare capture A threshold
42
  TCC0.PER = 200;            // Timer overflow threshold
43
  TCC0.CTRLA = TC_CLKSEL_DIV8_gc;     // Activate timer 0 and divide system clock by 8 => f=4MHz, t=250ns
44
  
45
  // Setup PORTC pin2 & pin3 as output to toggle status LEDS
46
  PORTC.DIR = PIN2_bm | PIN3_bm;  // Set pins as output
47
  PORTC.OUT = PIN3_bm | PIN3_bm;  // Switch LEDs off
48
  
49
  // Setup TWI bus
50
  TWIE.MASTER.BAUD = TWI_BAUD_RATE; // Set TWI baud rate
51
  TWIE.MASTER.CTRLA = TWI_MASTER_INTLVL_LO_gc | TWI_MASTER_RIEN_bm | TWI_MASTER_WIEN_bm | TWI_MASTER_ENABLE_bm; // Enable TWIE module
52
  TWIE.MASTER.CTRLB = TWI_MASTER_TIMEOUT_200US_gc; // Set TWIE inactivity timeout to 200µs
53
  TWIE.MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc; // Force TWIE module to be idle
54
  
55
  // Enable internal TWIE pull-up resistors 
56
  //PORTCFG.MPCMASK = 0x03; // Configure several PINxCTRL registers at the same time
57
  //PORTE.PIN0CTRL = (PORTE.PIN0CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLUP_gc; //Enable totem-pole pull-up resistors
58
  //PORTE.PIN0CTRL = (PORTE.PIN0CTRL & ~PORT_OPC_gm) | PORT_OPC_WIREDANDPULL_gc; //Enable wired-and pull-up resistors
59
  
60
  while (1) {
61
    // Send TWI slave address
62
    PORTC.OUTCLR = PIN3_bm;  // Set TWI-Busy status LED        
63
    TWIE.MASTER.ADDR = SLAVE_ADDRESS; // Send address
64
    while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm)); // Wait for TWI to be idle again
65
    PORTC.OUTSET = PIN3_bm; // Reset TWI-Busy status LED
66
    
67
    // Send TWI data
68
    i = 0;
69
    do {
70
      // Send one byte to TWI slave
71
      PORTC.OUTCLR = PIN3_bm; // Set TWI-Busy status LED
72
      TWIE.MASTER.DATA = twi_data[i]; // Send byte
73
      while(!(TWIE.MASTER.STATUS & TWI_MASTER_WIF_bm)); // Wait for TWI to be idle again
74
      PORTC.OUTSET = PIN3_bm; // Reset TWI-Busy status LED
75
      i++;
76
    } while (i<TWIM_WRITE_BUFFER_SIZE);    
77
    
78
    _delay_ms(1); // Halt program to synchronize with oscilloscope
79
              
80
  }
81
}
82
83
// TC0 overflow interrupt handle
84
ISR (TCC0_OVF_vect) {
85
  // Do nothing yet
86
}
87
88
// TC0 compare capture A interrupt handle
89
ISR (TCC0_CCA_vect) {
90
  // Toggle "Watchdog LED"
91
  if (--tcc0_cca_interrupt_counter<=0) {
92
    PORTC.OUTTGL = PIN2_bm; // Toggle LED at PORTC pin2
93
    tcc0_cca_interrupt_counter = 10000; // Set interval to 10000*100*250ns = 250ms
94
  }
95
}

von Konrad S. (maybee)


Lesenswert?

Holger M. schrieb:
>> Daraus ergibt sich, dass es nur mit externen
>> Pull-Ups funktionieren kann.
>
> Ich bin mir da noch nicht ganz sicher,

Wenn der Pull-Up nur während Input aktiv ist, wer oder was soll bei 
einem Open-Collector-Ausgang einen High-Pegel auf die Leitung bringen.

Andere Situation: Du hast sehr viele Teilnehmer auf dem Bus. Wenn alle 
die Pull-Ups aktiviert haben, dann tut sich nichts mehr. Wenn nur einer 
die Pull-Ups aktiviert hat und der wird ausgeschaltet, dann tut sich 
schon wieder nichts mehr.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Holger M. schrieb:
>> Die internen Pull-Ups [...] haben bei 5 Volt ungefähr 50-100k Ohm.
> Wo steht denn das? Angaben zu den tatsächlichen Werten habe ich bislang
> nirgends gefunden.

Datenblatt, S. 75:
1
RP Pull/Buss(sic!) keeper Resistor 24 kΩ

Eigentlich gar nicht so schlecht, damit solltest du es zumindest mit
100 kHz durchaus schaffen.  Die 1 µs Anstiegszeit entsprechen dann
etwa 40 pF Lastkapazität, für einen nicht allzu langen Bus ist das
zu schaffen (ein IC-Pin bringt es auf etwa 10 pF).

Du solltest aber beachten, dass dies im IC normalerweise keine echten
Widerstände sind, sondern FET-Kanal-Strecken.  Damit hängt deren
äquivalenter Widerstand stark von der Gate- und damit von der
Versorgungsspannung ab.  Leider steht in der Tabelle nicht drin, auf
welche Versorgungsspannung sich die 24 kΩ beziehen.

von Stefan Frings (Gast)


Lesenswert?

Dass die Pull-Ups von ATTiny und ATMega bei 5V ungefähr 50k-100k Ohm 
haben, steht tatsächlich nirgendwo. Das ist ein Erfahrungswert.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan Frings schrieb:
> Dass die Pull-Ups von ATTiny und ATMega bei 5V ungefähr 50k-100k Ohm
> haben, steht tatsächlich nirgendwo.

Stimmt nicht, hier beispielsweise das Datenblatt des ATmega16:
1
Rpu    I/O Pin Pull-up Resistor 20 50 kΩ

d. h. dort wurden minimale und maximale Werte spezifiziert, aber
keine typischen (übrigens für den kompletten Vcc-Bereich von 2,7
bis 5,5 V geltend).

von Konrad S. (maybee)


Lesenswert?

Jörg Wunsch schrieb:
> RP Pull/Buss(sic!) keeper Resistor 24 kΩ

Bus Keeper ist noch mal was anderes als ein Pull-Up.

von Spinner (Gast)


Lesenswert?

2k2 pullups sind eigentlich die Regel. Und die interne pullups: aus!

von Choleriker (Gast)


Lesenswert?

Steig gleich auf ARM um. Funktioniert und ist gleich viel Aufwand wie 
die Xmegas zu verstehen....

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Konrad S. schrieb:
> Jörg Wunsch schrieb:
>> RP Pull/Buss(sic!) keeper Resistor 24 kΩ
>
> Bus Keeper ist noch mal was anderes als ein Pull-Up.

Sie sind aber in einem gemeinsamen Parameter genannt.

Für die bus keeper würde es auch deutlich hochohmiger genügen.

Choleriker schrieb:
> Steig gleich auf ARM um.  Funktioniert  [...]

Wie bei ARM üblich, strickt jeder Hersteller sein eigenes Süppchen.
Insofern ist "funktioniert" genauso richtig und falsch wie beim AVR
(jeder außer Holger würde dort wohl auch sofort "funktioniert"
dran schreiben).

Ganz davon abgesehen ist mir völlig unklar, wie der Wechsel des
Controllertyps seine Pullup-Probleme lösen sollte.

von Armer (Gast)


Lesenswert?

>Ganz davon abgesehen ist mir völlig unklar, wie der Wechsel des
Controllertyps seine Pullup-Probleme lösen sollte.

dieser löst sie eben..

von Stefan F. (sfrings)


Lesenswert?

Welchen Zweck verfolgen eigentlich die Leute, die hier immer wieder 
ungefragt und unpassend einen Umstieg auf ARM empfehlen?

Ich frage mich auch, ob den Leuten eigentlich klar ist, dass ARM nicht 
gleich ARM ist. ARM ist ein CPU Kern. Gemeint sind hier wohl eher 
Mikrocontroller mit ARM Kern. Aber welcher?

Hier im Forum geht es fast immer um die Eigenschaften von I/O 
Schnittstellen. Wie die aussehen, hängt vom jeweiligen Mikrocontroller 
ab und überhaupt nicht vom (ARM) Kern!

Ironie an:

Ansonsten fag ich bald an, jeden der hier irgendein Problem hat, auf 
einen Intel zu verweisen. Der Intel kann nämlich alles und der Intel 
löst alle Probleme ganz von selbst. Als mein Vater seinen AMD durch 
einen Intel ersetzte wurde er tatsächlich glücklicher. Und mein VIA 
wurde durch Intel sogar derart schöner, dass die scharfen Frauen bei mir 
schlange stehen, nur um den tollen Intel mal anfassen zu dürfen. 90% der 
Frauen einer Studio unter 12 Frauen haben ergeben, dass Intel besser als 
ARM arm ist.

Ironie aus.

von Holger M. (_holger)


Lesenswert?

Jörg Wunsch schrieb:
> Datenblatt, S. 75:
> RP Pull/Buss(sic!) keeper Resistor 24 kΩ

Ah, da steht's! Mal angenommen ich hätte das vorher gelesen hätte ich 
wohl von vorn herein mit externen Widerständen gearbeitet.
Im Endeffekt müssen 5 ICs und ein paar cm Flachbandkabel an den Bus.

O.T.: Hat mich übrigens sehr überrascht und auf eine merkwürdige Art und 
Weise gefreut deinen Karl Otto unter diversen Headerdateien zu lesen :)

Choleriker schrieb:
> Steig gleich auf ARM um. Funktioniert und ist gleich viel Aufwand wie
> die Xmegas zu verstehen....

Ich habe mir sicher nicht alle CPUs auf dem Markt angeguckt, aber beim 
ATXMEGA bin ich hängen geblieben, weil der einfach alles was ich brauche 
von Haus aus macht.
Versorgungsspannung drauf und das Ding läuft == her damit!!

Performancetechnisch bin ich bislang auch mehr beeindruckt als alles 
andere.
Die zwei externen, nicht eingeplanten Pull-Ups seien ihm also verziehen.

Stefan Frings schrieb:
> nur um den tollen Intel mal anfassen zu dürfen.

Pass nur ja auf, dass die sich vorher auch alle vernünftig geerdet 
haben!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.