Zeitsteuerung

Fork of timer0 by V09

Files at this revision

API Documentation at this revision

Comitter:
rs27
Date:
Fri Feb 05 14:39:43 2016 +0000
Parent:
0:8d3e2b74d1d5
Commit message:
RS485 driver

Changed in this revision

rs_485.cpp Show annotated file Show diff for this revision Revisions of this file
rs_485.h Show annotated file Show diff for this revision Revisions of this file
timer0.cpp Show diff for this revision Revisions of this file
timer0.h Show diff for this revision Revisions of this file
diff -r 8d3e2b74d1d5 -r 8779e76fd4ea rs_485.cpp
--- /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;   
+       }
+       }
+    }
+}    
+
+
+
+ 
diff -r 8d3e2b74d1d5 -r 8779e76fd4ea rs_485.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rs_485.h	Fri Feb 05 14:39:43 2016 +0000
@@ -0,0 +1,61 @@
+
+#include "mbed.h"
+#include "MODSERIAL.h"
+
+// Schnittstelle für den H-Bus
+#define RS485_TX2   P2_0
+#define RS485_RX2   P2_1
+#define RS485_DIR2  P1_4
+
+class rs_485 {
+
+  private:
+
+    Timer   timeout;        // define debounce timer
+    Timeout timeout_out;
+    
+    int tx_timeout1;
+    int tx_timeout2;
+     
+    bool send_end_flag;     // Flag für Telegrammende
+    uint8_t rs_aktiv;       // 0 inaktiv auf Empfang
+                            // 1 aktiv auf Empfang
+                            // 2 aktiv im Sendemodus
+    uint8_t rs_aktiv_old;
+    uint8_t t_array[4];
+    int     zeit;
+      
+  public:
+
+    struct Message {
+    uint8_t     STX;                // Start byte
+    uint8_t     source;             // Absender Adresse
+    uint8_t     dest;               // Ziel Adresse 
+    uint8_t     len;                // Length of data field in bytes   
+    uint8_t     data[8];            // Data field
+    uint8_t     CRC;                // CRC
+    uint8_t     ETX;                // Telegramm Ende
+    uint8_t     h;
+    uint8_t     m;
+    uint8_t     s;
+    uint16_t    ms;
+    uint8_t     count;              // interner Zähler
+    uint8_t     sm;                 // interne Steuerung ( state maschine )
+    uint8_t     error; 
+    };
+
+    Message msg_out;
+    Message msg_in; 
+       
+    rs_485();
+   
+    void isr_timeout(void);
+    void txEmpty(MODSERIAL_IRQ_INFO *q);
+    uint8_t get_crc(uint8_t *pbuffer, uint8_t count);
+    void msg_print(Message msg);
+    void write(uint8_t *data);
+    void execute(void);
+    void send(void);
+    void receive(void);
+     
+};
\ No newline at end of file
diff -r 8d3e2b74d1d5 -r 8779e76fd4ea timer0.cpp
--- a/timer0.cpp	Sat Jan 03 15:26:23 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-#include "mbed.h"
-#include "timer0.h"
-
-
-//--------------------------------------------------------
-// Construktor initialisiert den Timer
-timer0::timer0()
-{
-    uint8_t i;
-    
-    ms = 0;
-    sec = 0;
-    
-    // Initialize countdown timers
-    for (i=0; i < TIMER0_NUM_COUNTDOWNTIMERS; i++)
-      CountDownTimers[i].status = 0xFF;
-  
-    ticker.attach_us(this, &timer0::func, 1000);
-}
-
-//--------------------------------------------------------
-// Interruptroutine wird jede ms aufgerufen
-void timer0::func(void)
-{
-    uint8_t i;
-    
-    if(counter != 0) counter--;
-
-    // Zeitbasis für Systemzeit
-    // ----- count down timers in ms -------------------------------------------------
-    for (i=0; i<TIMER0_NUM_COUNTDOWNTIMERS; i++) 
-    {
-        if (CountDownTimers[i].status == 1) 
-        {       // ms
-            if (CountDownTimers[i].count_timer > 0)
-                CountDownTimers[i].count_timer -- ;
-            if (CountDownTimers[i].count_timer == 0)
-                CountDownTimers[i].status = 0;
-        }
-    }
-    
-    if (ms < 1000) 
-    {
-        ms++;  
-    }
-    else
-    {
-        ms = 0;
-       
-        seconds++;
-        set_time(seconds);
-       
-        // ----- count down timers in s -------------------------------------------------
-        for (i=0; i<TIMER0_NUM_COUNTDOWNTIMERS; i++) 
-        {
-            if (CountDownTimers[i].status == 2) 
-            {   // sekunden
-                if (CountDownTimers[i].count_timer > 0)
-                    CountDownTimers[i].count_timer -- ;
-                if (CountDownTimers[i].count_timer == 0)
-                    CountDownTimers[i].status = 0;
-            }
-        }
-        
-        if (sec < 60) 
-        {
-            sec++;
-        }
-        else
-        {
-            sec = 0; 
-            
-            // hier folgt der Minutenzähler falls erforderlich           
-        }   
-    }
-    
-}
-
-//--------------------------------------------------------
-// Abfrage nach freiem Timer
-//
-// wenn alle Timer belegt sind wird 0xFF zurückgegebne
-
-uint8_t timer0::AllocateCountdownTimer (void)
-{
-    uint8_t i;
-    
-    for (i=0; i<TIMER0_NUM_COUNTDOWNTIMERS; i++)
-        if (CountDownTimers[i].status == 0xFF)
-        {
-            CountDownTimers[i].status = 0x00;   // Timer reserviert, nicht gestartet
-            // printf_P(PSTR("\rallocate timer [%03d] %d\n"),i,ListPointer);            
-            
-            return i;
-        }
-
-    return 0xFF;
-}
-
-//--------------------------------------------------------
-// Timer wieder freigeben
-void timer0::RemoveCountdownTimer(uint8_t timer)
-{
-    CountDownTimers[timer].status = 0xFF;
-}
-
-//--------------------------------------------------------
-// Abfrage ob Timer 0 erreicht hat                  
-uint8_t timer0::GetTimerStatus(uint8_t timer)
-{
-    return CountDownTimers[timer].status;
-}
-
-//--------------------------------------------------------
-// Abfrage der verbleibenden Zeit               
-uint16_t timer0::GetTimerZeit(uint8_t timer)
-{
-    return CountDownTimers[timer].count_timer;
-}
-
-//--------------------------------------------------------
-// Timer aktivieren
-void timer0::SetCountdownTimer(unsigned char timer, unsigned char status, unsigned short value)
-{
-    CountDownTimers[timer].count_timer = value;
-    CountDownTimers[timer].status = status;
-}
-
-//--------------------------------------------------------
-// Zeitstempel setzen
-void timer0::Set_t(uint8_t * data)
-{
-    char buffer[40];    
-    
-    t.tm_sec  = data[0];     // Sekunden 0-59
-    t.tm_min  = data[1];     // Minuten 0-59
-    t.tm_hour = data[2];     // Stunden 0-23
-    t.tm_mday = data[3];     // Tag 1-31
-    t.tm_mon  = data[4] - 1; // Monat 0-11 0 = Januar
-    t.tm_year = data[5];     // Jahr year since 1900   
-    
-    seconds = mktime(&t);
-    set_time(seconds);
-    
-    strftime(buffer, 40, "%a,%d.%m.%Y %H:%M:%S", localtime(&seconds));
-    // pc.printf("\ntimer0::set_t = %s", buffer);   
-}
diff -r 8d3e2b74d1d5 -r 8779e76fd4ea timer0.h
--- a/timer0.h	Sat Jan 03 15:26:23 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-
-#include "mbed.h"
-
-#define TIMER0_NUM_COUNTDOWNTIMERS  25
-
-// status definition:
-// 0            the timer has expired
-// 1            10 ms Timer
-// 2            Sekunden Timer
-// 3            Minuten Timer
-// 4            Stunden Timer
-// 0xFF         Free timer
-
-
-class timer0 {
-  private:
-    
-    struct timerStruct
-    {
-      unsigned char status;           // siehe Beschreibung
-      unsigned int count_timer;       // count down Zähler
-    } CountDownTimers[TIMER0_NUM_COUNTDOWNTIMERS];    
-    
-    struct tm t;        // Struktur Datum & Zeit
-    
-    Ticker ticker;
-  
-  public:
-    uint16_t counter;
-    
-    uint16_t ms;        // Zähler für milli Sekunden
-    uint8_t sec;        // Zähler für die Sekunden
-    time_t seconds;     // Sekunden
-        
-    timer0();
-    void func(void);
-    uint8_t AllocateCountdownTimer (void);
-    void RemoveCountdownTimer(uint8_t timer);
-    uint8_t GetTimerStatus(uint8_t timer);
-    uint16_t GetTimerZeit(uint8_t timer);
-    void SetCountdownTimer(unsigned char timer, unsigned char status, unsigned short value);
-    void Set_t(uint8_t * data);
-};
\ No newline at end of file