Sep . 2025
Um den DMR858M effizient und zuverlässig zu steuern, empfiehlt sich ein objektorientierter Ansatz mit einer Treiberklasse, die alle Interaktionen mit dem Modul kapselt. Diese Architektur ähnelt Bibliotheken für andere AT-Befehlsmodule (wie GSM- oder WLAN-Module) und bietet gute Modularität und Wiederverwendbarkeit.
Wir werden eine C++-Klasse namens DMR858M_Controller entwerfen. Diese Klasse ist für die Verwaltung der UART-Kommunikation, das Erstellen und Parsen von Datenrahmen, die Verarbeitung von Befehlen und Antworten sowie die Verwaltung des Modulstatus verantwortlich.
// DMR858M_Controller.h #include <Arduino.h> class DMR858M_Controller { public: DMR858M_Controller(HardwareSerial& serial, int pttPin, int csPin); void begin(long speed); bool setFrequency(uint32_t txFreq, uint32_t rxFreq); bool setPowerLevel(bool highPower); bool getFirmwareVersion(String& version); void setPTT(bool active); // ... andere Funktionsprototypen private: HardwareSerial& _serial; int _pttPin; int _csPin; void sendCommand(uint8_t cmd, uint8_t rw, const uint8_t* data, uint16_t len); bool warteAufAntwort(uint8_t* Puffer, uint16_t& Länge, uint32_t Timeout = 1000); uint16_t Prüfsumme berechnen(const uint8_t* Daten, Größe_t Länge); };
sendCommand ist der Kern aller Schreibvorgänge. Es ist für die Zusammenstellung des kompletten Binärpakets, die Berechnung der Prüfsumme und das Senden über UART verantwortlich.
// DMR858M_Controller.cpp void DMR858M_Controller::sendCommand(uint8_t cmd, uint8_t rw, const uint8_t* data, uint16_t len) { const uint16_t totalFrameLen = 9 + len; uint8_t frame[totalFrameLen]; frame[0] = 0x68; // Kopf frame[1] = cmd; // CMD frame[2] = rw; // R/W frame[3] = 0x01; // S/R (Anforderung) frame[4] = 0x00; // CKSUM_HI (temporär) frame[5] = 0x00; // CKSUM_LO (temporär) frame[6] = (len >> 8) & 0xFF; // LEN_HI frame[7] = len & 0xFF; // LEN_LO if (data && len > 0) { memcpy(&frame[8], data, len); } frame[8 + len] = 0x10; // Tail // Prüfsumme von CMD bis zum Ende von DATA berechnen uint16_t checksum = calculateChecksum(&frame[1], 7 + len); frame[4] = (checksum >> 8) & 0xFF; // CKSUM_HI frame[5] = checksum & 0xFF; // CKSUM_LO _serial.write(frame, totalFrameLen); } uint16_t DMR858M_Controller::calculateChecksum(const uint8_t* buf, size_t len) { uint32_t sum = 0; const uint8_t* current_buf = buf; size_t current_len = len; während (aktuelle_Länge > 1) { Summe += (uint16_t)((*aktueller_Puffer << 8) | *(aktueller_Puffer + 1)); aktueller_Puffer += 2; aktuelle_Länge -= 2; } wenn (aktuelle_Länge > 0) { Summe += (uint16_t)(*aktueller_Puffer << 8); } während (Summe >> 16) { Summe = (Summe & 0xFFFF) + (Summe >> 16); } return (uint16_t)(Summe ^ 0xFFFF); }
In eingebetteten Systemen sind blockierende Wartezeiten ein Programmiermuster, das vermieden werden sollte. Eine einfache waitForResponse-Funktion mit einer Schleife wie while(!_serial.available()){} friert die gesamte Hauptschleife ein und verhindert, dass die MCU andere Aufgaben wie die Aktualisierung einer Anzeige oder die Reaktion auf Tastendrücke ausführt. Dies führt zu einem nicht reagierenden System.
Ein robusteres Design sollte nicht blockierend sein . In der Hauptschleife sollte das Programm kontinuierlich den seriellen Port auf Daten prüfen und den eingehenden Datenrahmen mithilfe einer Zustandsmaschine verarbeiten. Dieser Ansatz stellt sicher, dass das System weiterhin andere Echtzeitereignisse verarbeiten kann, während es auf eine Antwort des Moduls wartet. Für eine Plattform wie den ESP32, die FreeRTOS unterstützt, ist die Erstellung einer dedizierten RTOS-Task für die Kommunikation mit dem DMR-Modul eine bessere Lösung. Diese Task kann bei fehlenden Daten blockieren, ohne die Ausführung anderer Tasks zu beeinträchtigen.
Hier ist ein vereinfachtes Beispiel einer nicht blockierenden Leselogik, die für eine Arduino-Loop()-Funktion geeignet ist:
// Vereinfachte, nicht blockierende Antwortverarbeitungslogik void loop() { // ... andere Aufgaben... if (_serial.available()) { // Byte lesen und in einen Puffer legen // Eine Zustandsmaschine zum Parsen des Datenrahmens verwenden (nach Header 0x68 suchen, angegebene Länge lesen, Prüfsumme und Tail 0x10 überprüfen) // Nach erfolgreicher Parsen die Antwortdaten verarbeiten } }
Das Folgende ist ein vollständiges Arduino/PlatformIO-Beispiel, das zeigt, wie das Modul initialisiert, PTT mit einer Taste gesteuert und eine SMS über den seriellen Monitor gesendet wird.
#include <Arduino.h> #include "DMR858M_Controller.h" #define PTT_BUTTON_PIN 25 #define PTT_MODULE_PIN 26 #define LED_PIN 2 HardwareSerial SerialTwo(2); DMR858M_Controller dmr(SerialTwo, PTT_MODULE_PIN, -1); void setup() { Serial.begin(115200); pinMode(PTT_BUTTON_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); dmr.begin(57600); delay(500); String fwVersion; if (dmr.getFirmwareVersion(fwVersion)) { Serial.println("DMR858M Firmware: " + fwVersion); } else { Serial.println("Kommunikation mit DMR858M-Modul fehlgeschlagen."); } // Beispiel: Frequenz für Kanal 1 auf 433,500 MHz einstellen dmr.setFrequency(433500000, 433500000); } void loop() { // PTT-Steuerlogik if (digitalRead(PTT_BUTTON_PIN) == LOW) { dmr.setPTT(true); digitalWrite(LED_PIN, HIGH); // Sendeanzeige } else { dmr.setPTT(false); digitalWrite(LED_PIN, LOW); } // ... hier kann eine nicht blockierende Logik zur Verarbeitung serieller Antworten hinzugefügt werden... // Beispiel: SMS über seriellen Monitor senden if (Serial.available()) { String cmd = Serial.readStringUntil('\n'); if (cmd.startsWith("sms")) { // SMS-Inhalt und Ziel-ID analysieren // dmr.sendSMS(...) aufrufen Serial.println("SMS-Befehl empfangen."); } } }
Teil 1: Detaillierte Analyse des DMR858M-Moduls
Teil 2: Hardwareintegration und Referenzdesign
Teil 3: Dekonstruktion des Serial Control Protocol
Teil 4: Firmware-Entwicklung und Treiberdesign
Teil 5: Erweiterte Funktionen und Schlussfolgerung
+86-755-23080616
sales@nicerf.com
Website: https://www.nicerf.com/
Adresse: 309-314, 3/F, Gebäude A, Hongdu-Geschäftsgebäude, Zone 43, Baoan Dist, Shenzhen, China
Datenschutzrichtlinie
· Datenschutzrichtlinie
Derzeit sind keine Inhalte verfügbar
E-Mail: sales@nicerf.com
Tel.:+86-755-23080616