Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of timer0 by
rs_485.cpp
00001 //--------------------------------------------------------------------------- 00002 // Modul...: RS_485.CPP 00003 // Chip....: iox.mini 00004 // 00005 //--------------------------------------------------------------------------- 00006 // Author..: Reinhold Schäfer 00007 // Date....: 2016.01.23 00008 // http....: //www.microsps.net 00009 //--------------------------------------------------------------------------- 00010 #include "mbed.h" 00011 #include "rs_485.h" 00012 #include "timer0.h" 00013 00014 MODSERIAL RS485(RS485_TX2, RS485_RX2); // tx, rx 00015 DigitalOut RS485_DIR(RS485_DIR2,0); // RS485 Direction 00016 00017 extern MODSERIAL pc; 00018 extern timer0 down_timer; // definiert in main 00019 00020 //-------------------------------------------------------- 00021 // Interruptroutine wird nach 300µs aufgerufen, da das Senden von 00022 // einem Zeichen ca. 100µs Zeit beansprucht, kann die Umschaltung 00023 // auf Empfang erst verzögert erfolgen. 00024 00025 void rs_485::isr_timeout(void) 00026 { 00027 RS485_DIR = 0; // auf Empfang umschalten 00028 send_end_flag = true; 00029 } 00030 00031 /* 00032 // ----------------------------------------------------------------------- 00033 // This function is called when TX buffer goes empty 00034 // 00035 void rs_485::txEmpty(MODSERIAL_IRQ_INFO *q) 00036 { 00037 timeout.attach_us(this, &rs_485::isr_timeout, 300); // Zeit für das Umschalten 00038 } 00039 */ 00040 //-------------------------------------------------------- 00041 // Construktor initialisiert den Timer 00042 rs_485::rs_485() 00043 { 00044 RS485.baud(115200); 00045 //RS485.attach(this, &rs_485::txEmpty); 00046 timeout.stop(); 00047 timeout.reset(); 00048 msg_in.sm = 0; 00049 msg_out.sm = 0; 00050 rs_aktiv = 0; 00051 rs_aktiv_old = 0; 00052 } 00053 //------------------------------------------------------------- 00054 // Checksum ermitteln 00055 00056 uint8_t rs_485::get_crc(uint8_t *pbuffer, uint8_t count) 00057 { 00058 uint8_t crc_value = 0; 00059 uint8_t temp; 00060 00061 // CheckSum calculation 00062 for(int i=0; i <= count; i++) 00063 { 00064 temp = *pbuffer; 00065 // pc.printf("\n CRC #%02d %02x ^ %02x = ",i,crc_value,temp); 00066 crc_value ^= temp; // XOR from ID to Data 00067 pbuffer++; 00068 // pc.printf("%02x",crc_value); 00069 } 00070 return crc_value; 00071 } 00072 00073 //------------------------------------------------------------- 00074 // zum Testen das Telegramm ausgeben 00075 // 00076 void rs_485::msg_print(Message msg) 00077 { 00078 uint8_t len; 00079 00080 pc.printf(" %02d:%02d:%02d.%03d",msg.h,msg.m,msg.s,msg.ms); 00081 00082 pc.printf(" %02x",msg.STX); 00083 pc.printf(" %02x",msg.source); 00084 pc.printf(" %02x",msg.dest); 00085 pc.printf(" %02x [",msg.len); 00086 00087 len = msg.len; 00088 for (int i = 0; i < len; i++) 00089 { 00090 pc.printf(" %02x",msg.data[i]); 00091 } 00092 pc.printf(" ] %02x",msg.CRC); 00093 pc.printf(" %02x",msg.ETX); 00094 00095 } 00096 00097 // ----------------------------------------------------------------------- 00098 // eine Telegramm erzeugen 00099 // 00100 // die Zeichen STX, CRC und ETX werden automatisch erzeugt 00101 // das Telegramm hat folgenden Aufbau 00102 // STX ADR ZIEL Länge [daten] CRC ETX 00103 // Länge ist Anzahl der Zeichen im Datenfeld 00104 // 00105 void rs_485::write(uint8_t *data) 00106 { 00107 uint16_t millis; 00108 uint8_t len; 00109 00110 msg_out.STX = 0x02; // STX 00111 00112 msg_out.source = *data; // Start Adresse 00113 data++; 00114 00115 msg_out.dest = *data; // Ziel Adresse 00116 data++; 00117 00118 msg_out.len = *data; // Länge 00119 len = *data; 00120 data++; 00121 00122 for (int i = 0; i < len; i++) 00123 { 00124 msg_out.data[i] = *data; // Datenbyte 00125 data++; 00126 } 00127 00128 // pc.printf("\n write crc berechnen \n"); 00129 msg_out.CRC = get_crc(&msg_out.source,msg_out.len+3); // CRC Summe ermitteln 00130 00131 msg_out.ETX = 0x03; // Telegramm Abschluss 00132 00133 // Zeitstempel schreiben 00134 down_timer.get_time_stamp(t_array,&millis); 00135 msg_out.h = t_array[0]; 00136 msg_out.m = t_array[1]; 00137 msg_out.s = t_array[2]; 00138 msg_out.ms = millis; 00139 00140 // Datenausgabe wird aktiviert, prüfen ob harte Umschaltung hier sinnvoll 00141 msg_out.sm = 0; 00142 rs_aktiv = 2; 00143 } 00144 00145 //------------------------------------------------------------- 00146 // Die Telegramme steuern und überwachen 00147 // 00148 void rs_485::execute(void) 00149 { 00150 // auf timeout testen, falls ein fehler auftritt 00151 // wird das Telegramm über diese Stelle abgebrochen 00152 // 00153 00154 int temp; 00155 00156 temp = timeout.read_ms(); 00157 if (temp >= 10) 00158 { 00159 timeout.stop(); 00160 timeout.reset(); 00161 msg_in.sm = 0; 00162 msg_out.sm = 0; 00163 00164 00165 if (rs_aktiv == 1) 00166 { 00167 pc.printf("\nreceive timeout %02d ms",temp); 00168 pc.printf("\n sm: %02x",msg_in.sm); 00169 pc.printf("\n tel:"); 00170 msg_print(msg_out); 00171 } 00172 00173 if (rs_aktiv == 2) 00174 { 00175 pc.printf("\nsende timeout %02d ms",temp); 00176 pc.printf("\n sm: %02x",msg_out.sm); 00177 pc.printf("\n tel:"); 00178 msg_print(msg_out); 00179 } 00180 00181 rs_aktiv = 0; 00182 } 00183 00184 // an dieser Stelle wird der Programmablauf gesteuert 00185 // 0 Bus inaktiv auf Empfang 00186 // 1 BUS aktiv auf Empfangsmode 00187 // 2 BUS aktiv im Sendemode 00188 00189 switch (rs_aktiv) 00190 { 00191 case 0: 00192 00193 if (rs_aktiv != rs_aktiv_old) 00194 { 00195 pc.printf("\n\nreceive"); 00196 timeout.stop(); // timer starten 00197 timeout.reset(); // timer auf 0 setzen 00198 rs_aktiv_old = rs_aktiv; 00199 } 00200 receive(); 00201 break; 00202 00203 case 1: 00204 00205 if (rs_aktiv != rs_aktiv_old) 00206 { 00207 pc.printf("\n\nreceive aktiv"); 00208 timeout.reset(); // timer auf 0 setzen 00209 timeout.start(); 00210 rs_aktiv_old = rs_aktiv; 00211 } 00212 receive(); 00213 break; 00214 00215 case 2: 00216 00217 if (rs_aktiv != rs_aktiv_old) 00218 { 00219 pc.printf("\n\nsende aktiv"); 00220 timeout.reset(); // timer auf 0 setzen 00221 timeout.start(); 00222 rs_aktiv_old = rs_aktiv; 00223 } 00224 send(); 00225 break; 00226 } // end switch 00227 00228 } 00229 00230 // ----------------------------------------------------------------------- 00231 // das Telegramm ausgeben 00232 // 00233 void rs_485::send(void) 00234 { 00235 00236 switch(msg_out.sm) 00237 { 00238 case 0: 00239 // das Senden beginnt erst, wenn das eingehende Telegramm abgeschlossen ist 00240 00241 msg_print(msg_out); 00242 pc.printf(" \n"); 00243 00244 RS485_DIR = 1; // Bus belegen 00245 msg_out.sm = 1; 00246 00247 break; 00248 00249 case 1: // Startzeichen senden 00250 RS485.putc(msg_out.STX); 00251 msg_out.sm++; 00252 break; 00253 00254 case 2: 00255 RS485.putc(msg_out.source); 00256 msg_out.sm++; 00257 break; 00258 00259 case 3: 00260 RS485.putc(msg_out.dest); 00261 msg_out.sm++; 00262 break; 00263 00264 case 4: 00265 RS485.putc(msg_out.len); 00266 msg_out.sm++; 00267 break; 00268 00269 case 5: 00270 for(int i=0; i < msg_out.len; i++) 00271 { 00272 RS485.putc(msg_out.data[i]); 00273 } 00274 msg_out.sm++; 00275 break; 00276 00277 case 6: 00278 RS485.putc(msg_out.CRC); 00279 msg_out.sm++; 00280 break; 00281 00282 case 7: 00283 RS485.putc(msg_out.ETX); 00284 msg_out.sm++; 00285 break; 00286 00287 case 8: 00288 // hier warten bis alle Zeichen ausgegeben 00289 int n = RS485.txBufferGetCount(); 00290 if (n == 0) msg_out.sm = 0; 00291 //tx_timeout1 = timeout.read_us(); 00292 break; 00293 00294 case 9: 00295 // hier warten bis alle Zeichen ausgegeben 00296 00297 //tx_timeout2 = timeout.read_us(); 00298 //if ((tx_timeout2 - tx_timeout1) >= 100) 00299 //{ 00300 msg_out.sm = 0; 00301 RS485_DIR = 0; // Bus frei geben 00302 rs_aktiv = 0; // Bus wieder auf Empfang 00303 //} 00304 break; 00305 00306 default: // wird nie erreicht 00307 pc.printf(" error in sm send %d",msg_out.sm); 00308 break; // 00309 } // end switch 00310 } 00311 00312 // ----------------------------------------------------------------------- 00313 // ein Telegramm lesen 00314 // 00315 void rs_485::receive(void) 00316 { 00317 uint8_t ch, pos; 00318 00319 if (RS485.readable()) // prüfen ob Zeichen im buffer vorhanden 00320 { 00321 ch = RS485.getc(); 00322 pc.printf(" %02x",ch); 00323 if ((ch == 0x02) && (msg_in.sm == 0)) 00324 { 00325 // ein neues Telegramm startet 00326 // ? ein timemout einbauen 00327 msg_in.STX = ch; 00328 msg_in.sm = 1; 00329 } 00330 else 00331 { 00332 switch(msg_in.sm) 00333 { 00334 case 1: 00335 msg_in.source = ch; 00336 msg_in.sm++; 00337 break; 00338 00339 case 2: 00340 msg_in.dest = ch; 00341 msg_in.sm++; 00342 break; 00343 00344 case 3: 00345 msg_in.count = ch; 00346 msg_in.sm++; 00347 pos = 0; 00348 break; 00349 00350 case 4: 00351 msg_in.data[pos] = ch; 00352 pos++; 00353 msg_in.count--; 00354 if (msg_in.count == 0) 00355 { 00356 msg_in.sm++; 00357 } 00358 break; 00359 00360 case 5: 00361 msg_in.CRC = ch; 00362 msg_in.sm++; 00363 break; 00364 00365 case 6: 00366 msg_in.ETX = ch; 00367 msg_in.sm = 0; // auf ein neues Telegramm warten 00368 rs_aktiv = 0; 00369 00370 // CRC prüfen 00371 uint8_t crc = get_crc(&msg_in.source,msg_in.len+3); // CRC Summe ermitteln 00372 if (crc == msg_in.CRC) 00373 { 00374 msg_in.error = 0xFF; // Telegramm korrekt empfangen 00375 } 00376 else 00377 { 00378 msg_in.error |= 0x80; // CRC Fehler 00379 } 00380 00381 // Telegramm ausgeben 00382 pc.printf("\n receive"); 00383 msg_print(msg_in); 00384 pc.printf(" stauts: %02x\n",msg_in.error); 00385 00386 break; 00387 } 00388 } 00389 } 00390 } 00391 00392 00393 00394
Generated on Mon Jul 25 2022 22:54:58 by
1.7.2
