Question

Ceci est lié avec les microcontrôleurs, mais pensé pour poster ici parce qu'il ya un problème avec les types d'algorithmes et de données et non pas avec tout le matériel de trucs. Je vais vous expliquer le problème afin que quelqu'un qui n'a pas de connaissances du matériel peut encore participer:)

  
      
  1. Dans Microcontroller il y a un convertisseur analogique-numérique 10   bits de résolution. (Il sera une sortie   valeur comprise entre 0 et 1023)

  2.   
  3. Je dois envoyer cette valeur au PC en utilisant le port série.

  4.   
  5. Mais vous ne pouvez écrire 8 bits à la fois. (Vous devez octets d'écriture). Il est   une limitation dans le micro-contrôleur.

  6.   
  7. Ainsi, dans le cas ci-dessus au moins, je dois envoyer 2 octets.

  8.   
  9. Mon application PC se contente de lire une séquence de nombres pour le traçage. Donc   il devrait saisir deux années consécutives   octets et construire le nombre de retour. Mais   ici, nous aurons besoin d'un delimiter   caractère aussi bien. mais le délimiteur a une valeur ascii entre 0 -. 255 alors il MixUp le processus

  10.   

Alors, quelle est une façon la plus simple de le faire? Dois-je envoyer les valeurs comme une séquence de caractères?

Ex : 1023 = "1""0""2""3" Vs "Char(255)Char(4)"

En résumé je dois envoyer une séquence de 10 numéros de bits sur série de manière plus rapide. :)

Était-ce utile?

La solution

Vous devez envoyer 10 bits, et parce que vous envoyez un octet à la fois, vous devez envoyer 16 bits. La grande question est de savoir combien est la vitesse une priorité, et comment synchroniser sont l'émetteur et le récepteur? Je peux penser à 3 réponses, selon ces conditions.

L'échantillonnage régulier, inconnu point de jonction

