Différences entre versions de « Linux uart sunxi armbian »

De The Linux Craftsman
Aller à la navigation Aller à la recherche
Ligne 26 : Ligne 26 :
  
 
= Programmation C =
 
= Programmation C =
Ci-dessous un ''petit'' exemple de programme qui accède au port UART pour lire:
+
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''
 
<source lang="c">
 
<source lang="c">
 +
int fd = open(tty, O_RDWR | O_NOCTTY);
 +
</source>
 +
* Une fois le port ouvert on peut écrire avec la fonction ''write'' en utilisant le descripteur de fichier retourné par ''open'':
 +
<source lang="c">
 +
write(fd, message, strlen(message));
 +
</source>
 +
* 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 !
 +
<source lang="c">
 +
char buf[10] = "";
 +
int len = read(fd, buf, 9);
 +
buf[len] = '\0';
 +
</source>
 +
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
 +
<source lang="c">
 +
#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;
 +
}
 
</source>
 
</source>
 +
Une fois compilé:
 +
<pre>
 +
# gcc -o serial.bin serial.c -l pthread
 +
</pre>
 +
On peut lire et écrire sur le port série depuis le CP1202:
 +
[[Fichier:Cp1202 uart opi zero.png|centré]]

Version du 17 octobre 2020 à 21:08

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

Cp2102.png

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
Uart cp2102 opi.png

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:

Cp1202 uart opi zero.png