Forum: Mikrocontroller und Digitale Elektronik Datenübertragungsrate nach EEPROM


von Maik G. (maik_l)


Angehängte Dateien:

Lesenswert?

Moin und Schönen Sonntag zusammen.

Nachdem ich mit meinem Programm fertig bin, wollte ich mich nun an 
einige Änderungen setzten.

Unter anderem beinhaltet dies auch, das die UART entsprechend der im 
EEPROM abgelgten Einstellung sich auf eine der verwendeteten 
Übertragungsraten einstellt und somit dann auch zB mit 115200 Baud Ihre 
Datenströme überträgt.

mein Ansatz sieht im Kern wie folgt aus.
1
    UBAUD = 9600;                                        // Akuelle Übertragungsrate
2
    EE_R_Baud();
3
    switch (_BAUD)
4
    {
5
      case 1: { UBAUD =   9600; break; }
6
      case 2: { UBAUD =  19200; break; }
7
      case 3: { UBAUD =  57600; break; }
8
      case 4: { UBAUD = 115200; break; }
9
    }
10
11
    _delay_ms(100);
12
13
    uart(true);

zu kurzen Erklärung.

Damit ich überhaupt erst mal von außen war reinbekommen Wird UBAUD 
vordefiniert. somit liegt es meiner Überlegung nach nur auf der Hand, 
das der Rest mehr oder weniger übersprungen wird, da nicht die Werte 
enthalten sind, welche ich vorgebe.

Nachdem ich allerdings via
1
$23>
 dem EEPROM sagen, das der die Konstante für 57600 Baud schreiben soll, 
was er ja auch definiv macht ist es mir ein Rätsel, warum er auch deinen 
9600 Baud bleibt.

In der Hoffnung, das ihr meinen Gedankenkang nachvollziehen könnt lege 
ich mal noch einige Programmauszüge und Definitionen in aufgerufener 
Reihenfolge bei.

Lesen des Wertes
1
void EE_R_Baud(void)
2
{
3
    _BAUD = eeprom_read_byte((uint8_t *)EE_BAUD_2);
4
    return;
5
}
6
7
#define EE_BAUD_2       0x00F

Schreibnen des Wertes
1
            if (rxd[0] == '2')
2
            {
3
                Write_BAUD((int) rxd[1]);
4
            }
5
6
void Write_BAUD(char Value)
7
{
8
    ee_write_BAUD(Value);
9
}
10
11
void ee_write_BAUD(uint8_t BAUD)
12
{
13
    eeprom_write_byte((uint8_t *)EE_BAUD_2, BAUD);
14
}

Weiterhin nochmal das 2 Logs für euch sowie im Bildanhang ein ScreenShot
1
picocom v1.7
2
3
port is        : /dev/ttyUSB0
4
flowcontrol    : none
5
baudrate is    : 9600
6
parity is      : none
7
databits are   : 8
8
escape is      : C-a
9
local echo is  : no
10
noinit is      : no
11
noreset is     : no
12
nolock is      : no
13
send_cmd is    : sz -vv
14
receive_cmd is : rz -vv
15
imap is        : 
16
omap is        : 
17
emap is        : crcrlf,delbs,
18
19
Terminal ready
20
$23>$5><8|010000117|11001110>
21
Thanks for using picocom
22
23
$ sudo picocom -b 9600 /dev/ttyUSB0 
24
picocom v1.7
25
26
port is        : /dev/ttyUSB0
27
flowcontrol    : none
28
baudrate is    : 9600
29
parity is      : none
30
databits are   : 8
31
escape is      : C-a
32
local echo is  : no
33
noinit is      : no
34
noreset is     : no
35
nolock is      : no
36
send_cmd is    : sz -vv
37
receive_cmd is : rz -vv
38
imap is        : 
39
omap is        : 
40
emap is        : crcrlf,delbs,
41
42
Terminal ready
43
$5><5|010010103|11101100>

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Wo initialisierst du dann den UART? Der Programmteil scheint ja das 
Problem zu sein, ist aber in den Schnipseln nicht vorhanden.

