PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Auswertung eines DCF77-Signals mit Atmega32



Mister232
10.03.2014, 10:42
Hallo Leute,

versuche mich gerade daran das Signal eines DCF77-Moduls von Reichelt auszuwerten und die aktuelle Zeit per serielle Schnittstelle an einen Computer zu senden. Am PC empfange ich auch etwas, nur leider nicht die aktuelle Zeit. Er zählt einfach die Sekunden hoch und zeigt mir den aktuellen Stand an. Hier mal die main-Datei und die Dtaei in welcher das Signal ausgewertet wird:



/*
* main.c
*
* Created: 27.02.2014 13:27:29
* Author: Jens
*
* This program receives the DCF77 signal from a DCF77-Module from Reichelt and evaluates the
* received data. The calculated time will be transmitted to a computer via UART. The program
* is written for an ATmega32 device
*
*/

#include "global.h"
#include "uart.h"
#include "DCF77.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
char msgBuffer[100];

// Initialize the UART-Interface with 4800 baud
init_UART(4800);
strcpy(msgBuffer, "*********** DCF77-Clock **************\n");
uart_write_msg(msgBuffer,strlen(msgBuffer));

// Enable global interrupts
sei();

// Start DCF77 clock
strcpy(msgBuffer, "Starting clock...");
uart_write_msg(msgBuffer,strlen(msgBuffer));
Start_Clock();
strcpy(msgBuffer, "Done\n");
uart_write_msg(msgBuffer,strlen(msgBuffer));

while(1)
{
// Transmit actual time to the computer
sprintf(msgBuffer, "Time: %i:%i:%i \n", hh, mm, ss);
uart_write_msg(msgBuffer,strlen(msgBuffer));

// Wait
_delay_ms(1000);
}

return 0;
}




/*
* main.c
*
* Created: 27.02.2014 00:10:17
* Author: Jens
*
* This file includes control functions for the use of a DCF77 module from Reichelt
*
*/

#include "DCF77.h"
#include "global.h"
#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned char ss = 0; // Seconds
volatile unsigned char mm = 0; // Minutes
volatile unsigned char hh = 0; // Hours

// Bit-counter for RX bit
volatile unsigned char rx_bit_counter = 0;

// 64 Bit, for DCF77 used 59 Bits
volatile unsigned long long dcf_rx_buffer = 0;

// Help-counter for seconds
volatile unsigned int h_ss = 0;

// Help-variable for hour-change
volatile unsigned int h_hh = 0;

// Timer1 overflow Interrupt, triggered by 59. second or no received DCF77 signal
ISR(TIMER1_OVF_vect)
{
struct DCF77_Bits *rx_buffer;
rx_buffer = (struct DCF77_Bits*)(char*)&dcf_rx_buffer;

// Reset timer
TCNT1 = 65535 - (F_CPU / 1024);

// If all 59 Bits and the parity's are correctly received, set clock to DCF77 signal
if ((rx_bit_counter == 59) && (flags.parity_P1 == rx_buffer->P1) && (flags.parity_P2 == rx_buffer->P2) && (flags.parity_P3 == rx_buffer->P3))
{
// Calculate minutes BCD to HEX
mm = rx_buffer->Min - ((rx_buffer->Min / 16) * 6);

if(mm != 0)
{
mm--;
}
else
{
mm = 59;
h_hh = 1;
}

// Calculate hours BCD to HEX
hh = rx_buffer->Hour - ((rx_buffer->Hour / 16) * 6);

if(h_hh)
{
hh--;
h_hh = 0;
}

// Reset seconds to zero
ss = 59;
flags.dcf_sync = 1;
}
else
{
// Manually set the clock
Add_one_Second();
flags.dcf_sync = 0;
}

// Reset the RX Bit-Counter
rx_bit_counter = 0;
// Clear the RX buffer
dcf_rx_buffer = 0;
}

// Interrupt on INT0, DCF77 Module receives time information
ISR(INT0_vect)
{
// Evaluate pulse width
if(INT0_CONTROL == INT0_RISING_EDGE)
{
flags.dcf_rx ^= 1;

// Calculate second help-counter
h_ss = h_ss + TCNT1 - (65535 - (F_CPU / 1024));
// Reset timer
TCNT1 = 65535 - (F_CPU / 1024);

// Check if a second is over
if(h_ss > (F_CPU / 1024 / 100 * 90)) //90% from 1 second
{
Add_one_Second();
// Reset second help-counter
h_ss = 0;
}

// Next interrupt with falling edge
INT0_CONTROL = INT0_FALLING_EDGE;
}
else
{
// Read pulse width from rising edge to falling edge
unsigned int pulse_wide = TCNT1;
// Reset timer
TCNT1 = 65535 - (F_CPU / 1024);
// Calculate second help-counter
h_ss = h_ss + pulse_wide - (65535 - (F_CPU / 1024));

//Safe parity:
// Begin area P1/P2/P3
if((rx_bit_counter == 21) || (rx_bit_counter == 29) || (rx_bit_counter == 36))
{
flags.parity_err = 0;
}
// Safe P1
if(rx_bit_counter == 28)
{
flags.parity_P1 = flags.parity_err;
}
//Safe P2
if(rx_bit_counter == 35)
{
flags.parity_P2 = flags.parity_err;
}
//Safe P3
if(rx_bit_counter == 58)
{
flags.parity_P3 = flags.parity_err;
}

// Check if a 0 or 1 is received
//0 = 100 ms
//1 = 200 ms
// > 150ms (15% from 1 second -> 150ms)
if(pulse_wide > (65535 - (F_CPU / 1024) / 100 * 85))
{
// Write a 1 into the dcf_rx_buffer at position rx_bit_counter
dcf_rx_buffer = dcf_rx_buffer | ((unsigned long long) 1 << rx_bit_counter);
//Toggle Help-Parity
flags.parity_err = flags.parity_err ^ 1;
}

// Next interrupt with rising edge
INT0_CONTROL = INT0_RISING_EDGE;
// Inkrement RX Bit-Counter
rx_bit_counter++;
}
}

