Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Balkonkraftwerk Speicher und Wechselrichter Tests und Tutorials

(Kategorie)
Zeile 1: Zeile 1:
 
Dieser Artikel befindet sich möglichrweise im Aufbau. Siehe [[Diskussion:Codesammlung_avr-gcc]]
 
Dieser Artikel befindet sich möglichrweise im Aufbau. Siehe [[Diskussion:Codesammlung_avr-gcc]]
 +
 +
=IR-Empang=
 +
==RC5 Decoder für AVR Mega==
 +
===Beschreibung===
 +
====Resourcen====
 +
{| {{Blauetabelle}}
 +
|'''Resource'''
 +
|'''Verbrauch (mit <code>-Os</code>)'''
 +
|-
 +
|I/O
 +
|Timer0, 1 Pin für extern INT
 +
|-
 +
|Interrupts
 +
|Timer0 Overflow, 1 externer IRQ
 +
|-
 +
|Flash
 +
| ~ 0x180
 +
|-
 +
|SRAM
 +
| statisch: 8<br>Stack: 0x15
 +
|-
 +
|Laufzeit
 +
| ?
 +
|}
 +
 +
====Interface====
 +
<pre>
 +
#define RC5_INT0 0
 +
#define RC5_INT1 1
 +
 +
#define RC5_ALL 0xff
 +
 +
typedef struct
 +
{
 +
uint8_t code;
 +
uint8_t addr;
 +
volatile char flip;
 +
} rc5_t;
 +
 +
extern rc5_t rc5;
 +
extern void rc5_init (uint8_t addr);
 +
</pre>
 +
 +
;<code>void rc5_init (uint8_t addr)</code>: Initialisiert die Hardware für RC5-Empfang. Akzeptiert wird Code, der an Adresse <code>addr</code> geschickt wird. Falls <code>addr = RC5_ALL</code> bzw Bit 7 von <code>addr</code> gesetzt ist, werden alle Adressen akzeptiert.
 +
;<code>extern rc5_t rc5</code>: In <code>rc5</code> wird der empangene RC5-Code geliefert.
 +
:;<code>rc5.code</code>: der empfangene RC5-Code, falls <code>rc5.flip != -1</code>
 +
:;<code>rc5.addr</code>: die Adresse, an die gesendet wurde, falls <code>rc5.flip != -1</code>
 +
:;<code>rc5.flip</code>: das Flip-Bit
 +
::;<code>rc5.flip = 0</code>: Flip-Bit ist 0, RC5-Empfang inaktiv
 +
::;<code>rc5.flip = 1</code>: Flip-Bit ist 1, RC5-Empfang inaktiv
 +
::;<code>rc5.flip = -1</code>: RC5-Empfang aktiv, wartet auf nächste Übertragung
 +
 +
{| {{Blauetabelle}}
 +
|'''Define'''
 +
|'''default'''
 +
|'''Werte'''
 +
|'''Beschreibung'''
 +
|-
 +
|<code>RC5_INT</code>
 +
|<code>RC5_INT0</code>
 +
|<code>RC5_INT0</code>, <code>RC5_INT1</code>
 +
|Code wird generiert für INT0 resp. INT1, zB gcc-Aufruf mit <code>-DRC5_INT=RC5_INT1</code> erzeugt Code für INT1
 +
|-
 +
|<code>RC5_PRESCALE</code>
 +
|<code>1024</code>
 +
|<code>64, 256, 1024</code>
 +
|Legt den Prescaler für Timer0 fest. Standardeinstellung auf 1024, was zu F_CPU=16000000 passt. Für kleinere CPU-Frequenzen muss evtl ein kleinerer PRESCALE gewählt werden; das geht noch nicht automatisch.
 +
|-
 +
|<code>F_CPU</code>
 +
|
 +
|
 +
|Gibt die CPU-Frequenz in Hz an
 +
|}
 +
 +
===Code===
 +
 +
====rc5.c====
 +
 +
<pre>
 +
#include <avr/io.h>
 +
#include <avr/signal.h>
 +
 +