Noch ein Tipp. Wenn du das EEPROM beim erstmaligen Programmieren mit 
sinnvollem Kram vorbesetzen willst, kannst du das so machen:
1
uint8_t EE_BAUD_2 __attribute__((section(".eeprom")))= 3;
Damit wird ein *.eep File erzeugt, was du beim erstmaligen Schreiben des 
MC ins EEPROM programmieren kannst.

von Maik G. (maik_l)


Lesenswert?

Matthias S. schrieb:
> Wo initialisierst du dann den UART? Der Programmteil scheint ja das
> Problem zu sein, ist aber in den Schnipseln nicht vorhanden.

du meinst diese Zeilen?
1
void uart(bool fast)                                    // doppelte Bautrate
2
{
3
  unsigned char x = 0x00;
4
  if (!(fast)) {
5
    UBRRL = (TAKT / (16ul * UBAUD)) - 1;                // Baudrate mit TAKt und BAUD
6
    UBRRH = 0;
7
    }
8
  else {
9
    UBRRL = (TAKT / (8ul * UBAUD)) - 1;                 // Baudrate mit TAKt und BAUD
10
    UBRRH = 0;
11
    }
12
  UCSRA |= (1 << U2X);                                  // U2X einfache / Doppelte Bautrate * 16/8 je nach vorauswahl
13
  UCSRB |= (1 << TXEN) | (1 << RXEN);                   // Sender und Empfänger ein
14
  UCSRC |= (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);  // async 8bit
15
  x = UDR;                                              // Empfänger leeren
16
  }

Nun da ich diese im Kern auf dem Buch:
*Mikrocomputertechnik mit Controllern der ATMEL AVR-RISC-Familie*
habe und nur nach meinen Bedürfnissen umgeschrieben habe glaube ich 
nicht, das da der Fehler ist, lasse mir aber gerne das Gegenteil zeigen.

Matthias S. schrieb:
> Noch ein Tipp. Wenn du das EEPROM beim erstmaligen Programmieren mit
> sinnvollem Kram vorbesetzen willst, kannst du das so machen:
>
1
> uint8_t EE_BAUD_2 __attribute__((section(".eeprom")))= 3;
2
>
> Damit wird ein *.eep File erzeugt, was du beim erstmaligen Schreiben des
> MC ins EEPROM programmieren kannst.

Danke für den Tip.
Das ist etwas, was ich schon lange gesucht habe.
Aber wird etwas Aufwand werden, um dies richtig einzubauen, da ich 
Cast-Probleme auf mich zukommen sehen werde. (uint8_t *) und (uint8_t)

: Bearbeitet durch User
von торфкопф (Gast)


Lesenswert?

Ich wuerde erst mal die verschiedenen Teile trennen und einzeln testen. 
Also senden und empfangen, und EEPROM lesen und  schreiben.

Also UART von Konstanten initilisieren, Konstanten senden und mit dem PC 
empfangen.
UART ab dem EEPROM initialisieren und ab dem EEPROM lesen und per UART 
senden.
Mit dem PC senden, mit dem UART emfangen, mit dem UART zuruecksenden, 
und mit dem PC empfangen.

Mit dem PC senden, mit dem UART emfangen, ins EEPROM schreiben, per 
Programmer auslesen und kontrollieren.

von holger (Gast)


Lesenswert?

>umgeschrieben habe glaube ich
>nicht, das da der Fehler ist,

  UCSRA |= (1 << U2X);    // U2X einfache / doppelte Baudrate

U2X wird in der Funktion immer gesetzt, egal ob "fast" oder nicht.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Maik G. schrieb:
>> uint8_t EE_BAUD_2 __attribute__((section(".eeprom")))= 3;
>> > Damit wird ein *.eep File erzeugt, was du beim erstmaligen Schreiben des
>> MC ins EEPROM programmieren kannst.
>
> Danke für den Tip.
> Das ist etwas, was ich schon lange gesucht habe.
> Aber wird etwas Aufwand werden, um dies richtig einzubauen, da ich
> Cast-Probleme auf mich zukommen sehen werde. (uint8_t *) und (uint8_t)

