1 | #define BAUDRATE 9600
|
2 | #define F_CPU 8000000
|
3 | #define MYADRESS 2
|
4 | #define SLAVETYPE Akustik
|
5 |
|
6 | #include <avr/io.h>
|
7 | #include <avr/interrupt.h>
|
8 | #include <util/delay.h>
|
9 | #include <stdlib.h>
|
10 |
|
11 |
|
12 | uint8_t inputbuf [10];
|
13 | uint8_t outputbuf [10];
|
14 | static uint8_t receivebytes, sendbytes=0;
|
15 | static uint8_t zeichen;
|
16 | static uint8_t protocollstart =0;
|
17 | static uint8_t msgend=0;
|
18 |
|
19 | void rs485_slave_init()
|
20 | {
|
21 | DDRC |= (1 << PC0); // PC0 als Output setzen
|
22 | PORTC &= ~(1 << PC0); // Max481 auf empfangen stellen
|
23 | _delay_us(500); // 500µs warten
|
24 |
|
25 | uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16UL*BAUDRATE) - 1);
|
26 |
|
27 | UBRRH = (uint8_t) (ubrr>>8);
|
28 | UBRRL = (uint8_t) (ubrr);
|
29 |
|
30 | // UART Receiver und Transmitter anschalten, Receive-Interrupt aktivieren
|
31 | // Data mode 8N1, asynchron
|
32 | UCSRA = 0;
|
33 | UCSRB = (1 << RXCIE)| (1 << RXEN) | (1 << TXEN);
|
34 | UCSRC = (1<<URSEL) | (1 << UCSZ1)| (1 << UCSZ0);
|
35 | }
|
36 |
|
37 | int rs485_slave_send(uint8_t outdata [3])
|
38 | {
|
39 | outputbuf[0]=0x02; //Startzeichen für Protokoll STX
|
40 | outputbuf[1]=MYADRESS; //Empfängeradresse in Array spreichern
|
41 | outputbuf[2]=0x42;
|
42 | outputbuf[3]=0;
|
43 | outputbuf[4]=0;
|
44 | outputbuf[5]=0;
|
45 |
|
46 | int x=0;
|
47 | for (int i=6;i <= 8;i++)
|
48 | {
|
49 | outputbuf[i]=outdata[x++]; //Datenarray in Outputbuf 3-5 schreiben
|
50 | }
|
51 | outputbuf[9]=0x03;
|
52 |
|
53 | PORTC |= (1 << PC0); // Max481 auf senden stellen
|
54 |
|
55 | cli();
|
56 | UCSRB &= ~(1 << RXEN);
|
57 | UCSRB |= (1 << UDRIE); //Interrupt zum Senden aktivieren
|
58 | sei();
|
59 |
|
60 |
|
61 | return 1;
|
62 | }
|
63 |
|
64 | int rs485_slave_read(uint8_t indata[], uint8_t size)
|
65 | {
|
66 | uint8_t n=0;
|
67 | if (inputbuf[0]== 0x02) //Start einer Nachricht feststellen
|
68 | {
|
69 | while (n <= 9)
|
70 | {
|
71 | indata[n]=inputbuf[n];
|
72 | n++;
|
73 | }
|
74 | return n;
|
75 | }
|
76 | else
|
77 | {
|
78 | return 0;
|
79 | }
|
80 |
|
81 |
|
82 | }
|
83 |
|
84 | void deleteInputbuf()
|
85 | {
|
86 | int i=0;
|
87 | while (i <= 11)
|
88 | {
|
89 | inputbuf[i++] = 0;
|
90 | }
|
91 | }
|
92 |
|
93 |
|
94 | int main(void)
|
95 | {
|
96 | DDRD |= (1 << PD6) | (1 << PD7); //PC0 als Ausgang für Signalisierung RX an Slave
|
97 | //DDRC &= ~(1 << PC1);
|
98 |
|
99 | uint8_t statusbyte[3];
|
100 | uint8_t inputdata [10];
|
101 |
|
102 | cli();
|
103 | //Initialisierung RS45
|
104 | rs485_slave_init();
|
105 | sei();
|
106 |
|
107 |
|
108 | while(1)
|
109 | {
|
110 |
|
111 |
|
112 | rs485_slave_read(inputdata, sizeof(inputdata));
|
113 |
|
114 | if(inputbuf[0] == 0x02 && msgend)
|
115 | {
|
116 | //Start und Ende von Frame erkannt, prüfen ob Nachricht für Teilnehmer ist
|
117 | if (inputbuf[1] == MYADRESS)
|
118 | {
|
119 | //Nachricht ist für diesen Teilnehmer
|
120 | //Auswerten der Steuerbytes
|
121 | PORTD |= (1 << PD7);
|
122 | if (inputbuf[3] & (1 << 2))
|
123 | {
|
124 | PORTD |= (1 << PD6);
|
125 | }
|
126 | else if (!(inputbuf[3] & (1 << 2)))
|
127 | {
|
128 | PORTD &= ~(1 << PD6);
|
129 |
|
130 | }
|
131 |
|
132 |
|
133 | statusbyte[0]= (1 << 0); //ACK Nachricht
|
134 | statusbyte[1]=0x58;
|
135 | statusbyte[2]=0x58;
|
136 |
|
137 | rs485_slave_send(statusbyte);
|
138 | deleteInputbuf();
|
139 | }
|
140 | else
|
141 | {
|
142 | PORTD &= ~(1 << PD7);
|
143 | }
|
144 |
|
145 | }
|
146 | }
|
147 |
|
148 | return 0;
|
149 | }
|
150 |
|
151 | ISR(USART_RXC_vect) //Interrupt-Routine, wird ausgelöst, wenn Zeichen empfangen wird
|
152 | {
|
153 | zeichen = UDR;
|
154 |
|
155 | if (zeichen == 0x02 && receivebytes==0)
|
156 | {
|
157 | protocollstart=1;
|
158 | }
|
159 |
|
160 |
|
161 | if (protocollstart)
|
162 | {
|
163 | inputbuf[receivebytes++]=zeichen;
|
164 | }
|
165 |
|
166 | if (receivebytes==10 && protocollstart)
|
167 | {
|
168 | //Ende der Nachricht erreicht
|
169 | //UCSRA |= (1 << RXC);
|
170 | UCSRB &= ~(1 << RXCIE);
|
171 | msgend=1;
|
172 | receivebytes=0;
|
173 | protocollstart=0;
|
174 | }
|
175 | }
|
176 |
|
177 | ISR(USART_UDRE_vect)
|
178 | {
|
179 | if (sendbytes==1)
|
180 | {
|
181 | UCSRB |= (1 << TXCIE); //Transmit Complete Interrupt aktivieren
|
182 | }
|
183 |
|
184 | if (sendbytes == 10)
|
185 | {
|
186 | UCSRB &= ~(1 << UDRIE); //Interrupt zum Senden deaktivieren
|
187 | UCSRA |= (1 << TXC);
|
188 | sendbytes =0;
|
189 | }
|
190 | else
|
191 | {
|
192 | //while (!(UCSRA & (1<<UDRE))) // warten bis Senden moeglich ist
|
193 | //{
|
194 | //}
|
195 | UDR = outputbuf[sendbytes++]; //Zeichen senden aus Outputbuf
|
196 | }
|
197 | }
|
198 |
|
199 |
|
200 | //Transmit Complete Interrupt Routine
|
201 | ISR(USART_TXC_vect)
|
202 | {
|
203 | // Transmit is complete: terminate
|
204 | PORTC &= ~(1 << PC0); //MAX485 auf Receive stellen
|
205 | UCSRB &= ~(1 << TXEN);
|
206 | UCSRB |= (1 << RXEN) | (1 << RXCIE); //Receive Interrupt einschalten
|
207 | UCSRB &= ~(1 << TXCIE); //Transmit Complete Interrupt deaktivieren
|
208 | }
|