Si l'appareil fonctionne tout le temps, vous n'êtes pas sûr quand vous allez vous connecter (vous pouvez joindre à tout moment dans la séquence), mais le taux d'échantillonnage est plus lent que la vitesse de communication de sorte que vous ne se soucient pas de la taille Je pense que je ferais probablement comme suit. Supposons que vous essayez d'envoyer le abcdefghij dix bits (chaque lettre d'un bit).

J'envoyer pq0abcde alors pq1fghij, où p et q sont les bits de contrôle d'erreur de . De cette façon:

  • pas delimiter est nécessaire (vous pouvez dire quel octet vous lisez par 0 ou 1)
  • vous pouvez certainement repérer toute erreur 1 bit, vous savez de mauvaises données

J'ai du mal à trouver un bon deux code de correction d'erreur binaire, donc je suppose que je venais de faire peu de parité pa pour les bits 2,3 et 4 (0, ab ci-dessus) et qa bit de parité pour 5 6 et 7 (c, d, e ci-dessus). Cela pourrait être plus clair avec un exemple.

  1. Si je veux envoyer 714 = 1011001010.
  2. Split en 2 10110, 01010
  3. Ajouter des bits pour indiquer un premier et un second octet 010110, 101010
  4. calculer la parité pour chaque moitié: p0 = par (010) = 1, q0 = par (110) = 0, p1 = par (101) = 0, q1 = par (010) = 1
  5. octets sont alors 10010110, 01101010

Vous avez alors peut détecter un grand nombre de différentes conditions d'erreur, vérifiez rapidement quel octet vous être envoyé si vous perdez la synchronisation, et aucune des opérations très long dans un microcontrôleur (je ferais la parité avec une 8 entrée recherche tableau).

Données Dense, point de jonction connu

Si vous savez que le lecteur démarre en même temps que l'écrivain, il suffit d'envoyer les 4 dix valeurs de bits en 5 octets. Si vous lisez toujours 5 octets à la fois alors aucun problème. Si vous voulez encore plus d'économie d'espace, et ont de bonnes données d'échantillons déjà, je compresser en utilisant un Huffman .

Données Dense, inconnu point de jonction

Dans 7 octets, vous pouvez envoyer 5 dix valeurs de bits avec 6 bits de rechange. Envoyer 5 valeurs comme ceci:

  • octet 0: 0 (7 bits)
  • octet 1: 1 (7 bits)
  • octet 2: 1 (7 bits)
  • octet 3: 1 (7 bits)
  • 4 octets: 0 (7 bits)
  • octet 5: 0 (7 bits)
  • octet 6: (8 bits)

Ensuite, chaque fois que vous voyez 3 1 dans une rangée pour le bit le plus significatif, vous savez que vous avez octets 1, 2 et 3. Ce déchets idée 1 bit à 56, pourrait donc être encore plus efficace, mais vous auriez d'envoyer plus de données à la fois. Par exemple, (5 consécutifs, 120 bits envoyés dans 16 octets):

  • octet 0: 0 (7 bits) 7
  • octet 1: 1 (7 bits) 14
  • octet 2: 1 (7 bits) 21
  • octet 3: 1 (7 bits) 28
  • octet 4: 1 (7 bits) 35
  • octet 5: 1 (7 bits) 42
  • 6 octets: 0 (7 bits) 49
  • octet 7: (8 bits) 57
  • octet 8: (8 bits) 65
  • octet 9: (8 bits) 73
  • octet 10: (8 bits) 81
  • octet 11: 0 (7 bits) 88
  • octet 12: (8 bits) 96
  • octet 13: (8 bits) 104
  • octet 14: (8 bits) 112
  • octet 15: (8 bits) 120

Ce problème est assez amusant!

Autres conseils

La meilleure méthode consiste à convertir les données en une chaîne ASCII et l'envoyer de cette façon - il rend le débogage beaucoup plus facile et évite divers problèmes de communication (signification particulière de certains caractères de contrôle, etc.)

.

Si vous avez vraiment besoin d'utiliser toute la bande passante disponible mais vous pouvez emballer 4 10 valeurs de bits en 5 octets consécutifs 8 bits. Vous devez être prudent sur la synchronisation.

Depuis que vous avez spécifié « la plus rapide » Je pense que l'expansion du nombre d'ASCII est exclue.

A mon avis, un bon compromis de simplicité et de performance code peut être obtenu par le codage suivant:

Deux valeurs 10 bits seront codés en 3 octets comme celui-ci.

premiers bits de la valeur de 10 bits: = abcdefghij

seconds bits de valeur de 10 bits: = klmnopqrst

Octets à encode:

1abcdefg
0hijklmn
0_opqrst

Il y a un peu plus (_) disponible qui pourrait être utilisé pour une parité sur tous les 20 bits pour le contrôle d'erreur ou tout simplement réglé sur une valeur fixe.

Quelques exemples de code (0 met à la position _):

#include <assert.h>
#include <inttypes.h>

void
write_byte(uint8_t byte);    /* writes byte to serial */

void
encode(uint16_t a, uint16_t b)
{
  write_byte(((a >> 3) & 0x7f) | 0x80);
  write_byte(((a & 3) << 4) | ((b >> 6) & 0x7f));
  write_byte(b & 0x3f);
}

uint8_t
read_byte(void);  /* read a byte from serial */

void
decode(uint16_t *a, uint16_t *b)
{
  uint16_t x;

  while (((x = read_byte()) & 0x80) == 0)  {}  /* sync */
  *a = x << 3;

  x = read_byte();
  assert ((x & 0x80) == 0); /* put better error handling here */

  *a |= (x >> 4) & 3;
  *b = x << 6;

  x = read_byte();
  assert ((x & 0xc0) == 0); /* put better error handling here */

  *b |= x;
}

J'utilise normalement un octet de début et de contrôle et dans ce cas de longueur fixe, donc envoyer 4 octets, le récepteur peut rechercher l'octet de début et si les trois prochaines ajouter à une quantité de savoir alors il est un bon paquet sortir les deux octets intermédiaires, si tiennent pas à la recherche. Le récepteur peut resynchroniser et il ne marche pas perdre la bande passante de ascii. Ascii est votre autre option, un octet de démarrage qui est pas un nombre et peut-être quatre chiffres pour décimal. Décimal est certainement pas amusant dans un microcontrôleur, alors commencez avec quelque chose de non-hexagonal comme X par exemple, et puis trois octets avec les valeurs ascii hexagonaux pour votre numéro. Rechercher les x examiner les trois octets, espoir pour le mieux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top