Hallo Leute, mir gehen langsam die Ideen aus. Folgendes Problem: Ich beschreibe meinen selbstgebauten Slave per I2C erfolgreich über einen ATmega32u4, 16MHz Quarz, 8 Bit Prozessor, mit Hilfe der Peter Fleury Lib.Alles gut soweit und alles funktioniert. Nun möchte ich das ganze Projekt auf den kleinen Arduino Nano mit dem ATmega328p on Board auslagern. Laut Datenblatt ebenso 16Mhz, 8 Bit Prozessor ... Dazu möchte ich nicht das ganze Arduinozeugs nutzen, sondern den C-Code inclusive TWI Lib weiter nutzen. Allerdings erkennt der Atmega328p gar nicht erst meinen Slave. Ich hätte primär gedacht, aufgrund der gleichen F_CPU beider Chips gar nichts anpassen zu müssen, da nichts ging habe ich die Source_Clock auf 400kHz gesetzt wie in diversen Tutorien beschrieben-alles ohne Erfolg. Bitte helft mir, anbei sind die beiden Libs, welche ich verwende.
Hi
>Laut Datenblatt ebenso 16Mhz, 8 Bit Prozessor ...
#define F_CPU 4000000UL
Mit welcher Frequenz arbeitet dein Controller wirklich?
MfG Spess
Flop P. schrieb: > Bitte helft mir, anbei sind die beiden Libs, welche ich verwende Und wo ist DEIN Programm?
Flop P. schrieb: > nichts anpassen zu müssen Dass du es mit neuer CPU-Definition neu übersetzen musst ist dir aber schon klar?
> #define F_CPU 4000000UL > Genau also die 4000000UL sind der default Wert aus der Biliothek. Bei dem 32u4 habe ich den Wert auf 2000000UL eingestellt. > Mit welcher Frequenz arbeitet dein Controller wirklich? > Die Fuses habe ich nicht verändert, laut Datenblatt " 8.6 Calibrated Internal RC Oscillator By default, the Internal RC Oscillator provides an approximate 8.0 MHz clock" würde ich also das als tatsächliche Frequenz vermuten?!
> > Und wo ist DEIN Programm? Hier ist mal der Code für die init,start_wait,read und stop Befehle welche ich dann später alle verwende. Ich denke hier mache ich irgendwo was falsch ^^ #define SCL_CLOCK 100000L #define F_CPU 2000000UL // Does not work with 1600000UL #include <util/delay.h> #include <avr/io.h> #include <inttypes.h> #include <util/twi.h> #include <stdint.h> #include <stdlib.h> //variables uint8_t reg[6]; int i; void i2c_start_wait(unsigned char address) { uint8_t twst; while ( 1 ) { // send START condition TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // wait until transmission completed while(!(TWCR & (1<<TWINT))); // check value of TWI Status Register. Mask prescaler bits. twst = TW_STATUS & 0xF8; if ( (twst != TW_START) && (twst != TW_REP_START)) continue; // send device address TWDR = address; TWCR = (1<<TWINT) | (1<<TWEN); // wail until transmission completed while(!(TWCR & (1<<TWINT))); // check value of TWI Status Register. Mask prescaler bits. twst = TW_STATUS & 0xF8; if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) { /* device busy, send stop condition to terminate write operation */ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); // wait until stop condition is executed and bus released while(TWCR & (1<<TWSTO)); continue; } //if( twst != TW_MT_SLA_ACK) return 1; break; } }/* i2c_start_wait */ unsigned char i2c_write(unsigned char data) { uint8_t twst; // send data to the previously addressed device TWDR = data; TWCR = (1<<TWINT) | (1<<TWEN); // wait until transmission completed while(!(TWCR & (1<<TWINT))); // check value of TWI Status Register. Mask prescaler bits twst = TW_STATUS & 0xF8; if( twst != TW_MT_DATA_ACK) return 1; return 0; } void i2c_stop() { /* send stop condition */ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); // wait until stop condition is executed and bus released while(TWCR & (1<<TWSTO)); } void i2c_init() { /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ TWSR = 0; /* no prescaler */ TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */ }
Flop P. schrieb: > Ich denke hier mache ich irgendwo was falsch ^^ Ja, du nimmst nicht Rücksicht auf "Wichtige Regeln - erst lesen, dann posten!" "Formatierung (mehr Informationen...)"
> Und wo ist DEIN Programm? Hier ist mal der Code für die init,start_wait,read und stop Befehle welche ich dann später alle verwende. Ich denke hier mache ich irgendwo was falsch ^^ > > "Formatierung (mehr Informationen...)"
1 | #define SCL_CLOCK 100000L
|
2 | #define F_CPU 2000000UL // Does not work with 1600000UL
|
3 | #include <util/delay.h> |
4 | #include <avr/io.h> |
5 | #include <inttypes.h> |
6 | #include <util/twi.h> |
7 | #include <stdint.h> |
8 | #include <stdlib.h> |
9 | |
10 | //variables
|
11 | uint8_t reg[6]; |
12 | int i; |
13 | |
14 | void i2c_start_wait(unsigned char address) |
15 | {
|
16 | uint8_t twst; |
17 | |
18 | |
19 | while ( 1 ) |
20 | {
|
21 | // send START condition
|
22 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
23 | |
24 | // wait until transmission completed
|
25 | while(!(TWCR & (1<<TWINT))); |
26 | |
27 | // check value of TWI Status Register. Mask prescaler bits.
|
28 | twst = TW_STATUS & 0xF8; |
29 | if ( (twst != TW_START) && (twst != TW_REP_START)) continue; |
30 | |
31 | // send device address
|
32 | TWDR = address; |
33 | TWCR = (1<<TWINT) | (1<<TWEN); |
34 | |
35 | // wail until transmission completed
|
36 | while(!(TWCR & (1<<TWINT))); |
37 | |
38 | // check value of TWI Status Register. Mask prescaler bits.
|
39 | twst = TW_STATUS & 0xF8; |
40 | if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) |
41 | {
|
42 | /* device busy, send stop condition to terminate write operation
|
43 | */
|
44 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); |
45 | |
46 | // wait until stop condition is executed and bus released
|
47 | while(TWCR & (1<<TWSTO)); |
48 | |
49 | continue; |
50 | }
|
51 | //if( twst != TW_MT_SLA_ACK) return 1;
|
52 | break; |
53 | }
|
54 | |
55 | }/* i2c_start_wait */ |
56 | unsigned char i2c_write(unsigned char data) |
57 | {
|
58 | uint8_t twst; |
59 | |
60 | // send data to the previously addressed device
|
61 | TWDR = data; |
62 | TWCR = (1<<TWINT) | (1<<TWEN); |
63 | |
64 | // wait until transmission completed
|
65 | while(!(TWCR & (1<<TWINT))); |
66 | |
67 | // check value of TWI Status Register. Mask prescaler bits
|
68 | twst = TW_STATUS & 0xF8; |
69 | if( twst != TW_MT_DATA_ACK) return 1; |
70 | return 0; |
71 | |
72 | }
|
73 | void i2c_stop() |
74 | {
|
75 | /* send stop condition */
|
76 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); |
77 | |
78 | // wait until stop condition is executed and bus released
|
79 | while(TWCR & (1<<TWSTO)); |
80 | |
81 | }
|
82 | void i2c_init() |
83 | {
|
84 | /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
|
85 | |
86 | TWSR = 0; /* no prescaler */ |
87 | TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation |
88 | */
|
89 | |
90 | }
|
Flop P. schrieb: > #define F_CPU 2000000UL // Does not work with 1600000UL Das es mit 1,6 MHz (1600000UL) nicht funktioniert kann ich verstehen :-) wenn ein 16MHz Quarz aktiv und lt. Fuses eingestellt ist. Wie wäre es mit 16000000UL ?
> > Wie wäre es mit 16000000UL ? Du hast natürlich vollkommen Recht. Aber das ändert allerdings auch nichts daran, dass der Slave nicht erkannt wird vom ATmega328p....
Flop P. schrieb: > #define F_CPU 2000000UL // Does not work with 1600000UL Das deutet darauf hin, dass man vielleicht doch bei den Fuses mal aktiv werden und den 1:8 Vorteiler rausnehmen sollte. Einfachste Möglichkeit zum Abschätzen der wahren CPU Taktfrequenz ist der 1Hz-Blink-Test mit einer LED. Um die Diagnose auf dem I2C zu vereinfachen, wäre vielleicht eine Minimalmessausstattung nicht schlecht, z.B. ein kleiner Logikanalysator für 6€ oder gar ein DSO. Nebenbei: Verwendest du geeignete Pull-Up Widerständen für den I2C-Bus?
Flop P. schrieb: > Aber das ändert allerdings auch > nichts daran, dass der Slave nicht erkannt wird vom ATmega328p.. Den Port / die Pins in der nicht gezeigten i2cmaster.S hast Du angepasst?
Georg G. > Dass du es mit neuer CPU-Definition neu übersetzen musst ist dir aber > schon klar? Georg G., wie genau müsste denn die neue CPU-Definition aussehen? Bzw. meinst du "nur" den neuen Wert ? Wie berechnet sich der, wenn ich einen 16MHz Quarz benutze und die Fuses Defaultwerte besitzen??
Flop P. schrieb: > Wie berechnet sich der, wenn ich einen > 16MHz Quarz benutze und die Fuses Defaultwerte besitzen?? Defaultmäßig wird der Quarz aber nicht benutzt.
Flop P. schrieb: > Wie berechnet sich der, wenn ich einen > 16MHz Quarz benutze und die Fuses Defaultwerte besitzen?? Zeig doch mal die Werte der Fuses. Wenn das ein vorkonfigurierter Arduino ist, dann sollten die Fuses korrekt eingestellt sein. Hast Du den Bootloader überschrieben?
> Zeig doch mal die Werte der Fuses. Wenn das ein vorkonfigurierter > Arduino ist, dann sollten die Fuses korrekt eingestellt sein. Hast Du > den Bootloader überschrieben? Aus der SCK Periode(T)=0.1us hätte ich jetzt F_CPU = 1/T = 10MHz abgeleitet. Funktioniert aber scheinbar nicht so ?! >Hast Du > den Bootloader überschrieben? Ich denke nicht, denn ich LED-Debugge meinen I2C Bus - sobald der Slave gefunden wurde, geht die LED ( PB5) auch aus(so sollte es zumindest sein wenn er den Slave finden würde). Damit diese LED erstmal angeht muss also quasi mein Code schonmal vom Booleader bearbeitet worden sein. Den Code flashe ich btw per 'avrdude -p m328p -c avrisp -P com39 -b 57600 -F -U flash:w:filename'
:
Bearbeitet durch User
Wolfgang schrieb: > Flop P. schrieb: >> #define F_CPU 2000000UL // Does not work with 1600000UL > > Einfachste Möglichkeit zum Abschätzen der wahren CPU Taktfrequenz ist > der 1Hz-Blink-Test mit einer LED. > > Nebenbei: Verwendest du geeignete Pull-Up Widerständen für den I2C-Bus? Genau Pull Ups mit 10k dimensioniert und von der Busleitung gegen Vcc geschalten
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.