1 | //----------------------------------------------------------------------
|
2 | // Titel : RFM12-Reedkontakt für Hausalarmanlage
|
3 | //----------------------------------------------------------------------
|
4 | // Schaltung : Pinbelegung siehe unten
|
5 | // Beschreibung : Überwacht den Batteriestatus und einen Reedkontakt.
|
6 | // Sendet nach Anfrage einen Statusbericht.
|
7 | //----------------------------------------------------------------------
|
8 | // Prozessor : ATmega8L
|
9 | // Takt : 1MHz, intern
|
10 | // Frequenz : 434MHz
|
11 | // Datenrate : 4.8kbps
|
12 | // Datum : 21.09.2015
|
13 | // Version : 1.0
|
14 | // Autor : P. Fuhsy
|
15 | // Fuses : lfuse=0xD0, hfuse=0xC9 (TODO: muss an externen Takt angepasst werden)
|
16 | // : lfuse=0xD4, hfuse=0xC9 (beim Testen)
|
17 |
|
18 | /****************************Pinbelegung********************************
|
19 | ------------------------------------------------------------------------
|
20 | Controller Anschluss Beschreibung
|
21 | ------------------------------------------------------------------------
|
22 | PB0 Reserve
|
23 | PB1 Reserve
|
24 | PB2-SS RFM - nSEL Select Chip
|
25 | PB3-MOSI RFM - SDI Serial Data In
|
26 | PB4-MISO RFM - SDO Serial Data Out
|
27 | PB5-SCK RFM - SCK Serial-Clock
|
28 | PB6-XTAL1 Osc 8MHz externer Quarz
|
29 | PB7-XTAL2 Osc 8MHz externer Quarz
|
30 |
|
31 | PC0 ADC UBAT Messung der Batterie-Spannung
|
32 | PC1 UOUT Messung der Versorgsspannung vorbereitet
|
33 | PC2 DIP-Schalter 1 Dip-Schalter 1 zur Adressierung
|
34 | PC3 DIP-Schalter 2 Dip-Schalter 2 zur Adressierung
|
35 | PC4 DIP-Schalter 3 Dip-Schalter 3 zur Adressierung
|
36 | PC5 DIP-Schalter 4 Dip-Schalter 4 zur Adressierung
|
37 |
|
38 | PD0-RXD Reserve
|
39 | PD1-TXD Reserve
|
40 | PD2-INT0 RFM - nIRQ Interrupt Output
|
41 | PD3-INT1 Ext. Interrupt Reedkontakt
|
42 | PD4 LED-Rot Rot, Low Current LED
|
43 | PD5 RFM - NINT am RFM - NINT vorbereitet
|
44 | PD6 RFM - DCLK am RFM - DCLK vorbereitet
|
45 | PD7 Reserve
|
46 | **********************************************************************/
|
47 | #define F_CPU 8000000UL //CPU festlegen TODO: auf 1MHz ändern
|
48 |
|
49 | #include <avr/io.h> //allg. Ports
|
50 | #include <util/delay.h> //TODO kann später wegfallen wenn Zeitbasis vorhanden
|
51 | #include <string.h> //zum Vergleichen von Strings
|
52 | #include <stdbool.h> //für Bool-Variablen
|
53 | #include <avr/interrupt.h> //für Interrupts
|
54 | #include <inttypes.h>
|
55 |
|
56 | #include "uart.h" //eigene Header
|
57 | #include "ports.h" //eigene Header
|
58 | #include "rfm12.h" //eigene Header
|
59 | #include "haa_bus.h" //eigene Header
|
60 |
|
61 | //------------------------------Funktionsaufruf-----------------------------
|
62 | void initPorts();
|
63 | void initInterrupt();
|
64 | void initADC();
|
65 | void Power_On();
|
66 | char *Wert0_in_str (uint16_t wert);
|
67 | void Sleep();
|
68 | unsigned char RFM_recv_xxx(void);
|
69 |
|
70 | void initPorts() //Ports deklarieren
|
71 | {
|
72 | //Outputs
|
73 | DDRB |= (1<<RFM_SEL); //SEL_OUTPUT
|
74 | DDRB |= (1<<RFM_SDI); //SDI_OUTPUT
|
75 | DDRB |= (1<<RFM_SCK); //SCK_OUTPUT
|
76 | DDRD |= (1<<LED_ROT); //LED für allg. Statuszustand
|
77 |
|
78 | //Ports die nicht benutzt werden als Output deklariert
|
79 | DDRB |= (1<<RESB0); //Reserve
|
80 | DDRB |= (1<<RESB1); //Reserve
|
81 | DDRD |= (1<<RESD0); //Reserve
|
82 | DDRD |= (1<<RESD1); //Reserve
|
83 | DDRD |= (1<<RESD7); //Reserve
|
84 | //Input
|
85 | DDRD &=~(1<<RFM_NINT); //Reserve
|
86 | DDRD &=~(1<<RFM_DCLK); //Reserve
|
87 |
|
88 | //Inputs
|
89 | DDRB &=~(1<<RFM_SDO); //SDO_INPUT
|
90 | DDRC &=~(1<<UBAT); //Batteriespannung
|
91 | DDRC &=~(1<<UOUT); //Spannung am Controller
|
92 | DDRC &=~(1<<DIP1); //Dip-Schalter 1
|
93 | DDRC &=~(1<<DIP2); //Dip-Schalter 2
|
94 | DDRC &=~(1<<DIP3); //Dip-Schalter 3
|
95 | DDRC &=~(1<<DIP4); //Dip-Schalter 4
|
96 | DDRD &=~(1<<REED_0); //Reed 0
|
97 | DDRD &=~(1<<RFM_IRQ); //IRQ_IN
|
98 |
|
99 | //interne Pull-Up-Widerstände einschalten
|
100 | PORTC |= (1<<DIP1); //DIP-Schalter
|
101 | PORTC |= (1<<DIP2); //DIP-Schalter
|
102 | PORTC |= (1<<DIP3); //DIP-Schalter
|
103 | PORTC |= (1<<DIP4); //DIP-Schalter
|
104 | PORTD |= (1<<REED_0); //Reed-Kontakt
|
105 | PORTD |= (1<<RFM_IRQ); //IRQ_IN
|
106 |
|
107 | //Ports initiaisieren, aus LOW setzten
|
108 | Led_Rot_Off();
|
109 | }
|
110 |
|
111 | void initInterrupt() //Port Interrupt initialisieren
|
112 | {
|
113 | MCUCR |= (1<<ISC01) | (0<<ISC00); //fallende Flanke am INT0 Pin als Auslöser
|
114 | MCUCR |= (1<<ISC11) | (1<<ISC01); //steigende Flanke am INT1 Pin als Auslöser
|
115 | GIMSK |= (1<<INT0) | (1<<INT1); //externen Interrupt 0, 1 einschalten
|
116 | sei(); //alle Interrups einschalten
|
117 | }
|
118 |
|
119 | void Power_On()
|
120 | {
|
121 | //POWER ON Prozedur, 3x blinken
|
122 | for(int i=0;i<3;i++)
|
123 | {
|
124 | _delay_ms(500);
|
125 | Led_Rot_On();
|
126 | _delay_ms(500);
|
127 | Led_Rot_Off();
|
128 | }
|
129 |
|
130 | _delay_ms(500);
|
131 | }
|
132 |
|
133 | void Sleep()
|
134 | {
|
135 | /* sei();
|
136 | set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Modus wählen
|
137 | sleep_enable(); //Sleep erlauben
|
138 | TIMSK0 = (0 << OCIE0A); //Timer vorrübergehend ausschalten
|
139 | sleep_mode(); //schlafen gehen
|
140 | */
|
141 | }
|
142 |
|
143 | void Zustand_Anlage() //allg. Zustand des Kontakts abfragen
|
144 | {
|
145 | //REEDkontakt ist geöffnet
|
146 | if (Reed0_ist_offen())
|
147 | {
|
148 | Reed_Alarm(); //Byte STA
|
149 | }
|
150 |
|
151 | //REEDkontakte sind geschlossen
|
152 | else
|
153 | {
|
154 | Reed_OK(); //Byte STA
|
155 | }
|
156 | }
|
157 |
|
158 | void Status_Senden() //Status der Anlage senden
|
159 | {
|
160 | uint8_t commando[6] = {"000000"}; //Array für Daten
|
161 |
|
162 | //Zusammenstellung der Daten
|
163 | commando[0] = 99; //Adresse 99
|
164 | commando[1] = 0b10000000; //Funktionen
|
165 | commando[2] = STA; //Status
|
166 | commando[3] = 255; //Wert 0
|
167 | commando[4] = 1; //Laufnummer
|
168 | commando[5] = 0b00010000; //Software-Version
|
169 |
|
170 | RFM_Empf_Aus();
|
171 | Daten_senden(commando, 6); //Daten senden
|
172 |
|
173 | Reed_OK(); //vorhandenen Alarm zurücksetzten falls vorhanden
|
174 | }
|
175 |
|
176 |
|
177 | int main(void) //Hauptprogramm
|
178 | {
|
179 | initPorts(); //AVR-Ports initialisieren
|
180 | //initUART(); //zu Testzwecken
|
181 | //UCSRB = (0<<RXEN)|(0<<RXCIE); //Receiver ausschalten
|
182 | //UCSRB = (1<<TXEN); //Transmitter zulassen
|
183 | initInterrupt(); //Interrups initialisieren
|
184 |
|
185 | Power_On(); //Powern On Prozedur von der LED
|
186 | _delay_ms(200); //Etwas Zeit verbummeln bis das Modul bereit ist
|
187 | initRFM_Ports(); //MOSI / MISO Ports initialisieren
|
188 | initRFM(); //RFM Grundkonfiguration
|
189 |
|
190 | while(true) //Hauptschleife
|
191 | {
|
192 | _delay_ms(3000); //TODO: durch Sleep ersetzten
|
193 |
|
194 | //Zustand der Anlage soll über INT1 gesetzt werden
|
195 | //Zustand_Anlage(); //Anlagenzustand abfragen
|
196 | Status_Senden(); //Status der Anlage senden
|
197 | Led_Rot_On();
|
198 | _delay_ms(50);
|
199 | Led_Rot_Off();
|
200 | //Sleep(); //Controller schlafen legen
|
201 | }
|
202 | }
|
203 |
|
204 | ISR(INT0_vect) //Interruptvektor für RFM12, wird bei jedem Byte aufgerufen
|
205 | {
|
206 | //wird beim Datenempfang benötigt
|
207 | }
|
208 |
|
209 | ISR(INT1_vect) //Interruptvektor für Reedkontakt, fallende Flanke
|
210 | {
|
211 | //Reed_Alarm();
|
212 | }
|
213 |
|
214 | ISR (TIMER2_COMP_vect) //Time-Compare-Interrupt, wird jede ms ausgelöst
|
215 | {
|
216 | //TODO
|
217 | }
|