Zeitsteuerung

Fork of timer0 by V09

Revision:
1:8779e76fd4ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rs_485.cpp	Fri Feb 05 14:39:43 2016 +0000
@@ -0,0 +1,394 @@
+//---------------------------------------------------------------------------
+// Modul...: RS_485.CPP    
+// Chip....: iox.mini
+// 
+//---------------------------------------------------------------------------
+// Author..: Reinhold Schäfer
+// Date....: 2016.01.23
+// http....: //www.microsps.net
+//---------------------------------------------------------------------------
+#include "mbed.h"
+#include "rs_485.h"
+#include "timer0.h"
+
+MODSERIAL RS485(RS485_TX2, RS485_RX2);  // tx, rx
+DigitalOut RS485_DIR(RS485_DIR2,0);     // RS485 Direction 
+
+extern MODSERIAL pc;
+extern timer0 down_timer;               // definiert in main
+
+//--------------------------------------------------------
+// Interruptroutine wird nach 300µs aufgerufen, da das Senden von
+// einem Zeichen ca. 100µs Zeit beansprucht, kann die Umschaltung
+// auf Empfang erst verzögert erfolgen.
+
+void rs_485::isr_timeout(void)
+{
+  RS485_DIR = 0; // auf Empfang umschalten
+  send_end_flag = true;  
+}
+
+/*
+// -----------------------------------------------------------------------
+// This function is called when TX buffer goes empty
+//
+void rs_485::txEmpty(MODSERIAL_IRQ_INFO *q) 
+{
+    timeout.attach_us(this, &rs_485::isr_timeout, 300);    // Zeit für das Umschalten
+}
+*/
+//--------------------------------------------------------
+// Construktor initialisiert den Timer
+rs_485::rs_485()
+{
+    RS485.baud(115200);
+    //RS485.attach(this, &rs_485::txEmpty);
+    timeout.stop();
+    timeout.reset();
+    msg_in.sm = 0;
+    msg_out.sm = 0;
+    rs_aktiv = 0;
+    rs_aktiv_old = 0;    
+}
+//-------------------------------------------------------------
+// Checksum ermitteln
+
+uint8_t rs_485::get_crc(uint8_t *pbuffer, uint8_t count)
+{
+    uint8_t crc_value = 0;
+    uint8_t temp;
+    
+    // CheckSum calculation
+    for(int i=0; i <= count; i++)
+    {
+       temp = *pbuffer;
+       // pc.printf("\n CRC #%02d  %02x ^ %02x = ",i,crc_value,temp);
+       crc_value ^= temp;    // XOR from ID to Data
+       pbuffer++;
+       // pc.printf("%02x",crc_value);
+    }
+    return crc_value;
+} 
+
+//-------------------------------------------------------------
+// zum Testen das Telegramm ausgeben
+//
+void rs_485::msg_print(Message msg) 
+{
+    uint8_t len;
+    
+    pc.printf(" %02d:%02d:%02d.%03d",msg.h,msg.m,msg.s,msg.ms);
+ 
+    pc.printf(" %02x",msg.STX);
+    pc.printf(" %02x",msg.source);
+    pc.printf(" %02x",msg.dest);
+    pc.printf(" %02x [",msg.len);
+    
+    len = msg.len;
+    for (int i = 0; i < len; i++)
+    {
+      pc.printf(" %02x",msg.data[i]);   
+    }
+    pc.printf(" ] %02x",msg.CRC);
+    pc.printf(" %02x",msg.ETX);
+       
+}
+
+// -----------------------------------------------------------------------
+// eine Telegramm erzeugen
+//
+// die Zeichen STX, CRC und ETX werden automatisch erzeugt
+// das Telegramm hat folgenden Aufbau
+// STX ADR ZIEL Länge [daten] CRC ETX
+//   Länge ist Anzahl der Zeichen im Datenfeld
+//
+void rs_485::write(uint8_t *data)
+{  
+   uint16_t millis;
+   uint8_t len;
+   
+   msg_out.STX  = 0x02;      // STX
+ 
+   msg_out.source = *data;   // Start Adresse
+   data++; 
+      
+   msg_out.dest = *data;     // Ziel Adresse
+   data++;
+  
+   msg_out.len = *data;      // Länge
+   len = *data;
+   data++;
+           
+   for (int i = 0; i < len; i++)
+   {
+        msg_out.data[i]  = *data; // Datenbyte
+        data++;
+   }
+
+   // pc.printf("\n write crc berechnen \n");
+   msg_out.CRC = get_crc(&msg_out.source,msg_out.len+3); // CRC Summe ermitteln
+      
+   msg_out.ETX      = 0x03;    // Telegramm Abschluss
+   
+   // Zeitstempel schreiben
+   down_timer.get_time_stamp(t_array,&millis);
+   msg_out.h = t_array[0];
+   msg_out.m = t_array[1];
+   msg_out.s = t_array[2];
+   msg_out.ms = millis;
+   
+   // Datenausgabe wird aktiviert, prüfen ob harte Umschaltung hier sinnvoll 
+   msg_out.sm = 0;
+   rs_aktiv = 2; 
+}
+    
+//-------------------------------------------------------------
+// Die Telegramme steuern und überwachen
+//
+void rs_485::execute(void)
+{
+    // auf timeout testen, falls ein fehler auftritt
+    // wird das Telegramm über diese Stelle abgebrochen
+    // 
+    
+    int temp;
+    
+    temp = timeout.read_ms();
+    if (temp >= 10)
+    {
+        timeout.stop();
+        timeout.reset();
+        msg_in.sm = 0;
+        msg_out.sm = 0;
+
+      
+        if (rs_aktiv == 1) 
+        {
+            pc.printf("\nreceive timeout %02d ms",temp);
+            pc.printf("\n sm: %02x",msg_in.sm);
+            pc.printf("\n tel:");
+            msg_print(msg_out);
+        }
+      
+        if (rs_aktiv == 2) 
+        {
+            pc.printf("\nsende timeout %02d ms",temp);
+            pc.printf("\n sm: %02x",msg_out.sm);
+            pc.printf("\n tel:");
+            msg_print(msg_out); 
+        }
+      
+        rs_aktiv = 0; 
+    }  
+ 
+    // an dieser Stelle wird der Programmablauf gesteuert
+    // 0 Bus inaktiv auf Empfang
+    // 1 BUS aktiv auf Empfangsmode
+    // 2 BUS aktiv im Sendemode 
+    
+    switch (rs_aktiv)
+    {
+      case 0:
+      
+        if (rs_aktiv != rs_aktiv_old)
+        {
+            pc.printf("\n\nreceive");  
+            timeout.stop(); // timer starten
+            timeout.reset(); // timer auf 0 setzen
+            rs_aktiv_old = rs_aktiv;
+        }
+        receive();
+        break;
+
+      case 1:
+        
+        if (rs_aktiv != rs_aktiv_old)
+        { 
+            pc.printf("\n\nreceive aktiv");
+            timeout.reset(); // timer auf 0 setzen
+            timeout.start();
+            rs_aktiv_old = rs_aktiv; 
+        }    
+        receive();
+        break;
+                
+      case 2:
+      
+        if (rs_aktiv != rs_aktiv_old)
+        {
+            pc.printf("\n\nsende aktiv");
+            timeout.reset(); // timer auf 0 setzen
+            timeout.start();
+            rs_aktiv_old = rs_aktiv; 
+        }
+        send();
+        break;      
+    }  // end switch
+        
+}
+
+// -----------------------------------------------------------------------
+// das Telegramm ausgeben
+//
+void rs_485::send(void)
+{
+   
+   switch(msg_out.sm)
+   {
+      case 0: 
+        // das Senden beginnt erst, wenn das eingehende Telegramm abgeschlossen ist
+
+        msg_print(msg_out);
+        pc.printf(" \n");
+        
+        RS485_DIR = 1;              // Bus belegen   
+        msg_out.sm = 1;
+
+        break;
+        
+      case 1:                       // Startzeichen senden 
+        RS485.putc(msg_out.STX);
+        msg_out.sm++;
+        break;
+      
+      case 2: 
+        RS485.putc(msg_out.source);
+        msg_out.sm++;
+        break;
+
+      case 3: 
+        RS485.putc(msg_out.dest);
+        msg_out.sm++;
+        break;
+        
+      case 4: 
+        RS485.putc(msg_out.len); 
+        msg_out.sm++;
+        break;
+        
+      case 5: 
+        for(int i=0; i < msg_out.len; i++)
+        {
+            RS485.putc(msg_out.data[i]);          
+        }
+        msg_out.sm++;
+        break;
+        
+      case 6: 
+        RS485.putc(msg_out.CRC);
+        msg_out.sm++;
+        break;
+         
+      case 7: 
+        RS485.putc(msg_out.ETX);
+        msg_out.sm++;
+        break;
+        
+      case 8: 
+        // hier warten bis alle Zeichen ausgegeben
+        int n = RS485.txBufferGetCount();
+        if (n == 0) msg_out.sm = 0;
+        //tx_timeout1 = timeout.read_us();
+        break; 
+
+      case 9: 
+        // hier warten bis alle Zeichen ausgegeben
+
+        //tx_timeout2 = timeout.read_us();
+        //if ((tx_timeout2 - tx_timeout1) >= 100) 
+        //{
+            msg_out.sm = 0;
+            RS485_DIR = 0;      // Bus frei geben
+            rs_aktiv = 0;       // Bus wieder auf Empfang
+        //} 
+        break;
+       
+      default:  // wird nie erreicht
+        pc.printf(" error in sm send %d",msg_out.sm);
+        break;                                                             // 
+    } // end switch                                
+}
+
+// -----------------------------------------------------------------------
+// ein Telegramm lesen
+//
+void rs_485::receive(void)
+{
+    uint8_t ch, pos;
+ 
+    if (RS485.readable())  // prüfen ob Zeichen im buffer vorhanden
+    {
+    ch = RS485.getc();
+    pc.printf(" %02x",ch);
+    if ((ch == 0x02) && (msg_in.sm == 0))
+    { 
+        // ein neues Telegramm startet
+        // ? ein timemout einbauen
+        msg_in.STX = ch;
+        msg_in.sm = 1;
+    }
+    else
+    {
+       switch(msg_in.sm)
+       {
+          case 1:
+            msg_in.source = ch;
+            msg_in.sm++;
+            break;
+            
+          case 2:
+            msg_in.dest = ch;
+            msg_in.sm++;
+            break;
+            
+          case 3:
+            msg_in.count = ch;
+            msg_in.sm++;
+            pos = 0;
+            break;
+            
+          case 4:
+            msg_in.data[pos] = ch;
+            pos++;
+            msg_in.count--;
+            if (msg_in.count == 0)
+            {
+              msg_in.sm++;   
+            }
+            break;
+             
+           case 5:
+            msg_in.CRC = ch;
+            msg_in.sm++;
+            break;
+            
+           case 6:
+            msg_in.ETX = ch;
+            msg_in.sm = 0;  // auf ein neues Telegramm warten 
+            rs_aktiv = 0;
+              
+            // CRC prüfen
+            uint8_t crc = get_crc(&msg_in.source,msg_in.len+3); // CRC Summe ermitteln
+            if (crc == msg_in.CRC)
+            {
+                msg_in.error = 0xFF; // Telegramm korrekt empfangen
+            }
+            else
+            {
+                msg_in.error |= 0x80; // CRC Fehler
+            }
+            
+            // Telegramm ausgeben
+            pc.printf("\n receive");
+            msg_print(msg_in);
+            pc.printf(" stauts: %02x\n",msg_in.error);
+            
+            break;   
+       }
+       }
+    }
+}    
+
+
+
+