#include "rc5.h"
 +
 +
#ifndef RC5_INT
 +
#define RC5_INT      RC5_INT0
 +
#endif  // RC5_INT
 +
 +
#ifndef RC5_PRESCALE
 +
#define RC5_PRESCALE 1024
 +
#endif  // RC5_PRESCALE
 +
 +
//////////////////////////////////////////////////////////////////////////////
 +
 +
rc5_t rc5;
 +
 +
//////////////////////////////////////////////////////////////////////////////
 +
 +
// µs for a whole bit of RC5 (first & second part)
 +
#define RC5_BIT_US  (64*27)
 +
 +
#define RC5_TICKS \
 +
((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE)))
 +
 +
#define RC5_DELTA \
 +
(RC5_TICKS / 6)
 +
 +
typedef union
 +
{
 +
uint16_t w;
 +
uint8_t b[2];
 +
 +
struct
 +
{
 +
unsigned code:6;
 +
unsigned addr:5;
 +
unsigned flip:1;
 +
unsigned agc:4;
 +
} __attribute__ ((packed));
 +
 +
} code_t;
 +
 +
static code_t code;
 +
static uint8_t rc5_addr;
 +
 +
// Number of Bits received so far
 +
// Number of Interrupts occured so far;
 +
#ifndef RC5_DEBUG
 +
static uint8_t nbits;
 +
static uint8_t nint;
 +
#else
 +
uint8_t nbits;
 +
uint8_t nint;
 +
uint16_t * const prc5_code = &code.w;
 +
#endif // !RC5_DEBUG
 +
 +
//////////////////////////////////////////////////////////////////////////////
 +
 +
void
 +
rc5_init (uint8_t addr)
 +
{
 +
nint = 0;
 +
nbits = 0;
 +
rc5.flip = -1;
 +
 +
rc5_addr = addr;
 +
 +
#if (RC5_PRESCALE==1024)
 +
TCCR0 = (1 << CS02) | (1 << CS00);
 +
#elif (RC5_PRESCALE==256)
 +
TCCR0 = (1 << CS02);
 +
#elif (RC5_PRESCALE==64)
 +
TCCR0 = (1 << CS01) | (1 << CS00);
 +
#else
 +
#error This RC5_PRESCALE is not supported
 +
#endif // RC5_PRESCALE
 +
 +
// INTx on falling edge
 +
// clear pending INTx
 +
// enable INTx interrupt
 +
#if (RC5_INT == RC5_INT0)
 +
MCUCR |=  (1 << ISC01);
 +
MCUCR &= ~ (1 << ISC00);
 +
GIFR = (1 << INTF0);
 +
GICR |= (1 << INT0);
 +
#elif (RC5_INT == RC5_INT1)
 +
MCUCR |=  (1 << ISC11);
 +
MCUCR &= ~ (1 << ISC10);
 +
GIFR = (1 << INTF1);
 +
GICR |= (1 << INT1);
 +
#else
 +
#error please define RC5_INT
 +
#endif // RC5_INT
 +
}
 +
 +
//////////////////////////////////////////////////////////////////////////////
 +
 +
