-         

Ergebnis 1 bis 8 von 8

Thema: Inkonsistente Variable auf ATmega644

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    30.05.2004
    Ort
    Detmold
    Alter
    30
    Beiträge
    557

    Inkonsistente Variable auf ATmega644

    Anzeige

    Moin,

    bei meinem Versuch, einen Kartenleser für einfache Speicherkarten zu entwerfen, bin ich über ein Softwareproblem gestolpert. Es scheint, als würde mein Array mem_main sich ständig verändern.

    Hier der Code (relevanter Ausschnitt):
    Code:
    #include <avr/io.h>
    #include <util/delay.h>
    
    #include "uart.h"
    
    #define SM_RST		PC0
    #define SM_CLK		PC1
    #define SM_IO		PC2
    #define SM_PORT		PORTC
    #define SM_PIN		PINC
    #define SM_DDR		DDRC
    
    unsigned char mem_main[256];
    
    int main() {
    	uart_init();
    	sm_init();
    
    	sm_read();
    
    	for (;; _delay_ms(1000)) {
    		for (unsigned int i = 0; i < 256; i++) {
    			uart_putc(mem_main[i]);
    		}
    	}
    
    	return 0;
    }
    
    void sm_init() {
    	SM_DDR = (1 << SM_RST) | (1 << SM_CLK);
    	SM_DDR &= ~(1 << SM_IO);
    	SM_PORT = (1 << SM_IO);
    }
    
    void sm_read() {
    	sm_command(0x30, 0x00, 0x00); // Kommando zum Lesen senden
    	SM_PORT &= ~(1 << SM_CLK);
    	SM_DDR &= ~(1 << SM_IO);
    	SM_PORT |= (1 << SM_IO);
    	_delay_us(100);
    
    	for (unsigned int i = 0; i < 256; i++) { // Byte-Schleife
    		unsigned char temp_byte; // Temporäres Byte
    		for (unsigned char k = 0; k < 8; k++) { // Bit-Schleife
    			SM_PORT |= (1 << SM_CLK); // Taktleitung auf H setzen
    			if (SM_PIN & (1 << SM_IO)) // I/O-Pin abfragen
    				temp_byte |= (1 << k);
    			_delay_us(100);
    			SM_PORT &= ~(1 << SM_CLK); // Taktleitung auf L setzen
    			_delay_us(100);
    		}
    		mem_main[i] = temp_byte; // Temporäres Byte in Hauptspeicher schreiben
    	}
    }
    
    void uart_init() {
    	UBRR0H = (unsigned char) (UBRR_VAL >> 8);
    	UBRR0L = (unsigned char) (UBRR_VAL);
    	UCSR0B = (1 << TXEN0);
    	UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Asynchron 8N1
    }
    
    void uart_putc(unsigned char c) {
    	while (!(UCSR0A & (1 << UDRE0))) {
    	}
    	UDR0 = c;
    }
    Seltsamerweise ändern sich vereinzelte Bytes in mem_main[...] anscheinend bei jeder Ausführung von print_mem(), obwohl keine schreibenden Zugriffe mehr stattfinden. Was könnte ich übersehen haben?

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.04.2010
    Beiträge
    1.249
    Hi

    Ich sehe kein print_mem.
    Vielleicht mal ein "volatile unsigned char mem_main[256];"
    Vielleicht solltest du die Variable nicht nur deklarieren sondern auch initialisieren.

    "for (;; _delay_ms(1000))" das meinst du nicht ernst oder?

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    30.05.2004
    Ort
    Detmold
    Alter
    30
    Beiträge
    557
    Erstmal vielen Dank für die Antwort.
    Ich sehe kein print_mem.
    Stimmt, ist beim Zusammenkopieren für das Minimalbeispiel abhanden gekommen, sorry...

    Also der bisherige Code sieht so aus:
    Code:
    #include <avr/io.h>
    #include <util/delay.h>
    
    #include "reader.h"
    #include "uart.h"
    #include "smartcard.h"
    
    volatile unsigned char mem_main[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    
    int main() {
    	uart_init();
    	sm_init();
    	_delay_us(100);
    
    	sm_read(); // Dummy readout
    	_delay_us(500);
    
    	sm_read();
    
    	for (;; _delay_ms(1000)) {
    		print_mem();
    	}
    
    	return 0;
    }
    
    void sm_init() {
    	SM_DDR = (1 << SM_RST) | (1 << SM_CLK);
    	SM_PORT = (1 << SM_IO);
    }
    
    void sm_command(unsigned char b, unsigned char a, unsigned char d) {
    	// gekürzt
    }
    
    void sm_read() {
    	sm_command(0x30, 0x00, 0x00);
    	SM_PORT &= ~(1 << SM_CLK);
    	SM_DDR &= ~(1 << SM_IO);
    	SM_PORT |= (1 << SM_IO);
    	_delay_us(100);
    
    	for (unsigned int byte = 0; byte < 256; byte++) { // Byte-Schleife
    		unsigned char temp_byte = 0x00; // Temporäres Byte
    		for (unsigned char bit = 0; bit < 8; bit++) { // Bit-Schleife
    			SM_PORT |= (1 << SM_CLK); // Taktleitung auf H setzen
    			if (SM_PIN & (1 << SM_IO)) // I/O-Pin abfragen
    				temp_byte |= (1 << bit);
    			_delay_us(100);
    			SM_PORT &= ~(1 << SM_CLK); // Taktleitung auf L setzen
    			_delay_us(100);
    		}
    		mem_main[byte] = temp_byte; // Temporäres Byte in Hauptspeicher schreiben
    	}
    }
    
    void uart_init() {
    	// gekürzt
    }
    
    void uart_putc(unsigned char c) {
    	// gekürzt
    }
    
    void print_mem() {
    	for (unsigned int i = 0; i < 256; i++) {
    		uart_putc(mem_main[i]);
    	}
    }
    Ich habe deine Vorschläge umgesetzt, leider ohne Ergebnis. Die Hex Dumps sehen z.B. so aus:
    Code:
    Erster Aufruf von print_mem():
    0000: A2 13 10 91 46 0B 81 15 - 42 45 00 23 09 05 5E 2F
    0010: 2E AA FF FF FF D2 76 00 - 00 63 01 FF FF FF FF FF
    0020: 30 30 30 39 32 36 30 30 - 30 30 30 30 00 00 00 A8
    0030: 64 64 00 01 00 B6 E4 D6 - 18 00 3F 02 FF FF FF FF
    0040: 11 56 7C 07 04 01 12 58 - 04 0D 00 92 58 08 A0 B2
    0050: 4F 00 18 03 04 0D 00 4D - 4A 00 E4 4D 08 00 15 59
    0060: 04 0E 12 80 05 32 06 90 - 27 08 14 25 04 0D 00 AC
    0070: 05 00 4A 08 00 09 12 24 - 04 0D 00 08 00 00 FD 4E
    0080: 08 00 16 00 00 10 00 00 - 00 49 00 90 06 11 15 58
    0090: 03 03 14 80 01 00 08 90 - FF FF FF FF FF FF FF FF
    00A0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00B0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00C0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00D0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00E0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00F0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    
    Zweiter Aufruf von print_mem():
    0000: A2 13 10 91 46 0B 81 15 - 42 45 00 23 09 05 5E 2F
    0010: 2E AA FF FF FF D2 76 00 - 00 00 00 FF FF FF FF FF
    0020: 30 30 30 39 32 36 30 30 - 30 30 30 30 00 00 E0 4C
    0030: 08 64 00 4E 08 17 E4 D6 - 18 00 AC 4D 08 00 FF FF
    0040: 11 56 7C 07 04 01 12 58 - 04 0D 00 00 A0 21 59 08
    0050: A0 B2 4F 00 18 0D 00 52 - 05 00 52 90 05 08 15 59
    0060: 04 0E 12 80 05 32 06 90 - 27 08 14 25 04 0D 00 80
    0070: 05 00 06 90 01 09 12 24 - 04 0D 00 00 00 00 06 90
    0080: 02 11 18 22 03 0B 28 80 - 03 32 06 90 06 11 15 58
    0090: 03 03 14 80 01 00 06 90 - FF FF FF FF FF FF FF FF
    00A0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00B0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00C0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00D0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00E0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    00F0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
    Eine ganze Reihe an Bytes unterscheidet sich leider.

    "for (;; _delay_ms(1000))" das meinst du nicht ernst oder?
    Ähm, das war nur auf die Schnelle zum Testen...

  4. #4
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von TobiKa
    "for (;; _delay_ms(1000))" das meinst du nicht ernst oder?
    Was bitte soll denn daran auszusetzen sein?


    @ Trabukh:

    Welcher Controller?
    Und den Code für uart_init und uart_putc würde ich auch gerne mal sehen.
    MfG
    Stefan

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.04.2010
    Beiträge
    1.249
    Der Code der Funktionen steht oben im ersten Post!

  6. #6
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von TobiKa
    Der Code der Funktionen steht oben im ersten Post!
    Ups, übersehen. Ich habe nur unter dem "Also der bisherige Code sieht so aus:" die "gekürzt" gesehen.

    EDIT: Und der Controller-Typ steht im Titel. Nicht mein Tag.

    Ich vermute, dass gar nicht wirklich der immer gleiche Speicherinhalt in einer Endlosschleife ausgegeben wird, sondern dass es zwischendurch einen Reset gibt, und dass sich die damit immer neu von der Karte gelesenen Daten unterscheiden. Meine erste Vermutung "Interrupt ohne ISR" hat sich nicht bestätigt. Nächster Versuch: Watchdog?
    MfG
    Stefan

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    30.05.2004
    Ort
    Detmold
    Alter
    30
    Beiträge
    557
    Leider trifft beides nicht zu. Ich habe aus Jux einfach mal nach dem ersten Aufruf von print_mem() die Speicherkarte herausgezogen, am Ausgang meiner "Experimente" hat das jedoch nichts geändert.

    Watchdog habe ich sicherheitshalber auch nochmal überprüft, der ist definitiv aus.

    EDIT: Folgender Code läuft im Übrigen anstandlos:
    Code:
    // µC: ATmega644
    
    #include <util/delay.h>
    #include <avr/io.h>
    
    #ifndef F_CPU
    #define F_CPU 14745600UL
    #endif
    #define BAUD 9600UL
    #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
    
    volatile unsigned char mem_main[256];
    
    int main() {
    	uart_init();
    
    	for (unsigned int i = 0; i < 256; i++) {
    		mem_main[i] = i;
    	}
    
    	for (;; _delay_ms(1000)) {
    		for (unsigned int i = 0; i < 256; i++) {
    			uart_putc(mem_main[i]);
    		}
    	}
    	return 0;
    }
    
    void uart_init() {
    	UBRR0H = (unsigned char) (UBRR_VAL >> 8);
    	UBRR0L = (unsigned char) (UBRR_VAL);
    	UCSR0B = (1 << TXEN0);
    	UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Asynchron 8N1
    }
    
    void uart_putc(unsigned char c) {
    	while (!(UCSR0A & (1 << UDRE0))) {
    	}
    	UDR0 = c;
    }
    EDIT 2: Wenn ich in meinem Programm die Baudrate auf 300 Stelle, scheint alles korrekt anzukommen. Wie kann sowas sein?

    EDIT 3: Zugegeben, ein dritter Edit ist schon peinlich, aber ich wurde das ungute Gefühl nicht los, dass mein Terminalprogramm nichts taugt. Die Vermutung hat sich bestätigt, mit hTerm funktioniert alles, wie es soll.
    Ich bitte somit um Verzeihung, dass an der völlig falschen Stelle gesucht werde und danke euch beiden für eure Hilfe.

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.04.2010
    Beiträge
    1.249
    Mich wundert das nur ein Teil der Variable falsch übertragen wird...

    Wie dem auch sei, ich benutze auch HTerm und das ist einfach das beste.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •