IR NEC Empfänger mit 4x7 LED Anzeige (ATtiny2313)

Ähnliche Dokumente
Mikrocontrollerplatine vorbereiten

Atmega Interrupts. Rachid Abdallah Gruppe 3 Betreuer : Benjamin Bös

C.1 Serielle Schnittstelle, erstes Testprogramm (a)

#include "C:\Users\media\Desktop\Harri\Technik\Elektronik\Projekte\Stiftuhr\Servotest\servotest\servotest.h"

WS 2016/17 Viel Erfolg!!

WS 2017/18 Viel Erfolg!!

Serielle Schnittstelle, erstes Testprogramm (a)

Für den CTC-Mode kann demnach TCCR1A komplett auf 0 gesetzt werden, weil WGM11 und WGM10 in diesem Register liegen und beide laut Tabelle 0 sind:

myavr Programmierung in C

ATmega8. Projekte mit AVR-Mikrocontroller. Ein Digitalvoltmeter Seite 1 von 6. Ein Datenlogger

V cc. 1 k. 7 mal 150 Ohm

Lotto. eine Projektarbeit in DVT. von Sven Schwab

by AS playground.boxtec.ch/doku.php/tutorial Multitasking 4

E.1 Einleitung. Teil E Pulsweitenmodulation (PWM) 1

DST EINFÜHRUNG IN MRT

Unter einem Interrupt kann man sich einen durch Hardware ausgelösten Unterprogrammaufruf vorstellen.

DST EINFÜHRUNG IN MRT

Für den Anschluss dieses und anderer Module dieser Serie an das myavr Board steht ein Adapter zur Verfügung.

Übungen zu Systemnahe Programmierung in C (SPiC)

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Globale Variablen

SS 2017 Viel Erfolg!!

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Schnittstellenbeschreibung. Inhalt

Einführung in die Programmierung von Mikrocontrollern mit C/C++

U5-2 Register beim AVR-µC

GdI2 - Systemnahe Programmierung in C Übungen Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2006 U4.fm

Studiengang Maschinenbau, Schwerpunkt Mechatronik (früher: Automatisierungstechnik) Seite 1 von 8

Interrupt-Programmierung

Makros sind Textersetzungen, welche vom Präprozessor aufgelöst werden. Dies Passiert bevor der Compiler die Datein verarbeitet.

Microcontroller Kurs Programmieren Microcontroller Kurs/Johannes Fuchs 1

Richtung durch Taster während des Ablaufs umschaltbar

Wiederholung: Zugriff auf AVR-Prozessor-Register. Aufgabe 3: 7seg-Modul der SPiCboard-Bibliothek

Übungen zu Systemnahe Programmierung in C (SPiC)

Projektarbeit in DVT auf dem Entwicklerboard

Inhalt. Aufgabe 4: LED-Modul Hinweise Testen des Moduls Sommersemester 2015

5 Funktionsbibliothek für den Controller XMC1100

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2017/18

C++ mit dem Arduino (Uno und Mega2560)

Autonome Mobile Systeme. Dr. Stefan Enderle

Parallel-IO. Ports am ATmega128

U3 3. Übung U3 3. Übung. Systemnahe Programmierung in C Übungen Moritz Strübe Universität Erlangen-Nürnberg Informatik 4, 2009 U3.fm

Besprechung Aufgabe 1. Pointer. Register und Ports. SPiC - Ü U3.1

U3-1 Register beim AVR-μC. U3 3. Übung. U3-2 I/O-Ports des AVR-μC. 1 Überblick. 2 Makros für Register-Zugriffe. 1 Überblick

Wiederholung: Zugriff auf AVR-Prozessor-Register. Aufgabe 3: 7seg-Modul der SPiCboard-Bibliothek

Wiederholung: Zugriff auf AVR-Prozessor-Register

Aufgabe 1: Transistor, Diode (ca. 15 Punkte)

Grundlagen der Objektorientierung :

Übungen zu Grundlagen der systemnahen Programmierung in C (GSPiC) im Wintersemester 2017/18

WS 2018/19 Viel Erfolg!!

Sebastian Maier (Lehrstuhl Informatik 4) Übung 4. Sommersemester 2017

Timer. Funktionsprinzip

Wer möchte, kann sein Programm auch auf echter Hardware testen

Aufbau eines Assembler-Programms

Zeiger vom Typ (void *) sind am besten für Zeigerarithmetik geeignet, da sie kompatibel zu jedem Zeigertyp sind.

U Abend 3: Musterlösungen, Taster entprellen, Unterprozeduren, Interrupts, Timer

Rot/Gelb. Grün. Rot. Gelb. G.1 Einleitung

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2017/18

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2018/19

Einführung Sprachfeatures Hinweise, Tipps und Styleguide Informationen. Einführung in C. Patrick Schulz

Erste Gehversuche mit ARDUINO (Teil 3) (DL6OAA) Die 7-Segmentanzeige (1-stellig)

Ansteuerung eines LCD-Screens

8.3 Taster am µcontroller

by AS playground.boxtec.ch/doku.php/tutorial Drehgeber mit RGB LED Drehgeber / Encoder

i2c-bus.de ASCII ZEICHEN AUF DEM HYPERTERMINAL Übungsaufgabe RS232 Schnittstelle Dokument NR.: AB-001-U-01

Projektdokumentation: DCF 77 Funkuhr

#include <pic.h> #include <pic1687x.h> #define FOSC L #define BAUD 9600L

Die Software zum Unser kleiner Computer

Mikrocontroller stromsparend. Uwe Berger

Microcontroller Selbststudium Semesterwoche 9

2.1 Atmega-Peripherie/Interrupts

Projektarbeit aus der Datenverarbeitung. Lotto. von: Hubert Schlenk Olimex AVR USB 162 Entwicklerboard Hubert Schlenk

d) Was passiert, wenn das folgende Programmstück übersetzt und ausgeführt

Stopp-Uhr. Erstellen Sie ein Programm (in Zweier- bzw. Dreier-Gruppen), welches folgende Bedingungen erfüllt:

4 Formelsammlung C/C++

Erste Schritte der Programmierung in C

LED-UHR. Bedienungsanleitung

U2-1 Register beim AVR- C. U2-2 I/O-Ports des AVR- C. 1 Überblick. 2 Makros für Register-Zugriffe. 1 Überblick

C++ mit dem Arduino (Uno und Mega2560)

A B C D E C 5 7 D 3 E. 2. [6-Bit, positiv] Welche Dezimalzahl wird durch die gegebene Bit-Sequenz kodiert?

Anwendung und Programmierung von Mikrocontrollern. Anwendung und Programmierung von Mikrocontrollern

Einführung DIP & AVR EVK1100

Übungen zu Systemnahe Programmierung in C (SPiC)

GREETBoard Stepper L6208. Version 1.0

Dokumentation. LED Cube 8x8x8. ein Praktikumsprojekt von Claudia Denk Severin Völkl. unter der Leitung von Gerald Schickhuber Prof. Georg Scharfenberg

Arduino für FunkAmateure

Interruptsystem AVR. Interrupt-Quellen: Extern, Timer, ADC, USART usw. (siehe IVT im Anhang) Rücksprungadresse automatisch am Stack.

Embedded Systems

Attenuator.mpas :09:01

Tag 2 Eingabe und Interrupts

AVR Ein/Ausgabe. Inhaltsverzeichnis

f) Was versteht man beim Zugriff auf I/O-Register unter dem Begriff "Memory-mapped"?

CCS Compiler Tutorial mit Beispielen

d) Welche Aussage zu volatile ist richtig?

Mikrocontrollertechnik C2 Timer. Einführung

Übungen zu Systemnahe Programmierung in C (SPiC)

Der Magnetfeldsensor HMC5883L

U5 Fortgeschrittene AVR-Programmierung

Forth-Vokabular. Vokabular für Attiny2313-Forth Stand: A: Assembler-Wort F: Forth-Wort C: Compiler-Wort

Klasse, Name : Datum : Rad l/r Linienfolger l/r Laderaum ATMEGA 128

Transkript:

// Include C Libriaries #include <avr/io.h> #define F_CPU 4000000UL #include <util/delay.h> #include <stdio.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> // Definition der Segmente #define SEG_O (1<<PD5) #define SEG_OR (1<<PD4) #define SEG_UR (1<<PD3) #define SEG_U (1<<PD2) #define SEG_UL (1<<PA0) #define SEG_OL (1<<PA1) #define SEG_M (1<<PD1) // Segment oben // Segment oben rechts // NEC Code: Dauer der Puls- und Pausephasen [Anzahl der Interrupts pro Halbbit/Phase] #define dauer_count 40 // Dauer zw. 2 Interrupts = Frequenz LED // 80 khz => 1/80.000 = 12 us // Test wegen uint8 bei Empfänger --> max 256 Counts #define startbit_pulse (9000/dauer_count) // Startbit Pulse = 225 #define startbit_pause (4500/dauer_count) // Startbit Pause = 112 #define datenbit_pulse (560/dauer_count) // Datenbit Pulse = 14 #define datenbit0_pause (560/dauer_count) // 0-Bit Pause = 14 #define datenbit1_pause (1690/dauer_count) // 1-Bit Pause = 42 #define stopbit_pulse (560/dauer_count) // Stopbit Pulse = 14 #define stopbit_pause (3000/dauer_count) // Stopbit Pause = 78 #define toleranz 0.5 // 50% Toleranz für Länge der Phasen // Wiederholte Befehlsfolgen // Sichern der Counts pro Phase und Zuruecksetzen der Variablen #define phasereset IR_signal_changed=0;IR_interrupt_count=0;IR_counts_letzte_phase=0 #define initvariablen modus=0;status_empfang=0;i=0;datenbits=0;ir_signal_changed=0;ir_counter_active=0;ir_interrupt_count=0; IR_counts_letzte_phase=0;LED_interrupt_count=0 // Globale Variablen volatile uint8_t IR_counter_active; volatile uint16_t IR_interrupt_count; volatile uint16_t IR_counts_letzte_phase; volatile uint8_t IR_signal_changed; volatile uint16_t LED_interrupt_count; volatile uint8_t ziffer[3]; // Flag zum Starten/Stoppen des Counters // Zaehler fuer Anzahl Interrupts (= Anzahl LED-Impulse) // Puffer fuer Anzahl Interrupts der abgeschlossenen Phase // Flag bei Signaländerung IR Empfänger (An>Aus>An) // Zaehler fuer Anzahl Interrupts (= Dauer LED-Anzeige pro Zahl) // 4 Ziffern fuer aktuell anzuzeigende Zahl 1

// Tabelle in Programmspeicher fuer LED-Segmente pro Ziffer typedef struct uint8_t porta; uint8_t portd; segmente_t; static const PROGMEM segmente_t segmente_array[] = SEG_UL SEG_OL, SEG_O SEG_OR SEG_UR SEG_U, // Ziffer 0 0, SEG_OR SEG_UR, // Ziffer 1 SEG_UL, SEG_O SEG_OR SEG_U SEG_M, // Ziffer 2 0, SEG_O SEG_OR SEG_UR SEG_U SEG_M, // Ziffer 3 SEG_OL, SEG_OR SEG_UR SEG_M, // Ziffer 4 SEG_OL, SEG_O SEG_UR SEG_U SEG_M, // Ziffer 5 SEG_UL SEG_OL, SEG_O SEG_UR SEG_U SEG_M, // Ziffer 6 0, SEG_O SEG_OR SEG_UR, // Ziffer 7 SEG_UL SEG_OL, SEG_O SEG_OR SEG_UR SEG_U SEG_M, // Ziffer 8 SEG_OL, SEG_O SEG_OR SEG_UR SEG_U SEG_M, // Ziffer 9 0, 0, // aus ; // Funktionsprototypen void displayzahl(uint16_t zahl, uint16_t dauer); void aktivieresegmente(uint8_t ziffer); // Hauptprogramm int main(void) // Variablen deklarieren uint8_t modus; uint8_t status_empfang; uint8_t i; uint32_t datenbits; uint8_t datenbyte[3]; uint16_t zahl; uint16_t dauer; // 0 = IR-Signal empfangen // 1 = Ergebnisse anzeigen // 0 = warten auf Startbit Pulse (Ende) // 1 = warten auf Startbit Pause (Ende) = erstes Datenbit Pulse (Beginn) // 2 = warten auf Datenbit Pulse (Ende) bzw. Stopbit Pulse (Ende) // 3 = warten auf Datenbit Pause (Ende) // 4 = warten auf Stopbit Pause (Ende = Ueberlauf Counter) // Index fuer Array mit Counts pro Phase // Speicherung der 32 empfangenen Datenbits // Aufsplitten in 4 Bytes fuer Anzeige // anzuzeigende Zahl für Display // Anzeigedauer einer Zahl // Variablen initialisieren dauer = 500; // Ports initialisieren DDRB = (1<<PB4) (1<<PB5) (1<<PB6) (1<<PB7); // Ausgang Ziffern DDRA = (1<<PA0) (1<<PA1); // Ausgang Segmente DDRD = (1<<PD0) (1<<PD1) (1<<PD2) (1<<PD3) (1<<PD4) (1<<PD5); // Ausgang Segmente DDRB = (1<<PB2); // Ausgang Kontroll-LED PORTB = 0b00000101; // Eingang IR LED / Konroll-LED aus 2

// Timer initialisieren // IR-Empfang: 4 MHz / (2*55) ~ 40 khz (40.000 Interrupts und LED-Toogle pro Sekunde) TCCR0A=(1<<WGM00); // Phasenkorrekter PWM TCCR0B=(1<<WGM02) (1<<CS00); // Vorteiler 1 OCR0A=55; // Compare-Wert = 55 TCNT0=0; // Zähler auf 0 setzen // LED-Anzeige: 4 MHz / 256 / 30 ~ 520 Hz TCCR1A=(1<<WGM10) (1<<WGM11); // Fast PWM TCCR1B=(1<<WGM12) (1<<WGM13) (1<<CS12); // Vorteiler 256 OCR1A=30; // Compare-Wert = 30 TCNT0=0; // Interrupts initialisieren PCMSK = (1<<PCINT0); GIMSK = (1<<PCIE); TIMSK = (1<<OCIE0A); // Endlosschleife while(1) // Modus "IR Signal empfangen" if (modus==0) cli(); // Interrupt bei Signalaenderung IR LED (Aus>An>Aus) // Interrupt zum Zaehlen der Pulse/Pausen pro Phase // Interrupts deaktivieren switch (status_empfang) // warten auf Startbit Pulse (Ende) case 0: if ((IR_signal_changed==1) && (IR_counts_letzte_phase>=startbit_pulse*(1-toleranz)) && (IR_counts_letzte_phase<=startbit_pulse*(1+toleranz))) status_empfang=1; // warten auf Startbit Pause (Ende) = erstes Datenbit Pulse (Beginn) case 1: if ((IR_signal_changed==2) && (IR_counts_letzte_phase>=startbit_pause*(1-toleranz)) && (IR_counts_letzte_phase<=startbit_pause*(1+toleranz))) status_empfang=2; // falls Startbit Pulse erneut empfangen wird if ((IR_signal_changed==1) && (IR_counts_letzte_phase>=startbit_pulse*(1-toleranz)) && (IR_counts_letzte_phase<=startbit_pulse*(1+toleranz))) status_empfang=1; // Fehler in Signalfolge --> zurueck zu Status 0 if (IR_signal_changed!=0) 3

// warten auf Datenbit Pulse (Ende) bzw. Stopbit Pulse (Ende) case 2: if ((IR_signal_changed==1) && (IR_counts_letzte_phase>=datenbit_pulse*(1-toleranz)) && (IR_counts_letzte_phase<=datenbit_pulse*(1+toleranz))) if (i<=31) status_empfang=3; // Datenbit status_empfang=4; // Stopbit // Fehler in Signalfolge --> zurueck zu Status 0 if (IR_signal_changed!=0) // warten auf Datenbit Pause (Ende) case 3: if ((IR_signal_changed==2) && // 1-Bit (IR_counts_letzte_phase>=datenbit1_pause*(1-toleranz)) && (IR_counts_letzte_phase<=datenbit1_pause*(1+toleranz))) i++; datenbits=(datenbits<<1); datenbits =(1<<0); status_empfang=2; if ((IR_signal_changed==2) && // 0-Bit (IR_counts_letzte_phase>=datenbit0_pause*(1-toleranz)) && (IR_counts_letzte_phase<=datenbit0_pause*(1+toleranz))) i++; datenbits=(datenbits<<1); status_empfang=2; // Fehler in Signalfolge --> zurueck zu Status 0 if (IR_signal_changed!=0) // warten auf Ende des Signals case 4: if (IR_interrupt_count>=2000) IR_counter_active=0; // Counter stoppen modus=1; // Empfang beendet, Ergebnisse anzeigen // Ende switch (status_empfang)... // Ende if (modus==0)... 4