SIGNAL (SIG_OVERFLOW0)
 +
{
 +
TIMSK &= ~(1 << TOIE0);
 +
 +
uint8_t _nbits = nbits;
 +
code_t _code = code;
 +
 +
if (26 == _nbits)
 +
{
 +
_nbits++;
 +
_code.w <<= 1;
 +
}
 +
 +
if (27 == _nbits
 +
&& 3 == _code.agc
 +
&& 0 > rc5.flip)
 +
{
 +
uint8_t _rc5_code;
 +
uint8_t _rc5_addr;
 +
// we do the bit manipulation stuff by hand, because of code size
 +
_rc5_code = _code.b[0] & 0x3f; // 0b00111111 : #0..#5
 +
_code.w <<= 2;
 +
_rc5_addr = _code.b[1] & 0x1f; // 0b00011111 : #6..#10
 +
 +
if (rc5_addr & 0x80
 +
|| rc5_addr == _rc5_addr)
 +
{
 +
rc5.code = _rc5_code;
 +
rc5.addr = _rc5_addr;
 +
char flip = 0;
 +
if (_code.b[1] & 0x20) // 0b00100000 : #11
 +
flip = 1;
 +
rc5.flip = flip;
 +
}
 +
}
 +
 +
nint = 0;
 +
nbits = 0;
 +
 +
// INTx on falling edge
 +
// clear pending INTx
 +
// enable INTx interrupt
 +
#if (RC5_INT == RC5_INT0)
 +
MCUCR |=  (1 << ISC01);
 +
MCUCR &= ~ (1 << ISC00);
 +
GIFR = (1 << INTF0);
 +
GICR |= (1 << INT0);
 +
#elif (RC5_INT == RC5_INT1)
 +
MCUCR |=  (1 << ISC11);
 +
MCUCR &= ~ (1 << ISC10);
 +
GIFR = (1 << INTF1);
 +
GICR |= (1 << INT1);
 +
#endif
 +
}
 +
 +
//////////////////////////////////////////////////////////////////////////////
 +
 +
#if (RC5_INT == RC5_INT0)
 +
SIGNAL (SIG_INTERRUPT0)
 +
#elif (RC5_INT == RC5_INT1)
 +
SIGNAL (SIG_INTERRUPT1)
 +
#endif // RC5_INT
 +
{
 +
code_t _code = code;
 +
uint8_t _nint = nint;
 +
 +
if (0 == _nint)
 +
{
 +
// INTx on both edges
 +
// clear pending INTx
 +
#if (RC5_INT == RC5_INT0)
 +
MCUCR &= ~ (1 << ISC01);
 +
MCUCR |=  (1 << ISC00);
 +
GIFR = (1 << INTF0);
 +
#elif (RC5_INT == RC5_INT1)
 +
MCUCR &= ~ (1 << ISC11);
 +
MCUCR |=  (1 << ISC10);
 +
GIFR = (1 << INTF1);
 +
#endif // RC5_INT
 +
 +
TCNT0 = 0;
 +
TIFR = (1 << TOV0);
 +
TIMSK |= (1 << TOIE0);
 +
_code.w = 0;
 +
}
 +
else
 +
{
 +
uint8_t tcnt0 = TCNT0;
 +
 +
TCNT0 = 0;
 +
 +
// Number of bits of the just elapsed period;
 +
uint8_t n = 1;
 +
// Bits received so far
 +
uint8_t _nbits = nbits;
 +
 +
// is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ?
 +
if (tcnt0 > RC5_TICKS + RC5_DELTA)
 +
goto invalid;
 +
else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA)
 +
goto invalid;
 +
else if (tcnt0 > RC5_TICKS - RC5_DELTA)
 +
n = 2;
 +
else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA)
 +
goto invalid;
 +
 +
// store the just received 1 or 2 bits
 +
do
 +
{
 +
_nbits++;
 +
if (_nbits & 1)
 +
{
 +
_code.w <<= 1;
 +
_code.b[0] |= _nint & 1;
 +
}
 +
}
 +
while (--n);
 +
 +
if (0)
 +
{
 +
invalid:
 +
 +
// disable INTx, run into Overflow0
 +
#if (RC5_INT == RC5_INT0)
 +
GICR &= ~(1 << INT0);
 +
#elif (RC5_INT == RC5_INT1)
 +
GICR &= ~(1 << INT1);
 +
#endif // RC5_INT
 +
 +
_nbits = 0;
 +
}
 +
 +
nbits = _nbits;
 +
}
 +
 +
code = _code;
 +
nint = 1+_nint;
 +
}
 +
</pre>
 +
 +
====rc5.h====
 +
<pre>
 +
#ifndef _RC5_H_
 +
#define _RC5_H_
 +
 +
#include <inttypes.h>
 +
 +
#define RC5_INT0 0
 +
#define RC5_INT1 1
 +
 +
#define RC5_ALL 0xff
 +
 +
