1 | /*
|
2 | * Rs485Dev.c
|
3 | *
|
4 | * Created: 11.11.2016 06:22:25
|
5 | * Author: Admin
|
6 | */
|
7 |
|
8 | #ifndef F_CPU
|
9 | #define F_CPU 16000000UL
|
10 | #endif
|
11 |
|
12 | #include <avr/io.h>
|
13 | #include <avr/interrupt.h>
|
14 | #include <util/delay.h>
|
15 | #include <stdio.h>
|
16 | #include <stdbool.h>
|
17 | #include <stdlib.h>
|
18 | #include <string.h>
|
19 |
|
20 |
|
21 | #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) \
|
22 | ( ( F_OSC ) / ( ( UART_BAUD_RATE ) * 8UL ) - 1 )
|
23 |
|
24 | #define NOP asm volatile ("nop" ::)
|
25 |
|
26 | #define NET_UCSRA UCSR0A
|
27 | #define NET_UCSRB UCSR0B
|
28 | #define NET_UCSRC UCSR0C
|
29 | #define NET_UDR UDR0
|
30 | #define CRC_BIT 0x10
|
31 | #define INCLUDE_CRC(x) (((x) & (CRC_BIT)) !=0) ? (2):(0)
|
32 |
|
33 | #define MAX_DATA_LENGTH 10
|
34 | #define CRC16_POLYNOM 0x1002
|
35 |
|
36 | typedef struct {
|
37 | unsigned char RxAddress;
|
38 | unsigned char InfoByte;
|
39 | unsigned char TxAddress;
|
40 | unsigned char DataLength;
|
41 | unsigned char Data[MAX_DATA_LENGTH];
|
42 | } st_protokoll_Data;
|
43 |
|
44 |
|
45 | typedef void ( *fptrNetTask)(st_protokoll_Data*);
|
46 |
|
47 | typedef struct{
|
48 | unsigned char MyAdr;
|
49 | bool MasterMode;
|
50 | unsigned int speed;
|
51 | fptrNetTask fptrCallBackOnOk;
|
52 | }st_Dev_Config;
|
53 |
|
54 |
|
55 |
|
56 | volatile bool DataOk;
|
57 |
|
58 | /* neu **********************/
|
59 | bool LCD_Update;
|
60 | unsigned char LCD_buf[20];
|
61 | st_Dev_Config *Dev_Config;
|
62 |
|
63 | st_protokoll_Data stRxData;
|
64 | st_protokoll_Data stTxData;
|
65 |
|
66 | unsigned char RxHeader;
|
67 | unsigned char RxBody;
|
68 | unsigned int RxCrc16;
|
69 | unsigned int crc16;
|
70 | unsigned char *NetTxPtr;
|
71 | unsigned char NetTxCount;
|
72 | unsigned char NetTxCount_temp;
|
73 |
|
74 | void NetSetTxEnable(bool enable) {
|
75 | if (enable) {
|
76 | PORTB |= (1 << PINB2);
|
77 | }
|
78 | else {
|
79 | PORTB &= ~(1 << PINB2);
|
80 | }
|
81 | }
|
82 |
|
83 | void NetInit(st_Dev_Config *config) {
|
84 | char c;
|
85 | Dev_Config = config;
|
86 | UBRR0H = (unsigned char)(UART_BAUD_CALC(Dev_Config->speed, F_CPU) >> 8);
|
87 | UBRR0L = (unsigned char)UART_BAUD_CALC(Dev_Config->speed, F_CPU);
|
88 |
|
89 | NET_UCSRA = (1 << U2X0) | (1 << MPCM0);
|
90 | NET_UCSRB = (1 << UCSZ02) | (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0) | (1 << TXCIE0);
|
91 | NET_UCSRC = (1 << UCSZ01) | (1 << UCSZ00);
|
92 | NetSetTxEnable(false);
|
93 | c = NET_UDR; // Rx Buffer leeren und verwerfen
|
94 | }
|
95 |
|
96 | void InitCRC(void) {
|
97 | crc16 = 0xffff;
|
98 | }
|
99 |
|
100 | void CalcCRC(unsigned char data) {
|
101 | unsigned char bitCount;
|
102 | unsigned char PolynomFlag;
|
103 | for (bitCount = 0; bitCount < 8; bitCount++) {
|
104 | PolynomFlag = (crc16 & 0x8000) != 0;
|
105 | crc16 <<= 1;
|
106 | if (data & 0x80) {
|
107 | crc16 |= 1;
|
108 | }
|
109 | data <<= 1;
|
110 | if (PolynomFlag)
|
111 | crc16 ^= CRC16_POLYNOM;
|
112 | }
|
113 | }
|
114 |
|
115 | void Net_NewFrameStart(void) {
|
116 | RxHeader = 0x00;
|
117 | RxBody = 0x00;
|
118 | RxCrc16 = 0;
|
119 | InitCRC();
|
120 | stRxData.TxAddress = NULL;
|
121 |
|
122 | }
|
123 |
|
124 | void Net_SendFrame(void)
|
125 | {
|
126 | int i, loop;
|
127 | i = 0;
|
128 | InitCRC();
|
129 | CalcCRC(stTxData.RxAddress);
|
130 | i++;
|
131 | CalcCRC(stTxData.InfoByte);
|
132 | i++;
|
133 | CalcCRC(stTxData.TxAddress);
|
134 | i++;
|
135 | CalcCRC((stTxData.DataLength += (INCLUDE_CRC(stTxData.InfoByte))));
|
136 | i++;
|
137 | for (loop = 0; loop < (stTxData.DataLength - (INCLUDE_CRC(stTxData.InfoByte))); loop++) // Framedaten
|
138 | {
|
139 | CalcCRC(stTxData.Data[loop]);
|
140 | i++;
|
141 | }
|
142 | CalcCRC(0);
|
143 | CalcCRC(0);
|
144 | stTxData.Data[loop++] = (crc16>>8)&0xff;
|
145 | stTxData.Data[loop] = (crc16)&0xff;
|
146 | NetTxCount = i+(INCLUDE_CRC(stTxData.InfoByte));
|
147 | NetTxCount_temp = NetTxCount;
|
148 | NetTxPtr = &stTxData.RxAddress;
|
149 | NetSetTxEnable(true);
|
150 | if(Dev_Config->MasterMode)NET_UCSRB |= (1<< TXB80); // nur beim Master
|
151 | NET_UCSRB |= (1<<UDRIE0); // Tx Empty einschalten
|
152 |
|
153 | }
|
154 |
|
155 | void Net_SendChar(unsigned char ptr_RXAddress,unsigned char *val,
|
156 | unsigned int len)
|
157 | {
|
158 | int loop;
|
159 | stTxData.RxAddress = ptr_RXAddress;
|
160 | stTxData.TxAddress = Dev_Config->MyAdr;
|
161 | stTxData.InfoByte = CRC_BIT;
|
162 | stTxData.DataLength = len;
|
163 | for(loop = 0; loop < len; loop++){
|
164 | stTxData.Data[loop] = *val++;
|
165 | }
|
166 | Net_SendFrame();
|
167 | }
|
168 |
|
169 | ISR(USART_UDRE_vect) // Tx Buffer ist leer und braucht nachschub
|
170 | {
|
171 |
|
172 | if (NetTxCount)
|
173 | {
|
174 | if(NetTxCount != NetTxCount_temp)NET_UCSRB &= ~(1<< TXB80);
|
175 | NET_UDR = *NetTxPtr;
|
176 | NetTxPtr++;
|
177 | NetTxCount--;
|
178 |
|
179 | }
|
180 | else
|
181 | NET_UCSRB &= ~(1<<UDRIE0); // Tx Empty abschalten
|
182 | }
|
183 |
|
184 |
|
185 | ISR(USART_TX_vect) // Leztes Byte wurde gesendet
|
186 | {
|
187 | NetSetTxEnable(false);
|
188 | NOP;
|
189 | NOP;
|
190 |
|
191 | }
|
192 |
|
193 | ISR(USART_RX_vect) {
|
194 | unsigned char ucRxByte;
|
195 |
|
196 | if (NET_UCSRA & ((1 << FE0) + (1 << DOR0))) // Fehler
|
197 | {
|
198 | ucRxByte = NET_UDR; // Rx Buffer leeren
|
199 | NET_UCSRA |= (1 << MPCM0); // MPCM Mode einschalten
|
200 | DataOk = false;
|
201 | return;
|
202 | }
|
203 |
|
204 | if ((NET_UCSRB & (1 << RXB80)) ) // OK mit 9. bit
|
205 | {
|
206 |
|
207 | ucRxByte = NET_UDR;
|
208 | if (ucRxByte == Dev_Config->MyAdr) {
|
209 | NET_UCSRA &= ~(1 << MPCM0); // MPCM Mode ausschalten
|
210 | stRxData.RxAddress = ucRxByte;
|
211 | Net_NewFrameStart();
|
212 | CalcCRC(ucRxByte);
|
213 | RxHeader++;
|
214 | return;
|
215 | }
|
216 | else // Packet ist nicht für mich gedacht.
|
217 | {
|
218 | NET_UCSRA |= (1 << MPCM0);
|
219 | return;
|
220 | }
|
221 |
|
222 | }
|
223 | // ab hier geht es weiter mit 8 bit
|
224 | ucRxByte = NET_UDR;
|
225 |
|
226 | if (RxHeader == 1) // Info BYTE
|
227 | {
|
228 | stRxData.InfoByte = ucRxByte;
|
229 | RxHeader++;
|
230 | CalcCRC(ucRxByte);
|
231 | return;
|
232 | }
|
233 | if (RxHeader == 2) // Sender ADR
|
234 | {
|
235 | stRxData.TxAddress = ucRxByte;
|
236 | RxHeader++;
|
237 | CalcCRC(ucRxByte);
|
238 | return;
|
239 | }
|
240 | if (RxHeader != 0xFF) // DATA Länge
|
241 | {
|
242 |
|
243 | RxHeader = 0xFF;
|
244 | stRxData.DataLength = ucRxByte;
|
245 | CalcCRC(ucRxByte);
|
246 | return;
|
247 | }
|
248 |
|
249 | if (RxBody < (stRxData.DataLength - (INCLUDE_CRC(stRxData.InfoByte)))) // DATA
|
250 | {
|
251 |
|
252 | stRxData.Data[RxBody] = ucRxByte;
|
253 | CalcCRC(ucRxByte);
|
254 | RxBody += 1;
|
255 | if (!INCLUDE_CRC(stRxData.InfoByte) &&
|
256 | (RxBody == stRxData.DataLength)) // Keine CRC nötig
|
257 | {
|
258 | NET_UCSRA |= (1 << MPCM0);
|
259 | Dev_Config->fptrCallBackOnOk(&stRxData);
|
260 | }
|
261 | return;
|
262 | }
|
263 | if (RxBody == (stRxData.DataLength - 2)) // CRC16 High
|
264 | {
|
265 | RxCrc16 = ucRxByte << 8;
|
266 | //stRxData.Data[RxBody] = ucRxByte;
|
267 | RxBody++;
|
268 | return;
|
269 | }
|
270 | if (RxBody == (stRxData.DataLength - 1)) // CRC16 Low
|
271 | {
|
272 |
|
273 | RxCrc16 |= ucRxByte;
|
274 | //stRxData.Data[RxBody] = ucRxByte;
|
275 | CalcCRC(0);
|
276 | CalcCRC(0);
|
277 | RxBody = RxHeader = 0;
|
278 | if (crc16 != RxCrc16) // fehler CRC
|
279 | {
|
280 | NET_UCSRA |= (1 << MPCM0);
|
281 | return;
|
282 | }
|
283 | else // alles OK
|
284 | {
|
285 | NET_UCSRA |= (1 << MPCM0);
|
286 | Dev_Config->fptrCallBackOnOk(&stRxData);
|
287 | return;
|
288 | }
|
289 | }
|
290 |
|
291 | if (RxBody==MAX_DATA_LENGTH)
|
292 | {
|
293 | NET_UCSRA |= (1 << MPCM0);
|
294 | return;
|
295 | }
|
296 |
|
297 | }
|
298 |
|
299 | #define SET_LED 0x01
|
300 | #define GET_INPUT 0x02
|
301 | #define RESET 0x03
|
302 | #define SET_PWM 0x04
|
303 | #define GET_ADC 0x05
|
304 | #define START_BOOTLOADER 0x06
|
305 | #define WRITE_LCD_BUFFER 0x07
|
306 | #define SET_NET_ADR 0x08
|
307 | /* usw */
|
308 |
|
309 | void NetAktion(st_protokoll_Data* RxFrame)
|
310 | {
|
311 | NOP;
|
312 | switch(RxFrame->Data[0])
|
313 | {
|
314 | case SET_LED:
|
315 | PORTC |= (1 <<RxFrame->Data[1]);
|
316 | break;
|
317 | case WRITE_LCD_BUFFER:
|
318 | memcpy (LCD_buf,&RxFrame->Data[1],(RxFrame->DataLength - (INCLUDE_CRC(RxFrame->InfoByte))));
|
319 | LCD_buf[(RxFrame->DataLength - (INCLUDE_CRC(RxFrame->InfoByte)))+1] = 0x00;
|
320 | LCD_Update = true;
|
321 | break;
|
322 | default:
|
323 | // Info an Master NO SERVICE AVAILABLE
|
324 | break;
|
325 |
|
326 | }
|
327 | }
|
328 |
|
329 | // Slave Main
|
330 | int main(void) {
|
331 | unsigned char buf[20];
|
332 | DDRB = (1 << PINB5) | (1 << PINB2); // set PINB0 and PINB2 as output
|
333 | DDRC =0xff;
|
334 | st_Dev_Config my_Dev_config;
|
335 |
|
336 | my_Dev_config.fptrCallBackOnOk = NetAktion;
|
337 | my_Dev_config.MasterMode = false;
|
338 | my_Dev_config.MyAdr = 0x44; // oder aus EEProm auslesen
|
339 | my_Dev_config.speed = 9600;
|
340 |
|
341 | NetInit(&my_Dev_config);
|
342 | _delay_ms(200);
|
343 | sei();
|
344 |
|
345 | while (1) {
|
346 |
|
347 | if(LCD_Update)
|
348 | {
|
349 | //lcd_string(&LCD_buf); // da ich deine LCD Lib nicht habe ist das ausgeklammert.
|
350 | LCD_Update = false;
|
351 | }
|
352 |
|
353 |
|
354 |
|
355 | } // while
|
356 |
|
357 | } // main
|
358 |
|
359 | // Master Main
|
360 | /*
|
361 | int main(void) {
|
362 | unsigned char buf[20];
|
363 | DDRB = (1 << PINB5) | (1 << PINB2); // set PINB0 and PINB2 as output
|
364 | DDRC =0xff;
|
365 | st_Dev_Config my_Dev_config;
|
366 |
|
367 | my_Dev_config.fptrCallBackOnOk = NetAktion;
|
368 | my_Dev_config.MasterMode = true;
|
369 | my_Dev_config.MyAdr = 0x01; // oder aus EEProm auslesen
|
370 | my_Dev_config.speed = 9600;
|
371 |
|
372 | NetInit(&my_Dev_config);
|
373 | _delay_ms(200);
|
374 | sei();
|
375 |
|
376 | while (1) {
|
377 |
|
378 | _delay_ms(1000);
|
379 | buf[0] = WRITE_LCD_BUFFER;
|
380 | sprintf(&buf[1],"LED");
|
381 | Net_SendChar( 0x44,&buf[0],4);
|
382 |
|
383 |
|
384 |
|
385 | } // while
|
386 |
|
387 | } // main
|
388 | */
|