Zeitsteuerung
Fork of timer0 by
Revision 1:8779e76fd4ea, committed 2016-02-05
- Comitter:
- rs27
- Date:
- Fri Feb 05 14:39:43 2016 +0000
- Parent:
- 0:8d3e2b74d1d5
- Commit message:
- RS485 driver
Changed in this revision
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