typedef struct
 +
{
 +
uint8_t code;
 +
uint8_t addr;
 +
volatile char flip;
 +
} rc5_t;
 +
 +
extern rc5_t rc5;
 +
extern void rc5_init (uint8_t addr);
 +
 +
#ifdef RC5_DEBUG
 +
extern uint16_t * const prc5_code;
 +
extern uint8_t nbits;
 +
extern uint8_t nint;
 +
#endif // RC5_DEBUG
 +
 +
#endif /* _RC5_H_ */
 +
</pre>
 +
 +
====Beispiele====
 +
 +
'''<code>Beispiel: Anwendung</code>'''
 +
<pre>
 +
#include <avr/io.h>
 +
#include <avr/interrupt.h>
 +
 +
#include "rc5.h"
 +
 +
...
 +
// Code atomar machen
 +
uint8_t sreg = SREG;
 +
cli();
 +
// Gibt's was Neues?
 +
if (-1 == rc5.flip)
 +
{
 +
// Nein, dann zurück
 +
SREG = sreg;
 +
return;
 +
}
 +
// Ja, dann code merken
 +
uint8_t code = rc5.code;
 +
// und auf nächstes Zeichen warten
 +
rc5.flip = -1;
 +
SREG = sreg;
 +
...
 +
</pre>
 +
 +
'''<code>Beispiel: Initialisierung</code>'''
 +
<pre>
 +
#include <avr/io.h>
 +
#include <avr/interrupt.h>
 +
 +
#include "rc5.h"
 +
 +
...
 +
// RC5 initialisieren, alle Adressen zulassen
 +
rc5_init (RC5_ALL);
 +
 +
// Interrupts zulassen
 +
sei();
 +
...
 +
</pre>
  
 
[[Kategorie:Software]]
 
[[Kategorie:Software]]

Version vom 3. Dezember 2005, 15:38 Uhr

Dieser Artikel befindet sich möglichrweise im Aufbau. Siehe Diskussion:Codesammlung_avr-gcc

IR-Empang

RC5 Decoder für AVR Mega

Beschreibung

Resourcen

Resource Verbrauch (mit -Os)
I/O Timer0, 1 Pin für extern INT
Interrupts Timer0 Overflow, 1 externer IRQ
Flash ~ 0x180
SRAM statisch: 8
Stack: 0x15
Laufzeit  ?

Interface

#define RC5_INT0 0
#define RC5_INT1 1

#define RC5_ALL 0xff

typedef struct
{
	uint8_t code;
	uint8_t addr;
	volatile char flip;
} rc5_t;

extern rc5_t rc5;
extern void rc5_init (uint8_t addr);
void rc5_init (uint8_t addr)
Initialisiert die Hardware für RC5-Empfang. Akzeptiert wird Code, der an Adresse addr geschickt wird. Falls addr = RC5_ALL bzw Bit 7 von addr gesetzt ist, werden alle Adressen akzeptiert.
extern rc5_t rc5
In rc5 wird der empangene RC5-Code geliefert.
rc5.code
der empfangene RC5-Code, falls rc5.flip != -1
rc5.addr
die Adresse, an die gesendet wurde, falls rc5.flip != -1
rc5.flip
das Flip-Bit
rc5.flip = 0
Flip-Bit ist 0, RC5-Empfang inaktiv
rc5.flip = 1
Flip-Bit ist 1, RC5-Empfang inaktiv
rc5.flip = -1
RC5-Empfang aktiv, wartet auf nächste Übertragung
Define default Werte Beschreibung
RC5_INT RC5_INT0 RC5_INT0, RC5_INT1 Code wird generiert für INT0 resp. INT1, zB gcc-Aufruf mit -DRC5_INT=RC5_INT1 erzeugt Code für INT1
RC5_PRESCALE 1024 64, 256, 1024 Legt den Prescaler für Timer0 fest. Standardeinstellung auf 1024, was zu F_CPU=16000000 passt. Für kleinere CPU-Frequenzen muss evtl ein kleinerer PRESCALE gewählt werden; das geht noch nicht automatisch.
F_CPU Gibt die CPU-Frequenz in Hz an