Lesen tue ich die EEPROM Zelle dann mit
1
UBAUD = eeprom_read_byte(&EE_BAUD_2);
2
// und schreiben mit 
3
cli();
4
eeprom_busy_wait();
5
eeprom_write_byte(&EE_BAUD_2,UBAUD);
6
(sei);
Übrigens haben einige wenige AVR Probleme mit Adresse 0 des EEPROM. 
Weils bei mir nicht auf jedes bisschen Platz im EEPROM ankommt, setze 
ich auf Adresse 0 meistens einen dummy, um dieses Problem zu vermeiden.

: Bearbeitet durch User
von Maik G. (maik_l)


Lesenswert?

торфкопф schrieb:
> Ich wuerde erst mal die verschiedenen Teile trennen und einzeln testen.
> Also senden und empfangen, und EEPROM lesen und  schreiben.
>
> Also UART von Konstanten initilisieren, Konstanten senden und mit dem PC
> empfangen.
> UART ab dem EEPROM initialisieren und ab dem EEPROM lesen und per UART
> senden.
> Mit dem PC senden, mit dem UART emfangen, mit dem UART zuruecksenden,
> und mit dem PC empfangen.
>
> Mit dem PC senden, mit dem UART emfangen, ins EEPROM schreiben, per
> Programmer auslesen und kontrollieren.

Dies war genau das, wie ich an Anfang vorgegangen bin.
Allstepbystep.
mache ich bei Lazarus nicht anders.
Funktion schreiben, Testen und versuchen alle Bugs bewusst zu finden. 
auf Konsolen-ebene geht es zwar auch mit mehreren Debug- und Infozeilen 
aber wenn da schon im Vorfeld möglicherweise der Wurm drin ist helfen 
diese auch nicht.

Bin halt erst durch die Anpassungen darauf aufmerksam geworden, das da 
was schief läuft

holger schrieb:
>>umgeschrieben habe glaube ich
>>nicht, das da der Fehler ist,
>
>   UCSRA |= (1 << U2X);    // U2X einfache / doppelte Baudrate
>
> U2X wird in der Funktion immer gesetzt, egal ob "fast" oder nicht.

Goldener Hinweiß auf diese Zeile.
Gerade in der Literatur noch mal belesen und der Klassiker

Matthias S. schrieb:
> Maik G. schrieb:
>>> uint8_t EE_BAUD_2 __attribute__((section(".eeprom")))= 3;
>>> > Damit wird ein *.eep File erzeugt, was du beim erstmaligen Schreiben des
>>> MC ins EEPROM programmieren kannst.
>>
>> Danke für den Tip.
>> Das ist etwas, was ich schon lange gesucht habe.
>> Aber wird etwas Aufwand werden, um dies richtig einzubauen, da ich
>> Cast-Probleme auf mich zukommen sehen werde. (uint8_t *) und (uint8_t)
>
> Lesen tue ich die EEPROM Zelle dann mit
>
1
> UBAUD = eeprom_read_byte(&EE_BAUD_2);
2
> // und schreiben mit
3
> cli();
4
> eeprom_busy_wait();
5
> eeprom_write_byte(&EE_BAUD_2,UBAUD);
6
> (sei);
7
>

Interrupt manipulieren willst du mir damit sagen.

Matthias S. schrieb:
> Übrigens haben einige wenige AVR Probleme mit Adresse 0 des EEPROM.
> Weils bei mir nicht auf jedes bisschen Platz im EEPROM ankommt, setze
> ich auf Adresse 0 meistens einen dummy, um dieses Problem zu vermeiden.

also empfiehlst du mir, da erst am der EEPROM 0x01 werte zu schreiben?
Nach dieser Info macht es sinn und da habe am ende nochmal 12 Bit frei 
bekommen.

Schade, das gerade diese Erfahrungswerte nicht in jeder Litereatur 
angemerkt werden. Aber dafür sind gerade die Informationen von euch so 
wichtig für jemanden, der in gewissen Punkten Quasi Neuling ist.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Maik G. schrieb:
> Interrupt manipulieren willst du mir damit sagen.

Auch, und das Übergeben der Adresse mit &.

Maik G. schrieb:
> also empfiehlst du mir, da erst am der EEPROM 0x01 werte zu schreiben?

Schaden tut es jedenfalls nicht. Hatte selbst bei moderneren AVR ab und 
zu mal Probleme mit Adresse 0.

von Maik G. (maik_l)


Lesenswert?

Habe mir gerade mal eine *.eep via Bless erstellt.

in der ersten sind die Werte wie ich diese gerne im EEPROM hätte
1
:01000000FF2017010100001
2
:00000001FF

und im 2ten, wie diese mir von Code:Blocks geliefert werden.
1
:10000000FF5D020001070001000200000000014244
2
:0100100003EC
3
:00000001FF

Nun die Große Frage...
Welche von beiden ist die, welche ich schreiben sollte?
Ich würde aus dem bauch sagen. die erste.

Dies die dazugehörige Definition im ganzen-
1
uint8_t EE_Dummy        EEMEM = 0xff;
2
uint8_t EE_SN_Fuse      EEMEM = 0x5D;
3
uint8_t EE_SN_Year_1    EEMEM = 2;
4
uint8_t EE_SN_Year_2    EEMEM = 0;
5
uint8_t EE_SN_Year_3    EEMEM = 1;
6
uint8_t EE_SN_Year_4    EEMEM = 7;
7
uint8_t EE_SN_Month_1   EEMEM = 0;
8
uint8_t EE_SN_Month_2   EEMEM = 1;
9
uint8_t EE_SN_Week_1    EEMEM = 0;
10
uint8_t EE_SN_Week_2    EEMEM = 2;
11
uint8_t EE_SN_LfdNr_1   EEMEM = 0;
12
uint8_t EE_SN_LfdNr_2   EEMEM = 0;
13
uint8_t EE_SN_LfdNr_3   EEMEM = 0;
14
uint8_t EE_SN_LfdNr_4   EEMEM = 0;
15
uint8_t EE_SN_LfdNr_5   EEMEM = 1;
16
uint8_t EE_BAUD_1       EEMEM = 0x42;
17
uint8_t EE_BAUD_2       EEMEM = 3;

bin auch dabei über diesen Artikel gestolpert.
Beitrag "Re: EEPROM Adressen"

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Maik G. schrieb:
> Dies die dazugehörige Definition im ganzen-
> uint8_t EE_Dummy        EEMEM = 0xff;
> uint8_t EE_SN_Fuse      EEMEM = 0x5D;
> uint8_t EE_SN_Year_1    EEMEM = 2;
> uint8_t EE_SN_Year_2    EEMEM = 0;
> uint8_t EE_SN_Year_3    EEMEM = 1;
> uint8_t EE_SN_Year_4    EEMEM = 7;
....

Wenn du die alle in EEMEM definierst, landen sie auch alle im EEPROM. 
Code:Blocks macht also nur, was du vorgegeben hast. Wenn du also jede 
Zahl des Datums als ein Byte definierst, bleibt das auch so. Du suchst 
ein Format wie 'Packed BCD', das ist aber nicht so mein Ding. Da gibts 
hier Leute, die das besser können. Ich würde fürs Jahr einfach ein 
uint16_t nehmen und das als word ins EEPROM schreiben. Für Monat und Tag 
je ein Byte und die Lfd. Nummer wieder als uint16_t (wenn das reicht).

von posti (Gast)


Lesenswert?

Hi

Hast Du diese eep-Datei Mal gebrannt?
Denke, da kommen genau die Werte raus, Die Du wünscht.

Denke weiter, daß die eep-Datei auch in dem Intel-Hex-Format (Prpfsumme 
ect.pp.) vorliegt.

MfG

