1 | // -------------------------------------------------------------
|
2 | /// \file main.c
|
3 |
|
4 | #include <avr/io.h>
|
5 | #include "Communication.h"
|
6 | #include "SlaveConfig.h"
|
7 | #include <util/delay.h>
|
8 | #include <avr/interrupt.h>
|
9 | #include "SlaveFunctions.h"
|
10 | #include <stdio.h>
|
11 |
|
12 | uint16_t received_char = 0;
|
13 | uint8_t bit_cnt_receiver = 0;
|
14 | uint8_t address_ok = 0;
|
15 | uint8_t command = 0;
|
16 | uint8_t frame_type = 0; //Flag: 0 = DatenFrame, 1 = Adressframe
|
17 | uint8_t device_addressed = 0;
|
18 | uint16_t ad_value = 0;
|
19 | uint8_t ad_pin_check = 0; //Flag: 0 = falscher PIN eingestellt, 1 = richtiger PIN eingestellt
|
20 |
|
21 | #define LED PORTB |= (1<<PINB2);
|
22 |
|
23 | //--------------------------------------------------------------
|
24 | /// Worker Routine of the Slave
|
25 | ///
|
26 | ///
|
27 | int main(void)
|
28 | {
|
29 | DDRB |= (1<<PINB2);
|
30 |
|
31 | initHardware(); //initialize Hardware Configuration
|
32 | sei(); //Global Interrupts enabled
|
33 | while (1)
|
34 | {
|
35 |
|
36 |
|
37 | checkIfAddress(); //Es wird kontrolliert, ob der Frame ein AdressFrame ist
|
38 |
|
39 | if(device_addressed) //Es wird kontrolliert, ob meine Adresse gemeint ist
|
40 | {
|
41 | processCommand(); //Kommandos werden ausgeführt
|
42 | }
|
43 |
|
44 | }
|
45 |
|
46 | return 0;
|
47 | }
|
48 |
|
49 | //--------------------------------------------------------------
|
50 | /// Address recognition routine for 9 bit data UART address frame
|
51 | ///
|
52 | ///
|
53 | void checkIfAddress(void)
|
54 | {
|
55 |
|
56 | frame_type = ((received_char & 0b0000000100000000) >> 8); //wenn 9tes bit (msb) = 1, dann handelt es sich um einen Address-Frame
|
57 |
|
58 | if(frame_type == ADDRESS_FRAME)
|
59 | {
|
60 | LED
|
61 | if((received_char & 0x00FF) == MY_SLAVE_ADDRESS)
|
62 | {
|
63 | device_addressed = 1;
|
64 |
|
65 | }
|
66 |
|
67 | if((received_char & 0x00FF) != MY_SLAVE_ADDRESS)
|
68 | {
|
69 | device_addressed = 0;
|
70 | }
|
71 |
|
72 | }
|
73 |
|
74 | }
|
75 |
|
76 | //--------------------------------------------------------------
|
77 | /// Command execution routine
|
78 | ///
|
79 | ///
|
80 | void processCommand(void)
|
81 | {
|
82 |
|
83 | command = (uint8_t)received_char;
|
84 |
|
85 | switch(command)
|
86 | {
|
87 | case GET_VOLTAGE:
|
88 | {
|
89 | getVoltage();
|
90 | }
|
91 | break;
|
92 |
|
93 | case GET_TEMPERATURE:
|
94 | {
|
95 | getTemperature();
|
96 | }
|
97 | break;
|
98 | }
|
99 |
|
100 | command = 0;
|
101 | }
|
102 |
|
103 | //--------------------------------------------------------------
|
104 | /// Hardware initialization routine for software UART
|
105 | ///
|
106 | ///
|
107 | void initHardware(void)
|
108 | {
|
109 | DDRB |= (1<<PIN_UART_TX); //PIN PIN_UART_TX = Output
|
110 | PORTB |= (1<<PIN_UART_TX); //IDLE-STATE = HIGH
|
111 |
|
112 | DDRB &= ~(1<<PIN_UART_RX); //PIN PIN_UART_RX = Input
|
113 |
|
114 | GIMSK |= (1<<PCIE); //PinChangeInterrupt für PIN_UART_RX ist aktiv
|
115 | PCMSK |= (1<<PIN_UART_RX); //Pin Change enabled
|
116 |
|
117 | ADCSRA |= (1<<ADEN); //AD Enable
|
118 | ADCSRA |= (1<<ADIE); //AD Interrupt Enable
|
119 |
|
120 | //Check, ob einer oder beide der AD_PINS auf einen Eingang gelegt wurden, der kein AD ist.
|
121 | if (!((PIN_AD_VOLT >= PB2 && PIN_AD_VOLT <= PB5) || ((PIN_AD_TEMP >= PB2 && PIN_AD_TEMP <= PB5))))
|
122 | {
|
123 | ad_pin_check = 0; //Wrong ad pin
|
124 | }
|
125 | }
|
126 |
|
127 | //--------------------------------------------------------------
|
128 | /// Software UART send routine for 8 bit data UART data frame
|
129 | ///
|
130 | ///
|
131 | void sendChar(uint8_t chr) //Character senden
|
132 | {
|
133 | cli();
|
134 | uint8_t bit_cnt; //bit counter -> um die einzelnen bits zu vergleichen
|
135 |
|
136 | PORTB &= ~(1<<PIN_UART_TX); //Start-Bit
|
137 | _delay_us(ONE_BIT); //Warten von 104 µS
|
138 |
|
139 | for(bit_cnt = 0; bit_cnt < 8; bit_cnt++) //Für die Länge eines 8 bit Frames
|
140 | {
|
141 | //Wenn aktuelles bit = 1 ist
|
142 | if(chr & (1 << bit_cnt))
|
143 | {
|
144 | PORTB |= (1<<PIN_UART_TX); //PIN_UART_TX = HIGH
|
145 | }
|
146 |
|
147 | //Wenn aktuelles bit = 0 ist
|
148 | else
|
149 | {
|
150 | PORTB &= ~(1<<PIN_UART_TX); //PIN_UART_TX = LOW
|
151 | }
|
152 |
|
153 | _delay_us(ONE_BIT); //Warten von 104 µS
|
154 | }
|
155 |
|
156 | PORTB |= (1<<PIN_UART_TX); //Stop-Bit
|
157 | _delay_us(ONE_BIT); //Warten von 104 µS
|
158 | sei();
|
159 | }
|
160 |
|
161 | void getTemperature(void)
|
162 | {
|
163 | setADChannel(PIN_AD_TEMP);
|
164 | startADConversion();
|
165 | sendADValueToMaster();
|
166 | }
|
167 |
|
168 | void getVoltage(void)
|
169 | {
|
170 | setADChannel(PIN_AD_VOLT);
|
171 | startADConversion();
|
172 | sendADValueToMaster();
|
173 | }
|
174 |
|
175 |
|
176 | void setADChannel(uint8_t ad_pin)
|
177 | {
|
178 |
|
179 | if(ad_pin_check) //Flag, das nur beim initialisieren gesetzt wird
|
180 | {
|
181 | ADMUX &= ~((1<<MUX1)|(1<<MUX0)); //Clear the AD/PIN selection
|
182 |
|
183 | switch(ad_pin)
|
184 | {
|
185 | case PINB2:
|
186 | ADMUX |= (1<<MUX0); //ADC1
|
187 | break;
|
188 |
|
189 | case PINB3:
|
190 | ADMUX |= (1<<MUX1) | (1<<MUX0); //ADC3
|
191 | break;
|
192 |
|
193 | case PINB4:
|
194 | ADMUX |= (1<<MUX1); //ADC2
|
195 | break;
|
196 |
|
197 | case PINB5:
|
198 | //ADC0
|
199 | break;
|
200 | }
|
201 | }
|
202 | }
|
203 |
|
204 |
|
205 | void startADConversion(void)
|
206 | {
|
207 | ADCSRA |= (1<<ADSC); //AD/Wandlung im Single Conversion Mode starten
|
208 | while((ADCSRA & (1 << ADIF)) != 1); //Hänge, solange Wert nicht gelesen wurde...
|
209 | }
|
210 |
|
211 |
|
212 | void sendADValueToMaster(void)
|
213 | {
|
214 | sendChar(ad_value >> 8); //Oberen 2 Bits werden gesendet (Rest wird mit 0 aufgefüllt)
|
215 | _delay_us(10); //Sicherheitshalber, um negative timing-fehler wieder auszugleichen
|
216 | sendChar(ad_value); //Unteren 8 bits werden gesendet
|
217 | }
|
218 |
|
219 | //--------------------------------------------------------------
|
220 | /// Interrupt routine for completed Analog to Digital conversion (10 bit)
|
221 | ///
|
222 | ///
|
223 | ISR(ADC_vect)
|
224 | {
|
225 | ad_value = ADC;
|
226 | }
|
227 |
|
228 | //--------------------------------------------------------------
|
229 | /// Interrupt routine for PIN-Change for receiving 11 bits (Software-Uart-Receiving) (-> Command + Adress)
|
230 | ///
|
231 | ///
|
232 | ISR(PCINT0_vect)
|
233 | {
|
234 | received_char = 0;
|
235 | cli();
|
236 |
|
237 | for(bit_cnt_receiver = 0; bit_cnt_receiver < 11; bit_cnt_receiver++) //von 0 bis 10 = 1 Frame
|
238 | {
|
239 | if (bit_cnt_receiver == 0) //Startbit wird empfangen (+5V)
|
240 | {
|
241 | _delay_us(HALF_BIT);
|
242 | }
|
243 |
|
244 | if(bit_cnt_receiver > 0 && bit_cnt_receiver < 10)
|
245 | {
|
246 |
|
247 | if(PINB & (1<<PIN_UART_RX)) //Wenn PinB0 einen High-Pegel empfängt
|
248 | {
|
249 | received_char |= (1 << (bit_cnt_receiver - 1)); //LSB wird zuerst empfangen (-1, um vorhergehendes "startbit" zu eliminieren)
|
250 | }
|
251 |
|
252 | else if (PINB & ~(1<<PIN_UART_RX)) //Wenn PinB0 einen Low-Pegel empfängt
|
253 | {
|
254 | received_char &= ~(1 << (bit_cnt_receiver - 1)); //LSB wird zuerst empfangen (-1, um vorhergehendes "startbit" zu eliminieren)
|
255 | }
|
256 | }
|
257 |
|
258 | if (bit_cnt_receiver > 9) //Stopbit wird empfangen (0V)
|
259 | {
|
260 | bit_cnt_receiver = 0;
|
261 | _delay_us(HALF_BIT); //Halbes Bit wird abgewartet, damit Frame pünktlich beendet wird
|
262 | sei();
|
263 | return;
|
264 | }
|
265 |
|
266 | _delay_us(ONE_BIT);
|
267 | }
|
268 |
|
269 | }
|
270 |
|
271 |
|
272 |
|
273 | /// @} //end group slave
|