Code

rc5.c

#include <avr/io.h>
#include <avr/signal.h>

#include "rc5.h"

#ifndef RC5_INT
#define RC5_INT      RC5_INT0
#endif  // RC5_INT

#ifndef RC5_PRESCALE
#define RC5_PRESCALE 1024
#endif  // RC5_PRESCALE

//////////////////////////////////////////////////////////////////////////////

rc5_t rc5;

//////////////////////////////////////////////////////////////////////////////

// µs for a whole bit of RC5 (first & second part)
#define RC5_BIT_US   (64*27)

#define RC5_TICKS \
	((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE)))
	
#define RC5_DELTA \
	(RC5_TICKS / 6)
	
typedef union 
{
	uint16_t w;
	uint8_t b[2];
	
	struct
	{
		unsigned code:6;
		unsigned addr:5;
		unsigned flip:1;
		unsigned agc:4;
	} __attribute__ ((packed));
	
} code_t;

static code_t code;
static uint8_t rc5_addr;

// Number of Bits received so far
// Number of Interrupts occured so far;
#ifndef RC5_DEBUG
static uint8_t nbits;
static uint8_t nint;
#else
uint8_t nbits;
uint8_t nint;
uint16_t * const prc5_code = &code.w;
#endif // !RC5_DEBUG

//////////////////////////////////////////////////////////////////////////////
	
void 
rc5_init (uint8_t addr)
{
	nint = 0;
	nbits = 0;
	rc5.flip = -1;
	
	rc5_addr = addr;
	
#if (RC5_PRESCALE==1024)
	TCCR0 = (1 << CS02) | (1 << CS00);
#elif	(RC5_PRESCALE==256)
	TCCR0 = (1 << CS02);
#elif	(RC5_PRESCALE==64)
	TCCR0 = (1 << CS01) | (1 << CS00);
#else
#error This RC5_PRESCALE is not supported
#endif // RC5_PRESCALE
	
	// INTx on falling edge
	// clear pending INTx
	// enable INTx interrupt
#if (RC5_INT == RC5_INT0)		
	MCUCR |=   (1 << ISC01);
	MCUCR &= ~ (1 << ISC00);
	GIFR = (1 << INTF0);
	GICR |= (1 << INT0);
#elif (RC5_INT == RC5_INT1)		
	MCUCR |=   (1 << ISC11);
	MCUCR &= ~ (1 << ISC10);
	GIFR = (1 << INTF1);
	GICR |= (1 << INT1);
#else
#error please define RC5_INT
#endif // RC5_INT
}

//////////////////////////////////////////////////////////////////////////////

SIGNAL (SIG_OVERFLOW0)
{
	TIMSK &= ~(1 << TOIE0);
	
	uint8_t _nbits = nbits;
	code_t _code = code;
	
	if (26 == _nbits)
	{
		_nbits++;
		_code.w <<= 1;
	}
	
	if (27 == _nbits 
		&& 3 == _code.agc 
		&& 0 > rc5.flip)
	{
		uint8_t _rc5_code;
		uint8_t _rc5_addr;
		// we do the bit manipulation stuff by hand, because of code size
		_rc5_code = _code.b[0] & 0x3f; // 0b00111111 : #0..#5
		_code.w <<= 2;
		_rc5_addr = _code.b[1] & 0x1f; // 0b00011111 : #6..#10
		
		if (rc5_addr & 0x80
			|| rc5_addr == _rc5_addr)
		{
			rc5.code = _rc5_code;
			rc5.addr = _rc5_addr;
			char flip = 0;
			if (_code.b[1] & 0x20) // 0b00100000 : #11
				flip = 1;
			rc5.flip = flip;
		}
	}
	
	nint = 0;
	nbits = 0;
	
	// INTx on falling edge
	// clear pending INTx
	// enable INTx interrupt
#if (RC5_INT == RC5_INT0)		
	MCUCR |=   (1 << ISC01);
	MCUCR &= ~ (1 << ISC00);
	GIFR = (1 << INTF0);
	GICR |= (1 << INT0);
#elif (RC5_INT == RC5_INT1)		
	MCUCR |=   (1 << ISC11);
	MCUCR &= ~ (1 << ISC10);
	GIFR = (1 << INTF1);
	GICR |= (1 << INT1);
#endif
}

