MAISONÀ PROPOS DE NOUSINFORMATIONS SUR L'INDUSTRIE GUIDE PRATIQUE DES TALKIES-WALKIES NUMéRIQUES ESP3...

Guide pratique des talkies-walkies numériques ESP32 personnalisés (Partie 4) : Développement du micrologiciel et conception des pilotes

11

Sep . 2025

Par SDGA:

Pour contrôler le DMR858M de manière efficace et fiable, une approche orientée objet est recommandée, créant une classe de pilote pour encapsuler toutes les interactions avec le module. Cette architecture est similaire aux bibliothèques conçues pour d'autres modules de commande AT (tels que les modules GSM ou Wi-Fi) et offre une bonne modularité et une grande réutilisabilité.

Méthode d'architecture : classe DMR858M_Controller

Nous concevrons une classe C++ nommée DMR858M_Controller. Cette classe sera responsable de la gestion des communications UART, de la création et de l'analyse des trames de données, de la gestion des commandes et des réponses, et de la gestion de l'état du module.

// 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);     // ... autres prototypes de fonctions private:     HardwareSerial& _serial;     int _pttPin;     int _csPin;     void sendCommand(uint8_t cmd, uint8_t rw, const uint8_t* data, uint16_t len);     bool waitForResponse(uint8_t* tampon, uint16_t& len, uint32_t timeout = 1000);     uint16_t calculateChecksum(const uint8_t* données, size_t len); };






















Détails de l'implémentation principale (exemple de code)

Construction et transmission de paquets

La commande sendCommand est au cœur de toutes les opérations d'écriture. Elle est responsable de l'assemblage du paquet binaire complet, du calcul de la somme de contrôle et de son envoi via UART.

// 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; // Head     frame[1] = cmd; // CMD     frame[2] = rw; // R/W     frame[3] = 0x01; // S/R (Requête)     frame[4] = 0x00; // CKSUM_HI (temporaire)     frame[5] = 0x00; // CKSUM_LO (temporaire)     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     // Calculer la somme de contrôle de CMD à la fin de DATA     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;     while (current_len > 1) {         somme += (uint16_t)((*current_buf << 8) | *(current_buf + 1));         current_buf += 2;         current_len -= 2;     }     if (current_len > 0) {         somme += (uint16_t)(*current_buf << 8);     }     while (somme >> 16) {         somme = (somme & 0xFFFF) + (somme >> 16);     }     return (uint16_t)(somme ^ 0xFFFF); }








   


   


   



   

   


   


   






















Importance de la gestion des réponses et des opérations asynchrones

Dans les systèmes embarqués, les attentes bloquantes sont un schéma de programmation à éviter. Une simple fonction waitForResponse utilisant une boucle comme while(!_serial.available()){} gèlera toute la boucle principale, empêchant le microcontrôleur d'effectuer d'autres tâches, comme la mise à jour d'un affichage ou la réponse aux boutons, ce qui entraînera un système insensible.

Une conception plus robuste devrait être non bloquante . Dans la boucle principale, le programme doit vérifier en permanence la présence de données sur le port série et utiliser une machine à états pour traiter la trame de données entrante. Cette approche garantit que le système peut continuer à gérer d'autres événements temps réel en attendant une réponse du module. Pour une plateforme comme l'ESP32 prenant en charge FreeRTOS, une meilleure solution consiste à créer une tâche RTOS dédiée pour gérer la communication avec le module DMR. Cette tâche peut se bloquer en l'absence de données sans affecter l'exécution des autres tâches.

Voici un exemple simplifié de logique de lecture non bloquante adaptée à une fonction Arduino loop() :

// Logique simplifiée de gestion des réponses non bloquantes void loop() {     // ... autres tâches...     if (_serial.available()) {         // Lire l'octet et le placer dans un tampon         // Utiliser une machine à états pour analyser la trame de données (rechercher l'en-tête 0x68, lire la longueur spécifiée, vérifier la somme de contrôle et la queue 0x10)         // Une fois l'analyse réussie, traiter les données de réponse     } }










Exemple complet : un programme de preuve de concept

Ce qui suit est un exemple Arduino/PlatformIO complet qui montre comment initialiser le module, contrôler le PTT avec un bouton et envoyer un SMS via le moniteur série.

#include <Arduino.h> #include "DMR858M_Controller.h" #définir PTT_BUTTON_PIN 25 #définir PTT_MODULE_PIN 26 #définir 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("Micrologiciel DMR858M : " + fwVersion);     } else {         Serial.println("Échec de la communication avec le module DMR858M.");     }     // Exemple : définir la fréquence du canal 1 sur 433,500 MHz     dmr.setFrequency(433500000, 433500000); } void loop() {     // Logique de contrôle PTT     if (digitalRead(PTT_BUTTON_PIN) == LOW) {         dmr.setPTT(true);         digitalWrite(LED_PIN, HIGH); // Indicateur de transmission     } else {         dmr.setPTT(false);         digitalWrite(LED_PIN, LOW);     }     // ... une logique de gestion de réponse série non bloquante peut être ajoutée ici...     // Exemple : envoyer des SMS via un moniteur série     if (Serial.available()) {         String cmd = Serial.readStringUntil('\n');         if (cmd.startsWith("sms")) {             // analyser le contenu du SMS et l'ID cible             // appeler dmr.sendSMS(...)             Serial.println("Commande SMS reçue.");         }     } }



















































Guide pratique des talkies-walkies numériques ESP32 personnalisés


Partie 1 : Analyse approfondie du module DMR858M

Partie 2 : Intégration matérielle et conception de référence

Partie 3 : Déconstruction du protocole de contrôle série

Partie 4 : Développement du micrologiciel et conception des pilotes

Partie 5 : Exploration des fonctionnalités avancées et conclusion



    Contactez-nous

     +86-755-23080616

     sales@nicerf.com

    Site Internet : https://www.nicerf.com/

    Adresse : 309-314, 3/F, bâtiment A, bâtiment commercial de Hongdu, zone 43, Baoan Dist, Shenzhen, Chine

    Contactez-nous
    politique de confidentialité

    politique de confidentialité

    · Politique de confidentialité

    Il n'y a actuellement aucun contenu disponible


               

    Courriel : sales@nicerf.com

    Tél : +86-755-23080616

    Adresse : 309-314, 3/F, bâtiment A, bâtiment commercial de Hongdu, zone 43, Baoan Dist, Shenzhen, Chine


    ×