Différences entre versions de « Linux uart sunxi armbian »
(2 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 161 : | Ligne 161 : | ||
[[Fichier:Cp1202 uart opi zero.png|centré]] | [[Fichier:Cp1202 uart opi zero.png|centré]] | ||
= Modification de la vitesse = | = Modification de la vitesse = | ||
− | Pour changer la vitesse du port série il faudra utiliser l'interface POSIX [http://manpagesfr.free.fr/man/man3/termios.3.html ''termios'']. | + | Pour changer la vitesse du port série il faudra utiliser l'interface POSIX [http://manpagesfr.free.fr/man/man3/termios.3.html ''termios'']. Sans recopier l'intégralité du script précédent, voici les étapes qu'ils suffit de suivre: |
+ | * inclure le fichier de définition | ||
+ | <source lang="c"> | ||
+ | #include <termios.h> | ||
+ | </source> | ||
+ | * créer la structure qui va permettre de manipuler le port série: | ||
+ | <source lang="c"> | ||
+ | struct termios options; | ||
+ | </source> | ||
+ | * récupérer les options du port: | ||
+ | <source lang="c"> | ||
+ | tcgetattr(fd, &options); | ||
+ | </source> | ||
+ | * modifier la vitesse, ici 115200 bauds: | ||
+ | <source lang="c"> | ||
+ | cfsetispeed(&options, B115200); | ||
+ | cfsetospeed(&options, B115200); | ||
+ | </source> | ||
+ | * appliquer les modifications immédiatement (''TCSCANOW''): | ||
+ | <source lang="c"> | ||
+ | tcsetattr(fd, TCSANOW, &options); | ||
+ | </source> | ||
+ | N'hésitez pas à parcourir [https://www.cmrr.umn.edu/~strupp/serial.html#2_5_2 cette page] pour plus d'information sur les options disponibles ! |
Version actuelle datée du 14 novembre 2020 à 11:58
Introduction
Nous allons utiliser le protocole UART sur une platine Sunxi (ARM AllWinner) OrangePi Zero. La connexion se fera entre l'OrangePi et un convertisseur USB / UART CP2102
Montage
Nous allons connecter le CP2102 au port UART1 de l'OrangePi. Il faudra donc raccorder les deux de la sorte:
CP2102 -> OrangePi GND -> GND RX -> TX TX -> RX |
Activation du port UART1
Il faut spécifier au système d'exploitation que nous voulons utiliser les broches 7 et 6 pour le port UART et non pas comme GPIO. Cela se fait en ajoutant les lignes suivantes dans le fichier /boot/armbianEnv.txt. Il faut modifier la directive overlays pour ajouter simplement uart1 :
# Exemple d'ajout en plus des overlays USB et du protocole oneWire: overlays=usbhost2 usbhost3 w1-gpio uart1
Il ne reste plus qu'à redémarrer le système pour appliquer les modifications.
Programmation C
Passons en revue les différentes étapes qui nous permettent d'utiliser le port UART:
- la première étape consiste à ouvrir le port, cela se fait avec la fonction open
int fd = open(tty, O_RDWR | O_NOCTTY);
- Une fois le port ouvert on peut écrire avec la fonction write en utilisant le descripteur de fichier retourné par open:
write(fd, message, strlen(message));
- On peut lire avec la fonction read en utilisant également le descripteur de fichier ainsi qu'un tampon (tableau de caractères). N'oubliez pas le \0 qu'il faut ajouter si vous voulez manipuler votre tampon !
char buf[10] = "";
int len = read(fd, buf, 9);
buf[len] = '\0';
N'oubliez pas que l'opération de lecture (read) est bloquante ! Il faudra donc la mettre dans un thread si vous voulez faire une autre action en même temps.
Ci-dessous un petit exemple de programme serial.c qui:
- accède au port série
- démarre un thread pour la lecture de la console (message de l'utilisateur)
- démarre un thread de lecture du port série
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
int open_uart(const char * tty)
{
int fd = open(tty, O_RDWR | O_NOCTTY);
if (fd == -1){
printf("Unable to open %s: %s\n", tty, strerror(errno));
} else {
printf("Opening %s\n", tty);
}
return fd;
}
void * writeSerial(void * arg){
printf("Enter \"exit\" to quit program\n");
int fd = *((int*) arg);
char buffer[80] = "";
// Stocke la longeur du message reçu
int len = 0;
int code = 0;
while(1){
// On lit jusqu'au caractère '\n'
len = scanf("%[^\n]", buffer);
if(len < 0){
perror("Fail reading from console !\n");
code = 1;
break;
}
if(strncmp("exit", buffer, 4) == 0){
break;
}else if(write(fd, buffer, strlen(buffer)) < 0){
perror("Fail writting to UART !\n");
code = 1;
break;
}
// Supprime le caractère '\n'
fgetc(stdin);
}
//Fermeture du port série
close(fd);
// Fermeture du programme
pthread_exit(0);
exit(code);
}
void * readSerial(void * arg){
int fd = *((int*) arg);
// Lecture par bloc de 10 octets
char buf[10] = "";
// Stocke la longeur du message reçu
int len = 0;
// Lecture en boucle, jusqu'à erreur
while(1){
// Lecture des caractères
len = read(fd, buf, 9);
if(len < 0){
// erreur
printf("Fail reading from serial: %s\n", strerror(errno));
break;
}
// Ajout du terminateur de chaîne
buf[len] = '\0';
// Affichage du message
if(len > 0){
printf("%s", buf);
}
}
//Fermeture du port série
close(fd);
// Fermeture du programme
pthread_exit(0);
exit(EXIT_FAILURE);
}
int main(int argc, char * argv[]){
// Récupération des arguments
if(argc < 2){
perror("You must specify an UART to open !\n");
return EXIT_FAILURE;
}
// Ouveture du port série
int fd = open_uart(argv[1]);
if(fd < 0){
return EXIT_FAILURE;
}
// Thread pour la lecture du port série
pthread_t lecture = 0;
// Thread pour écouter le clavier et écrire dans le port série
pthread_t ecriture = 0;
// Démarrage du thread de lecture
pthread_create(&lecture, NULL, readSerial, &fd);
// Démarrage du thread d'écriture
pthread_create(&ecriture, NULL, writeSerial, &fd);
// On attend que l'utilisateur stop le programme en envoyant "exit"
pthread_join(ecriture, NULL);
// On ferme proprement le port série
close(fd);
return EXIT_SUCCESS;
}
Une fois compilé:
# gcc -o serial.bin serial.c -l pthread
On peut lire et écrire sur le port série depuis le CP1202 à 9600 bauds:
Modification de la vitesse
Pour changer la vitesse du port série il faudra utiliser l'interface POSIX termios. Sans recopier l'intégralité du script précédent, voici les étapes qu'ils suffit de suivre:
- inclure le fichier de définition
#include <termios.h>
- créer la structure qui va permettre de manipuler le port série:
struct termios options;
- récupérer les options du port:
tcgetattr(fd, &options);
- modifier la vitesse, ici 115200 bauds:
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
- appliquer les modifications immédiatement (TCSCANOW):
tcsetattr(fd, TCSANOW, &options);
N'hésitez pas à parcourir cette page pour plus d'information sur les options disponibles !