STM32F4 UART Pilote de HAL
Je suis à essayer de comprendre comment utiliser ce nouveau pilote de HAL. Je veux recevoir des données à l'aide de la HAL_UART_Receive_IT()
qui met en place le dispositif pour exécuter une fonction d'interruption lorsque des données sont reçues.
Problème, c'est que vous devez spécifier la longueur de données à lire avant l'interruption se déclenche. J'ai l'intention de l'envoi de la console de commandes de longueur variable ne peut donc pas avoir une longueur fixe. Je suppose que la seule façon de le faire serait de lire une seule caractères à la fois, et de construire une chaîne distincte.
Le pilote de HAL semble avoir un problème où, si vous définissez la HAL_UART_Receive_IT()
pour recevoir x
nombre de caractères, puis essayez d'envoyer plus de x
personnages, il y aura une erreur.
Actuellement, je n'ai aucune idée de si je vais sur le droit chemin, des idées?
Vous devez vous connecter pour publier un commentaire.
J'ai décidé d'aller avec DMA pour obtenir le recevoir travail. Je suis à l'aide d'un 1 byte buffer circulaire de traiter les données comme il est tapé sur l'émetteur de série du terminal. Voici mon code final (uniquement la partie, plus d'infos sur les transmettre à la partie inférieure).
Certains définit et variables:
Configurer IO:
Configurer l'UART:
Configurer DMA:
Configurer DMA interrompre:
Commencer DMA:
DMA recevoir de rappel:
Donc c'est à peu près tout le code pour recevoir des caractères et de construire une chaîne de caractères (char tableau) qui indique que l'utilisateur a entré. Si l'utilisateur appuie sur la touche retour arrière ou suppr, le dernier caractère dans le tableau est remplacé et si ils ont frappé entrer, ce tableau est envoyé à une autre fonction et traitée comme une commande.
De voir comment l'analyse de commandes et de transmettre des code fonctionne, voir mon projet Ici
Grâce à @Flip et @Dormen pour leurs suggestions!
La réception de données, tandis que le Registre de Données (DR) est complet entraînera une erreur dépassement de capacité. Le problème est que la fonction
UART_Receive_IT(UART_HandleTypeDef*)
arrêter de lire le DR registre une fois qu'il a reçu suffisamment de données. Toutes les nouvelles données qui seront la cause de l'erreur dépassement de capacité.Ce que j'ai fait a été d'utiliser une circulaire DMA recevoir de la structure. Vous pouvez ensuite utiliser
currentPosInBuffer - uart->hdmarx->Instance->NDTR
pour déterminer la quantité de données reçues que vous n'avez pas encore été traités.C'est un peu plus compliqué parce que tout le DMA ne la circulaire de mise en mémoire tampon, vous devez manuellement mettre en œuvre le bouclage le début si vous allez au-delà de la fin de la mémoire tampon.
J'ai également trouvé un glitch où le contrôleur dit qu'il en a transféré les données (c'est à dire
NDTR
a diminué), mais les données ne sont pas encore dans la mémoire tampon. Il peut y avoir certains DMA/accès au bus de contention de problème, mais c'est ennuyeux.Le STM32 UART les pilotes sont un peu bancale. La seule façon dont ils fonctionnent hors de la boîte, si vous connaissez le nombre exact de caractères que vous allez recevoir. Si vous souhaitez recevoir un nombre quelconque de caractères, il existe quelques solutions que j'ai trouvé et essayé:
Définir le nombre de caractères à recevoir de 1 et de construire une chaîne distincte. Cela fonctionne, mais a des problèmes lors de la réception de données très rapide, parce que chaque fois que le pilote lit le rxBuffer il dissables de l'interruption, de sorte que certains caractères peuvent être perdues.
Définir le nombre de caractères à recevoir le plus possible la taille du message et de mettre en œuvre un dépassement de délai, après lequel l'ensemble du message est lu.
Écrire votre propre UART_Receive_IT fonction, qui écrit directement dans une mémoire tampon circulaire. C'est plus de travail, mais c'est ce que j'ai trouvé qui fonctionne le mieux dans la fin. Vous ne devez modifier certains de hal pilotes, donc le code est moins portable.
Une autre méthode consiste à utiliser le DMA comme @Flip suggéré.
Wait for 1 byte -> receive value "5", Wait for 5 bytes -> receive the 5 bytes, Wait for 1 byte -> receive value "28", Wait for 28 bytes -> receive the 28 bytes, ..., Wait for 1 byte -> receive value "0", END
J'ai dû faire face au même problème dans mon projet.
Ce que j'ai fait est de commencer la lecture de 1 octet avec
HAL_USART_Receive_IT()
juste après le périphérique d'initialisation.Ensuite, j'ai écrit un rappel sur transfert complet qui met l'octet dans le buffer, définit un indicateur si la commande est complète et appelle ensuite
HAL_USART_Receive_IT()
à nouveau pour un autre octet.Il semble que ça fonctionne bien pour moi depuis que je reçois des commandes par l'USART dont le premier octet m'indique combien d'octets de plus que la commande va être long.
Peut-être que ça pourrait fonctionner pour vous aussi!
Ont une approche différente de l'application de correctifs ex: "nul USART2_IRQHandler(void)" dans le fichier "stm32l0xx_it.c" (ou l4xx que nécessaire). Chaque fois qu'un caractère est reçu cette interruption est appelée. Il y a d'espace pour insérer du code d'utilisateur qui maintient inchangées lors de la mise à jour avec CubeMX générateur de code. Patch:
J'offre un petit tampon de caractère et de commencer à le recevoir de la fonction. Jusqu'à 115200 Bauds il n'a jamais consommé plus d ' 1 Octet en laissant le reste de la mémoire tampon utilisé.
Lors de la réception d'un octet je le capturer et de le mettre à mon propre anneau de la mémoire tampon et de définir le caractère de pointeur et de gré à dos:
Cette méthode s'est révélée être plutôt rapide. La réception d'un seul octet de l'utiliser ou de DMA toujours de-initialise et les besoins de l'initialisation du processus de réception, qui s'est avéré être trop lent. Le code ci-dessus est seulement une image, j'ai utilisé pour compter les caractères de saut de ligne ici, dans un état de structure qui me permet de tout le temps de lire terminé lignes de l'anneau de la mémoire tampon. Également vérifier si la réception d'un caractère ou d'un autre événement a causé l'interruption doit être inclus.
EDIT:
Cette méthode a prouvé à travailler très bien avec USARTS qui ne sont pas pris en charge par la DMA et l'utiliser à la place.
À l'aide de DMA avec 1 octet en mode circulaire est plus court et plus facile à mettre en œuvre lors de l'utilisation de CubeMX générateur avec HAL bibliothèque.
D'habitude, j'ai écrit mon propre UART tampon circulaire de mise en œuvre. Comme dit avant, STM32 HAL de la bibliothèque de l'UART interrompre les fonctions sont un peu étrange.
Vous pouvez écrire votre propre tampon circulaire avec seulement 2 tableau et à l'aide de pointeurs UART interrompre les drapeaux.