// Function to add a second to the actual time value
void Add_one_Second (void)
{
ss++;

// Check if a minute is done
if (ss == 60)
{
ss = 0;
mm++;

// Check if a hour is done
if (mm == 60)
{
mm = 0;
hh++;

// Check if the day is finished
if (hh == 24)
{
hh = 0;
}
}
}
};

// Function to initialize and start the timer
void Start_Clock (void)
{
// Enable interrupt on DCF77 with rising edge
DCF77_INT_ENABLE();
INT0_CONTROL = INT0_RISING_EDGE;

// Interrupt overflow enable
TIMSK1 |= (1 << TOIE1);
// Set prescaler to 1024
TCCR1B |= (1<<CS10 | 0<<CS11 | 1<<CS12);
TCNT1 = 65535 - (F_CPU / 1024);
}


Und der Header zur Signalauswertung:


/*
* DCF77.h
*
* Created: 27.02.2014 10:20:46
* Author: Jens
*/


#ifndef DCF77_H_
#define DCF77_H_

volatile unsigned char ss; // Seconds
volatile unsigned char mm; // Minutes
volatile unsigned char hh; // Hours

extern void Start_Clock (void); // Function to start the DCF77-Clock
extern void Add_one_Second (void); // Function to add one second to the actual time

// 64 Bit, for DCF77 used 59 Bits
volatile unsigned long long dcf_rx_buffer;
// RX Pointer (Counter)
volatile extern unsigned char rx_bit_counter;
// Help-Counter for seconds
volatile unsigned int h_ss;

// INT0 Interrupt definitions
#define DCF77_INT_ENABLE() GICR |= (1<<INT0);
#define INT0_CONTROL MCUCR
#define INT0_FALLING_EDGE 0x02
#define INT0_RISING_EDGE 0x03
#define TIMSK1 TIMSK

//Structure of the dcf_rx_buffer
struct DCF77_Bits {
unsigned char M :1 ;
unsigned char O1 :1 ;
unsigned char O2 :1 ;
unsigned char O3 :1 ;
unsigned char O4 :1 ;
unsigned char O5 :1 ;
unsigned char O6 :1 ;
unsigned char O7 :1 ;
unsigned char O8 :1 ;
unsigned char O9 :1 ;
unsigned char O10 :1 ;
unsigned char O11 :1 ;
unsigned char O12 :1 ;
unsigned char O13 :1 ;
unsigned char O14 :1 ;
unsigned char R :1 ;
unsigned char A1 :1 ;
unsigned char Z1 :1 ;
unsigned char Z2 :1 ;
unsigned char A2 :1 ;
unsigned char S :1 ;
unsigned char Min :7 ;// 7 Bits for minutes
unsigned char P1 :1 ;// Parity minutes
unsigned char Hour :6 ;// 6 Bits for hours
unsigned char P2 :1 ;// Parity hours
unsigned char P3 :1 ;// Parity from P2
};

struct
{
volatile char parity_err :1 ;// Help Parity
volatile char parity_P1 :1 ;// Calculated Parity P1
volatile char parity_P2 :1 ;// Calculated Parity P2
volatile char parity_P3 :1 ;// Calculated Parity P3
volatile char dcf_rx :1 ;// A impulse is received
volatile char dcf_sync :1 ;// The clock was synchronized in the last minute
}flags;

#endif /* DCF77_H_ */


Ich hoffe ihr könnt mir weiterhelfen ;)

Gruß
Mister232

JoeM1978
10.03.2014, 21:28
C is nicht unbedingt mein Favorit... und ich kann mich sicher auch Täuschen...
aber ich würde mal das genauer kontrollieren:

if ((rx_bit_counter == 59) && (flags.parity_P1 == rx_buffer->P1) && (flags.parity_P2 == rx_buffer->P2) && (flags.parity_P3 == rx_buffer->P3))

Anscheinend muss ja diese Bedingung nicht erfüllt sein... daher geht das Programm dazu über die sekunden "manuell" zu zählen.

oder der Interrupt meldet nie, das die DCF ein Signal gesendet hat.