von Maik G. (maik_l)


Lesenswert?

Matthias S. schrieb:
> Maik G. schrieb:
>> Dies die dazugehörige Definition im ganzen-
>> uint8_t EE_Dummy        EEMEM = 0xff;
>> uint8_t EE_SN_Fuse      EEMEM = 0x5D;
>> uint8_t EE_SN_Year_1    EEMEM = 2;
>> uint8_t EE_SN_Year_2    EEMEM = 0;
>> uint8_t EE_SN_Year_3    EEMEM = 1;
>> uint8_t EE_SN_Year_4    EEMEM = 7;
> ....
>
> Wenn du die alle in EEMEM definierst, landen sie auch alle im EEPROM.
> Code:Blocks macht also nur, was du vorgegeben hast. Wenn du also jede
> Zahl des Datums als ein Byte definierst, bleibt das auch so. Du suchst
> ein Format wie 'Packed BCD', das ist aber nicht so mein Ding. Da gibts
> hier Leute, die das besser können. Ich würde fürs Jahr einfach ein
> uint16_t nehmen und das als word ins EEPROM schreiben. Für Monat und Tag
> je ein Byte und die Lfd. Nummer wieder als uint16_t (wenn das reicht).

das mit den uint16t war mein erster Gedanke, den ich aber wieder sehr 
schnell verworfen habe, da ich Probleme hatte diese dann zu übergeben, 
und die sollen auch so im EEPROM landen. wobei EE_BAUD_2 die wichtigste 
ist.
ggf. ändere ich die Position.

unabhängig davon stört mich ja nur die Verwaltung der automatischen 
Baudeinstellung, aber da werd ich mir mit 4 LEDs Abhilfe schaffen, hätte 
ich eher mal drauf kommen sollen.

posti schrieb:
> Hi
>
> Hast Du diese eep-Datei Mal gebrannt?
> Denke, da kommen genau die Werte raus, Die Du wünscht.

Der Post entstand genau aus diesem Grund, da ich eine geschrieben hatte.
Welche Info möglicherweise noch wichtig wäre.

Verwende einen Atmega16 mit 8MHz.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Maik G. schrieb:
> da ich Probleme hatte diese dann zu übergeben,
> und die sollen auch so im EEPROM landen.

Öh, wie jetzt - Probleme? Es gibt z.B. die Funktionen 
eeprom_write_word() und eeprom_read_word(), die mit uint16_t genauso 
klarkommen wie ihre entsprechenden Kumpels für Bytes.

von Maik G. (maik_l)


Lesenswert?

Habe mir das Ganze nochmal durch den Kopf gehen lassen und bin vorerst 
zu dem Entschluss gekommen, das ich die Bautrate erstmal nur Manuell 
eintrage und somit mit 19200 BAUD bei 8MHz arbeite, wodurch sich meine 
UART nun von
1
void uart(bool fast)                                    // doppelte Bautrate
2
{
3
  UBAUD = 9600;                                        // Akuelle Übertragungsrate
4
  unsigned char x = 0x00;
5
  if ((!)fast) {
6
    UBRRL = (TAKT / (16ul * UBAUD)) - 1;                // Baudrate mit TAKt und BAUD
7
    UBRRH = 0;
8
    UCSRA |= (0 << U2X);                                // U2X eindache Bautrate * 16
9
    }
10
  else {
11
    UBRRL = (TAKT / (8ul * UBAUD)) - 1;                 // Baudrate mit TAKt und BAUD
12
    UBRRH = 0;
13
    UCSRA |= (1 << U2X);                                // U2X Doppelte Bautrate * 8
14
    }
15
  UCSRB |= (1 << TXEN) | (1 << RXEN);                   // Sender und Empfänger ein
16
  UCSRC |= (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);  // async 8bit
17
  x = UDR;                                              // Empfänger leeren
18
  }
 in
1
void uart(bool fast)                                    // doppelte Bautrate
2
{
3
  UBAUD = 19200;                                        // Akuelle Übertragungsrate
4
  unsigned char x = 0x00;
5
  if (fast) {
6
    UBRRL = (TAKT / (8ul * UBAUD)) - 1;                 // Baudrate mit TAKt und BAUD
7
    UBRRH = 0;
8
    UCSRA |= (1 << U2X);                                // U2X Doppelte Bautrate * 8
9
    }
10
  else {
11
    UBRRL = (TAKT / (16ul * UBAUD)) - 1;                // Baudrate mit TAKt und BAUD
12
    UBRRH = 0;
13
    UCSRA |= (0 << U2X);                                // U2X eindache Bautrate * 16
14
    }
15
  UCSRB |= (1 << TXEN) | (1 << RXEN);                   // Sender und Empfänger ein
16
  UCSRC |= (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);  // async 8bit
17
  x = UDR;                                              // Empfänger leeren
18
  }
geändert hat.
zum einem habe ich da denn Vorteil, das ich selber durch meine Verdrehte 
Logik nicht durcheinander komme und ich kann es noch besser lesen als 
vorher.

Weiterhin habe ich auch den Eindruck, das sich meine Software an der 
*.eep verschluckt.
1
:03000000FF5D039E
2
:00000001FF

Wie ich darauf komme?
Habe mir mal eine Kontrolle eingebaut
1
    while(1)
2
  {
3
        switch (EE_R_Baud())
4
        {
5
          case 1: {
6
                    putch(_BAUD);
7
                    PORTA=0x00; _delay_ms(250); PORTA=0xFF; _delay_ms(1000);
8
                    PORTA=0x00; _delay_ms(250); PORTA=0xFF; _delay_ms(1000);
9
                    PORTA=0x00; _delay_ms(250); PORTA=0xFF; _delay_ms(1000);
10
                    break; }
11
          case 2: {
12
                    putch(_BAUD);
13
                    PORTA=0x00; _delay_ms(500); PORTA=0xFF; _delay_ms(1000);
14
                    PORTA=0x00; _delay_ms(500); PORTA=0xFF; _delay_ms(1000);
15
                    PORTA=0x00; _delay_ms(500); PORTA=0xFF; _delay_ms(1000);
16
                    break; }
17
          case 3: {
18
                    putch(_BAUD);
19
                    PORTA=0x00; _delay_ms(750); PORTA=0xFF; _delay_ms(1000);
20
                    PORTA=0x00; _delay_ms(750); PORTA=0xFF; _delay_ms(1000);
21
                    PORTA=0x00; _delay_ms(750); PORTA=0xFF; _delay_ms(1000);
22
                    break; }
23
          case 4: {
24
                    putch(_BAUD);
25
                    PORTA=0x00; _delay_ms(1000); PORTA=0xFF; _delay_ms(1000);
26
                    PORTA=0x00; _delay_ms(1000); PORTA=0xFF; _delay_ms(1000);
27
                    PORTA=0x00; _delay_ms(1000); PORTA=0xFF; _delay_ms(1000);
28
                    break; }
29
        }

und die Entsprechende Zugriffsfunction geändert.
1
uint8_t EE_R_Baud(void)
2
{
3
   _BAUD = eeprom_read_byte(&EE_BAUD_1);
4
    return _BAUD;
5
}

Wie erkenntlich ist will ich eine LED blinken lassen. Da ich bei 250ms 
und 1000ms nicht wirklich viel sehe habe ich diese je 3 mal angesetzt, 
was das Programm jedoch unnötig aufbläht.

Den rest des EEPROM schreibe ich dann wie gewünscht über meine Externe 
Software.

von Maik G. (maik_l)


Lesenswert?

Gerade mal wieder den Kopfzermartert, weil ich mich gewundert habe, 
wieso ich meine eep nicht auf den Chip bekomme.

dabei waren die Lösungen da so sibmle, das wohl Niemand daran gedacht 
hat mal die FuseBits ins Auge zu fassen...

Naja. nun kann ich 100 pro und ohne größere Probleme weiterarbeiten 
hoffe ich doch mal...

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.