// Modus "Zahl auf Display anzeigen" if (modus==1) TIMSK = (1<<OCIE1A); PORTB&=!(1<<PB2); _delay_ms(300); PORTB =(1<<PB2); // Interrupt zur Steuerung LED Mulitplexing // Kontroll-LED an // Kontroll-LED aus // Datenbits aufbereiten und anzeigen for (i=0;i<4;i++) datenbyte[3-i]=datenbits; datenbits=datenbits/256; for (i=0;i<4;i++) displayzahl(datenbyte[i],dauer); _delay_ms(500); PORTB&=!(1<<PB2); _delay_ms(300); PORTB =(1<<PB2); PCMSK = (1<<PCINT0); GIMSK = (1<<PCIE); TIMSK = (1<<OCIE0A); // Kontroll-LED an // Kontroll-LED aus // Interrupt bei Signalaenderung IR LED (Aus>An>Aus) // Interrupt zum Zaehlen der Pulse/Pausen pro Phase // Variablen initialisieren // Ende if(modus==1)... // Ende while(1)... // Ende main()... 5

// Interrupt Service Routinen ISR(TIMER0_COMPA_vect) if (IR_counter_active) IR_interrupt_count++; ISR(PCINT_vect) IR_counts_letzte_phase=IR_interrupt_count; IR_interrupt_count=0; IR_counter_active=1; // Interrupts (= Dauer Pulse/Pausen) zaehlen // Counter sichern // Counter zuruecksetzen // Counter starten // Eingang ist High, d. h. kein Empfang am TSOP --> Wechsel An>Aus --> Ende/Dauer Pulse-Phase if (PINB & (1<<PB0)) IR_signal_changed=1; // Eingang ist Low, d. h. Empfang am TSOP --> Wechsel Aus>An --> Ende/Dauer Pause-Phase IR_signal_changed=2; ISR(TIMER1_COMPA_vect) uint8_t aktstelle; segmente_t segmente; if(led_interrupt_count>0) LED_interrupt_count--; aktstelle = LED_interrupt_count % 4; // alle Ziffern ausschalten PORTB = (1<<PB0); // Eingang IR auf 1 setzen PORTB &= ~((1<<PB7) (1<<PB6) (1<<PB5) (1<<PB4)); // Ausgang Ziffern auf 0 setzen // Segmente aktivieren memcpy_p(&segmente, segmente_array + ziffer[aktstelle], sizeof(segmente_t)); PORTA = segmente.porta; PORTD = segmente.portd; // Ziffer aktivieren PORTB = (1<<(7-aktStelle)); 6

// Helper Funktionen void displayzahl(uint16_t zahl, uint16_t dauer) // Zahl in Ziffern zerlegen // Einser ziffer[3] = zahl % 10; zahl = zahl / 10; // Zehner if (zahl > 0) ziffer[2] = zahl % 10; ziffer[2] = 10; zahl = zahl / 10; // Hunderter if (zahl > 0) ziffer[1] = zahl % 10; ziffer[1] = 10; zahl = zahl / 10; // Tausender if (zahl > 0) ziffer[0] = zahl % 10; ziffer[0] = 10; cli(); LED_interrupt_count = dauer; while(led_interrupt_count>0); // alle Ziffern und Segmente ausschalten PORTA = 0; PORTB = (1<<PB0); // Eingang IR auf 1 setzen PORTB &= ~((1<<PB7) (1<<PB6) (1<<PB5) (1<<PB4)); // Ausgang Ziffern auf 0 setzen PORTD = 0; 7