//////////////////////////////////////////////////////////////////////////////

#if (RC5_INT == RC5_INT0)		
SIGNAL (SIG_INTERRUPT0)
#elif (RC5_INT == RC5_INT1)		
SIGNAL (SIG_INTERRUPT1)
#endif // RC5_INT
{
	code_t _code = code;
	uint8_t _nint = nint;
	
	if (0 == _nint)
	{
		// INTx on both edges
		// clear pending INTx
#if (RC5_INT == RC5_INT0)		
		MCUCR &= ~ (1 << ISC01);
		MCUCR |=   (1 << ISC00);
		GIFR = (1 << INTF0);
#elif (RC5_INT == RC5_INT1)		
		MCUCR &= ~ (1 << ISC11);
		MCUCR |=   (1 << ISC10);
		GIFR = (1 << INTF1);
#endif // RC5_INT
	
		TCNT0 = 0;
		TIFR = (1 << TOV0);
		TIMSK |= (1 << TOIE0);
		_code.w = 0;
	}
	else
	{
		uint8_t tcnt0 = TCNT0;
		
		TCNT0 = 0;
		
		// Number of bits of the just elapsed period;
		uint8_t n = 1;
		// Bits received so far
		uint8_t _nbits = nbits;
	
		// is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ?
		if (tcnt0 > RC5_TICKS + RC5_DELTA)
			goto invalid;
		else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA)
			goto invalid;
		else if (tcnt0 > RC5_TICKS - RC5_DELTA)
			n = 2;
		else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA)
			goto invalid;
		
		//	store the just received 1 or 2 bits
		do
		{
			_nbits++;
			if (_nbits & 1)
			{
				_code.w <<= 1;
				_code.b[0] |= _nint & 1;
			}
		} 
		while (--n);
		
		if (0)
		{
			invalid:
			
			// disable INTx, run into Overflow0
#if (RC5_INT == RC5_INT0)		
			GICR &= ~(1 << INT0);
#elif (RC5_INT == RC5_INT1)		
			GICR &= ~(1 << INT1);
#endif // RC5_INT			

			_nbits = 0;
		}
		
		nbits = _nbits;
	}

	code = _code;
	nint = 1+_nint;
}

rc5.h

#ifndef _RC5_H_
#define _RC5_H_

#include <inttypes.h>

#define RC5_INT0 0
#define RC5_INT1 1

#define RC5_ALL 0xff

typedef struct
{
	uint8_t code;
	uint8_t addr;
	volatile char flip;
} rc5_t;

extern rc5_t rc5;
extern void rc5_init (uint8_t addr);

#ifdef RC5_DEBUG
extern uint16_t * const prc5_code;
extern uint8_t nbits;
extern uint8_t nint;
#endif // RC5_DEBUG

#endif /* _RC5_H_ */

Beispiele

Beispiel: Anwendung

#include <avr/io.h>
#include <avr/interrupt.h>

#include "rc5.h"

	...
	// Code atomar machen
	uint8_t sreg = SREG;
	cli();
	// Gibt's was Neues?
	if (-1 == rc5.flip)
	{
		// Nein, dann zurück	
		SREG = sreg;
		return;
	}
	// Ja, dann code merken
	uint8_t code = rc5.code;
	// und auf nächstes Zeichen warten
	rc5.flip = -1;
	SREG = sreg;
	...

Beispiel: Initialisierung

#include <avr/io.h>
#include <avr/interrupt.h>

#include "rc5.h"

	...
	// RC5 initialisieren, alle Adressen zulassen
	rc5_init (RC5_ALL);

	// Interrupts zulassen
	sei();
	...

LiFePO4 Speicher Test