- Labornetzteil AliExpress         
Ergebnis 1 bis 10 von 10

Thema: Probleme bei Strukturen (Projekt Funkuhr)

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    04.10.2007
    Alter
    39
    Beiträge
    17

    Probleme bei Strukturen (Projekt Funkuhr)

    Anzeige

    Powerstation Test
    Hallo,

    bin gerade dabei mir eine Funkuhr zu bauen. Das Signal empfange ich mittlerweile problemlos. Jetzt wollte ich das empfangene Signal umwandeln aber das klappt überhaupt nicht.

    Ich speichere die ganzen 59 Bits in char dcf[60];
    Nun wollte ich das aber über eine Struktur lösen. In meinem Programm zählt eine Variable dcf_ctr die einzelnen Bits des Signals hoch. Habe mal mit einer Struktur angefangen um die Wetterinformationen zu speichern aber habs nicht geschafft die ersten 15 bits in der Struktur zu speichern. Hier mal mein Code:

    Code:
    #include "avr/io.h"
    #include "function.h"
    #include <avr/interrupt.h>
    
    volatile uint16_t dcf_time = 0;			//Zählvariable DCF Pausen
    uint8_t dcf_before = 1;					//DCF Signal zuvor
    uint8_t dcf_flag = 0;					//DCF Signal aktuell
    uint8_t dcf_ctr = 0;					//DCF Bitzähler
    char dcf[60];							//Codiertes DCF Signal 59 bit
    
    int main (void)
    {
    
    	//Port Konfiguration DCF77 Empfänger
    
    	dcf_ddr &= ~(1<<dcf_bit);      //PinX als Eingang definieren
    	dcf_port |= (1<<dcf_bit);      //Pullup Widerstand für diesen Pin aktivieren
    	   
    
    
    	//Debug Konfiguration, LED1, LED2
    
    
    	DDRC |= (1<<0) | (1<<1);      //Bit0 PortC Ausgang
    	PORTC |= (1<<0) | (1<<1);      //Led an PortC aus   
    
    	//Timer 1 starten, Globale Interrups aktivieren
    	init_timer();
    	//USART initialisieren
    	init_USART();
    
    	/*###############################################
    	#                                 			   #
    	#   Hauptprogramm                 		       #
    	#                                 			   #
    	################################################*/
    	while(1)
    	{
        
    		//##################### DEBUG ### LED1 zeigt DCF77 Signal#####################
    		if (dcf_pin & (1<<dcf_bit))
    			PORTC |= (1<<0);                     // Ausführen wenn HIGH
    		else
    			PORTC &= ~(1<<0);                     // Ausführen wenn LOW
    	}
    return 0; 
    }
    
    
    
    
    
    //Portzustand DCF77 einlesen und in dcf_flag schreiben
    int get_dcf_bit()
    {
    	if (dcf_pin & (1<<dcf_bit))
    	{
    		dcf_flag = 1;
    
    	}else{
    		dcf_flag = 0;
    	}
    return(dcf_flag); 
    }
       
    SIGNAL (SIG_OUTPUT_COMPARE1A)
    {
    	PORTC ^= (1<<1);      //DEBUG Zeige Frequenz vom Timer-Interrupt an LED2
    	get_dcf_bit();         //Pegel vom DCF Signal einlesen und in dcf_flag speichern
       
    	if(dcf_flag == 1)      //Wenn DCF Signal HIGH > Zeit messen
    	{
    		if(dcf_flag == dcf_before)      //Führe aus, wenn sich Pegel nicht geändert hat
    		{      
    			dcf_time += 20;            //Zeit +20ms
    		}else{                   //Führe aus bei Pegeländerung
    			if(dcf_time > 770 && dcf_time < 830)		//Erkenne Pause von 800 ms = logisch 1
    			{
    				dcf[dcf_ctr] = '1';
    				dcf_ctr++;
    			}
    			if(dcf_time > 870 && dcf_time < 930)		//Erkenne Pause von 900 ms = logisch 0
    			{
    				dcf[dcf_ctr] = '0';
    				dcf_ctr++;
    			}
    			if(dcf_time > 1770 && dcf_time < 1830)		//Erkenne Pause von 1800 ms = logisch 1, Ende der Übertragung
    			{
    				dcf[dcf_ctr] = '1';
    				sendUSART(dcf);
    				sendUSART("\r\n");
    				dcf_ctr = 0;
    			}
    			if(dcf_time > 1870 && dcf_time < 1930)			//Erkenne Pause von 1900 ms = logisch 0, Ende der Übertragung
    			{
    				sendUSART(dcf);
    				sendUSART("\r\n");
    				dcf_ctr = 0;
    			}
    			dcf_time = 0;            //Zeitvariable zurücksetzen
    		}
    	}
    dcf_before = dcf_flag;            //Alten Pegel in der Variable dcf_before speichern
    }
    Alles was mit der Struktur zu tun hatte wurde entfernt da das Programm sonst nimmer korrekt funktionierte.

    Meine Struktur sah so aus:
    Mit voran gestellten typedef hat mir AVR Studio gleich nen Fehler ausgespuckt. Kann mir einer sagen warum?
    Code:
    struct
    {
    weather[15];
    }dcf_struct;
    Und zum speichern habe ich bei jeder Pausenerkennung eine if-Abfrage eingebaut. Hier das Beispiel für ne 1 erkannt.
    Code:
    if(dcf_ctr <=14){
    dcf_struct.weather |= (1<<dcf_ctr);
    }
    Der richtig Emfpangene DCF String hat nie mit dcf_struct.weather übereingestimmt. Hab auch Probleme dcf_struct.weather über USART auszugeben. Sendet nur wirres Zeug und itoa geht auch nicht.
    Das man USART nicht in Interrupts aufruft ist mir klar, ist nur zum Debuggen drinn

    Wäre um jede Hilfe froh wie ich das mit Strukturen lösen kann.
    Vielen Dank schonmal

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Mit voran gestellten typedef hat mir AVR Studio gleich nen Fehler ausgespuckt.
    Und wie lautete der?

    struct
    {
    weather[15];
    }dcf_struct;
    Und poste bitte nochmal die tatsächliche Definition von dcf_struct, denn diese wirst du wohl kaum benutzt haben, schließlich hat weather da gar keinen Typ.
    MfG
    Stefan

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    04.10.2007
    Alter
    39
    Beiträge
    17
    Sorry hat sich wohl ein Fehler eingeschlichen Um mich mit Strukturen vertraut zu machen hab ich am Anfang ne ganz einfache genommen. Hier klappts mit typedef nicht:

    typedef struct
    {
    uint16_t weather:15;
    }dcf_s;

    +

    dcf_s.weather = 3;

    ergibt den Fehler : ../dcf77.c:51: error: expected identifier or '(' before '.' token
    Lass ich das typedef weg funktionierts

    Da fällt mir gerade auf: Wo liegt der Unterschied wenn ich bei struct einmal uint16_t weather:15; schreibe oder uint16_t weather[15];?

    Leider klappts da nicht viel bis jetzt, Tutorial hab ich das von RN-Wissen

    Danke
    lg

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    17.08.2004
    Beiträge
    1.065
    Ich wüsste jetzt auhc keine konkrete Antwort, hatte aber mal ähnliche Fragen, vielleicht findest du hier noch ein paar Antworten auf deine: https://www.roboternetz.de/phpBB2/viewtopic.php?t=40386

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Lass ich das typedef weg funktionierts
    Mit typedef erzeugst du einen neuen Typ "dcf_s". Du musst dann erstmal eine Variable dieses neuen Typs erstellen, also z.B.:
    Code:
    dcf_s SomeVar; 
    SomeVar.weather = 3;
    Ohne das typedef erzeugst du eine Variable mit Namen "dcf_s", die du dann direkt verwenden kannst.

    Wo liegt der Unterschied wenn ich bei struct einmal uint16_t weather:15; schreibe oder uint16_t weather[15];?
    Das erste ist ein Bit-Field, das zweite ein Array.

    Nimm es mir bitte nicht krumm, aber bei dir fehlen ja noch essentielle Grundlagen der Programmiersprache C. Bitte nimm dir mal ein C Buch zur Hand und lese dich da etwas ein. Man lernt C nicht mal so eben nebenbei durch Try&Error oder durch ein paar Fragen in einem Forum.
    MfG
    Stefan

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    04.10.2007
    Alter
    39
    Beiträge
    17
    Vielen Dank

    typedef hab ich einfach falsch im Wiki verstanden aber nu klappts. Bitfelder kannte ich bis jetzt einfach nicht da ich sie noch nicht verwenden musste. Bis jetzt immer Arrays verwendet die mir hier auch sinnvoller erscheinen.

    Wie will man denn was neues lernen ausser durch LearningByDoing? Wenn ich ein Buch gelesen habe werd ichs auch nicht gleich perfekt können. Der Code der bis jetzt steht funktioniert ja einwandfrei (vlt nicht besonders schön und gecodet aber funktioniert) und ist auch nur durch LerningByDoing entstanden.

    Die Werte in struct_s.weather schreiben hab ich nun hinbekommen. Hab vergessen das die Werte dabei ja rechts mit dem LSB anfangen
    Ist die Methode so i.O oder gibt es schönere um die Werte in die Struktur zu übernehmen?

    Code:
    #include "avr/io.h"
    #include "function.h"
    #include <avr/interrupt.h>
    
    volatile uint16_t dcf_time = 0;			//Zählvariable DCF Pausen
    uint8_t dcf_before = 1;					//DCF Signal zuvor
    uint8_t dcf_flag = 0;					//DCF Signal aktuell
    uint8_t dcf_ctr = 0;					//DCF Bitzähler
    char dcf[60];							//Codiertes DCF Signal 59 bit
    int temp;
    int temp2[15];
    
    struct
    {
    	int weather:15;
    }dcf_s;
    
    int main (void)
    {
    
    	//Port Konfiguration DCF77 Empfänger
    
    	dcf_ddr &= ~(1<<dcf_bit);      //PinX als Eingang definieren
    	dcf_port |= (1<<dcf_bit);      //Pullup Widerstand für diesen Pin aktivieren
    	   
    
    
    	//Debug Konfiguration, LED1, LED2
    
    
    	DDRC |= (1<<0) | (1<<1);      //Bit0 PortC Ausgang
    	PORTC |= (1<<0) | (1<<1);      //Led an PortC aus   
    
    	//Timer 1 starten, Globale Interrups aktivieren
    	init_timer();
    	//USART initialisieren
    	init_USART();
    
    	/*###############################################
    	#                                 			   #
    	#   Hauptprogramm                 		       #
    	#                                 			   #
    	################################################*/
    	while(1)
    	{
        
    		//##################### DEBUG ### LED1 zeigt DCF77 Signal#####################
    		if (dcf_pin & (1<<dcf_bit))
    			PORTC |= (1<<0);                     // Ausführen wenn HIGH
    		else
    			PORTC &= ~(1<<0);                     // Ausführen wenn LOW
    	}
    return 0; 
    }
    
    
    
    
    
    //Portzustand DCF77 einlesen und in dcf_flag schreiben
    int get_dcf_bit()
    {
    	if (dcf_pin & (1<<dcf_bit))
    	{
    		dcf_flag = 1;
    
    	}else{
    		dcf_flag = 0;
    	}
    return(dcf_flag); 
    }
       
    SIGNAL (SIG_OUTPUT_COMPARE1A)
    {
    	PORTC ^= (1<<1);      //DEBUG Zeige Frequenz vom Timer-Interrupt an LED2
    	get_dcf_bit();         //Pegel vom DCF Signal einlesen und in dcf_flag speichern
       
    	if(dcf_flag == 1)      //Wenn DCF Signal HIGH > Zeit messen
    	{
    		if(dcf_flag == dcf_before)      //Führe aus, wenn sich Pegel nicht geändert hat
    		{      
    			dcf_time += 20;            //Zeit +20ms
    		}else{                   //Führe aus bei Pegeländerung
    			if(dcf_time > 770 && dcf_time < 830)		//Erkenne Pause von 800 ms = logisch 1
    			{
    				if(dcf_ctr <= 14)
    				{
    					dcf_s.weather |= (1<<dcf_ctr);
    				}
    				dcf[dcf_ctr] = '1';
    				dcf_ctr++;
    			}
    			if(dcf_time > 870 && dcf_time < 930)		//Erkenne Pause von 900 ms = logisch 0
    			{
    				if(dcf_ctr <= 14)
    				{
    					dcf_s.weather &= ~(1<<dcf_ctr);
    				}
    				dcf[dcf_ctr] = '0';
    				dcf_ctr++;
    			}
    			if(dcf_time > 1770 && dcf_time < 1830)		//Erkenne Pause von 1800 ms = logisch 1, Ende der Übertragung
    			{
    				if(dcf_ctr <= 14)
    				{
    					dcf_s.weather |= (1<<dcf_ctr);
    				}
    				dcf[dcf_ctr] = '1';
    				temp = dcf_s.weather;
    				itoa(temp,temp2,2);
    				//sendUSART(dcf);
    				//sendUSART("\r\n");
    				sendUSART("Wetter: ");
    				sendUSART(temp2);
    				sendUSART("\r\n");
    				dcf_ctr = 0;
    			}
    			if(dcf_time > 1870 && dcf_time < 1930)			//Erkenne Pause von 1900 ms = logisch 0, Ende der Übertragung
    			{
    				if(dcf_ctr <= 14)
    				{
    					dcf_s.weather &= ~(1<<dcf_ctr);
    				}
    				dcf[dcf_ctr] = '0';
    				temp = dcf_s.weather;
    				itoa(temp,temp2,2);
    				//sendUSART(dcf);
    				//sendUSART("\r\n");
    				sendUSART("Wetter: ");
    				sendUSART(temp2);
    				sendUSART("\r\n");
    				dcf_ctr = 0;
    			}
    			dcf_time = 0;            //Zeitvariable zurücksetzen
    		}
    	}
    dcf_before = dcf_flag;            //Alten Pegel in der Variable dcf_before speichern
    }

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    Hallo Wasserkäfer,

    bei meinem DCF77-Decoder für den RP6 ...
    https://www.roboternetz.de/phpBB2/viewtopic.php?t=34240
    ... habe ich z.B. diesen uint64_t Typ für DCF77 genommen:
    Code:
    typedef union {
    	uint64_t bits;						// All DCF77 bits
    	struct {
    		unsigned weather		: 15;	// Bits 0..14: Coded weather info
    		unsigned flags			:  6;	// R:  Call bit 15 for PTB employees
    										// A1: Announcement of a time zone change
    										// Z1: Time zone 1 [0 = MEZ, 1 = MESZ]
    										// Z2: Time zone 2 [1 = MEZ, 0 = MESZ]
    										// A2: Announcement of a leap second
    										// S:  Start bit 20 (always 1)
    		unsigned minute			:  7;	//     7 bits for the minute (BCD)
    		unsigned bit_P1			:  1;	// P1: Minute parity bit 28
    		unsigned hour			:  6;	//     6 bits for the hour (BCD)
    		unsigned bit_P2			:  1;	// P2: Hour parity bit 35
    		unsigned day			:  6;	//     6 bits for the day (BCD)
    		unsigned weekday		:  3;	//     3 bits for the weekday
    		unsigned month			:  5;	//     5 bits for the month (BCD)
    		unsigned year			:  8;	//     8 bits for the year (BCD)
    		unsigned bit_P3			:  1;	// P3: Date parity bit 58
    		unsigned bit_59			:  1;	// Leap second bit 59 (always 0)
    		unsigned notused		:  4;	// Bits 60..63: Not used
    	};
    } dcf77_t;
    Da schiebe ich dann alle Bits des DCF-Telegramms rein und kann mir dann die einzelnen Werte (f. Stunde, Minute ...) da wieder rausziehen.

    Vielleicht wäre das auch was für dich. Sieh dir die Libs doch 'mal an.

    Gruß Dirk

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    04.10.2007
    Alter
    39
    Beiträge
    17
    Hi,

    hab mir deine Libs jetzt mal angeschaut und teilweise versteh ichs auch.
    Nur zum Verständniss: Du kannst dir da die einzelnen Werte aus der Union wieder rausziehen weil bei einer Union ja die einzelnen Werte übereinander auf dem selben Speicherplatz liegen. Somit ist dcf77_t.bits und die geschachtelte Struktur übereinander. Stimmt das so?

    Aber leider ist mir nicht ganz klar, wie du die empfangenen Informationen in dcf77_t.bits reinschiebst.

    Das hier müsste ja eine Pausenerkennung sein:
    Code:
    if ((duration > (PAUSE_900MS - PAUSE_DEVIATION))
    		 && (duration < (PAUSE_900MS + PAUSE_DEVIATION))) {
    			dcfbit = BIT_0;
    			dcfstream.bits &= ~bitstream_mask;
    			bitstream_mask <<= 1;
    Wird eine 0 erkannt weist du dcfbit = 0b00000000 zu. (Warum? dcfbit hat doch nichts mit dcf77_t.bits zu tun)
    Die nächsten zwei Zeilen mit dcfstream.bits und bitstream_mask sind mir vollkommen unklar. Woher kommen die 2 Variablen?
    Was die zwei Zeilen ausführen hoff ich verstanden zu haben:

    dcfstream.bits &= ~bitstream_mask;
    UND - Verknüpfung von dcfstream.bits und invertiertem bitstream_mask

    bitstream_mask <<= 1;
    bitstream_mask um 1 nach links schieben und in bitstream_mask speichern


    Danke schonmal für die Hilfe

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    04.10.2007
    Alter
    39
    Beiträge
    17
    So nach einem Tag intensiven Lib anschaun habe ich den Teil soweit verstanden. Es sind nur 3 kleine Fragen geblieben ^^

    1. Für was benötigt man dcfbit = Bit_0; bzw. Bit_1;?
    2. Warum reicht static uint64_t bitstream_mask;?
    Müsste man die Variable nicht mit 1 vorladen da diese ja nach links
    durchgeschoben wird?
    3. Braucht man unbedingt static für die Variablen?

    Vielen Dank schonmal

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    Sorry, war im Urlaub, daher erst jetzt:

    Zu 1:
    Mit dcfbit = ... werden die 4 Bit-Varianten (0/1-Bit und 0/1-Lastbit, d.h. Telegrammende) bezeichnet.

    Verwendet wird das dann später in 2 Abfragen:
    if (dcfbit != BIT_ERROR) {...
    Dieser Teil wird nur ausgeführt, wenn eine der 4 Varianten erkannt wurde.
    ... und ...
    if (dcfbit & LASTBIT_0) {...
    Da wird getestet, ob ein Lastbit (also Telegrammende) vorliegt.

    Zu 2:
    Stimmt: Immer wenn ein Lastbit erkannt wurde (Pause 1800 oder 1900ms), wird mit ...
    bitstream_mask = 1;
    ... diese Variable wieder mit 1 vorgeladen, sonst um eine Stelle nach links geschoben.

    Zu 3:
    Ja.

    Gruß Dirk

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad