Rs485Dev.c


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
*/