Forum: Mikrocontroller und Digitale Elektronik Codekonvertierung von ATmega32u4 auf ATmega328p


von Flop P. (mr_x)


Angehängte Dateien:

Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

Hi

>Laut Datenblatt ebenso 16Mhz, 8 Bit Prozessor ...

#define F_CPU 4000000UL

Mit welcher Frequenz arbeitet dein Controller wirklich?

MfG Spess

von Dieter F. (Gast)


Lesenswert?

Flop P. schrieb:
> Bitte helft mir, anbei sind die beiden Libs, welche ich verwende

Und wo ist DEIN Programm?

von Georg G. (df2au)


Lesenswert?

Flop P. schrieb:
> nichts anpassen zu müssen

Dass du es mit neuer CPU-Definition neu übersetzen musst ist dir aber 
schon klar?

von Flop P. (mr_x)


Lesenswert?

> #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?!

von Flop P. (mr_x)


Lesenswert?

>
> 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 
*/

}

von Frickelfritze (Gast)


Lesenswert?

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...)"

von Flop P. (mr_x)


Lesenswert?

> 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
}

von Dieter F. (Gast)


Lesenswert?

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 ?

von Flop P. (mr_x)


Lesenswert?

>
> 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....

von Wolfgang (Gast)


Lesenswert?

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?

von Dieter F. (Gast)


Lesenswert?

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?

von Flop P. (mr_x)


Lesenswert?

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??

von Dietrich L. (dietrichl)


Lesenswert?

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.

von Dieter F. (Gast)


Lesenswert?

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?

von Flop P. (mr_x)


Angehängte Dateien:

Lesenswert?

> 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
von Flop P. (mr_x)


Lesenswert?

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
Noch kein Account? Hier anmelden.