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
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
Sieht bei mir auch so aus (mit 4.7k und 3 Slaves dran). Funktioniert aber einwandfrei mit den I²C -Slaves :D
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.
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?
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.
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.
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.
Hi >Zeig doch mal her. >Im Grunde mußt Du: >.... Bei Hardware-TWI muss er das nicht. MfG Spess
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.
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 | }
|
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.
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.
Dass die Pull-Ups von ATTiny und ATMega bei 5V ungefähr 50k-100k Ohm haben, steht tatsächlich nirgendwo. Das ist ein Erfahrungswert.
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).
Jörg Wunsch schrieb: > RP Pull/Buss(sic!) keeper Resistor 24 kΩ Bus Keeper ist noch mal was anderes als ein Pull-Up.
2k2 pullups sind eigentlich die Regel. Und die interne pullups: aus!
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.
>Ganz davon abgesehen ist mir völlig unklar, wie der Wechsel des
Controllertyps seine Pullup-Probleme lösen sollte.
dieser löst sie eben..
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.