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  | }
  |