ATmega328p et Communication série
Bien le bonjour http://chat.developpez.com/smileys/10977-7eb6.gif
Je suis détenteur d'un Arduino Uno. Je m'intéresse plus particulièrement à la programmation de l'ATmega328p en C, en me basant sur les bibliothèques fournis par AVR-GCC ainsi que sur le datasheet du µC.
Mon problème aujourd'hui se situe au niveau de la communication série entre l'Arduino et le Pc. En fait, comme je développe tout autant le côté "transmission de donnée" via l'µC que le côté "réception de donnée" sur le pc, je n'arrive pas à comprendre à quel niveau se situe mon problème.
Actuellement, je transmet en série 8bits de data, sans bit de parité, avec 1bit de stop et le baudrate set à 9600. Pas de notion de "ligne", juste 8bits bête et méchant. Pour mes tests, j'envoie soit une succession de 0 et de 1 à la chaine.
Pour envoyer mes données, j'utilise le code suivant (atmega_main.c):
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| /*
* Test de transmission serial simple...
* ATmega328p
* 8bits de data, 0 bit de parity, 1 bit de stop.
*
*/
#include <avr/io.h>
int main(){
/*
* SETUP
*/
// initialisation de la Frame
UCSR0A &= ~(_BV(1)); // No U2X speed
UCSR0A &= ~(_BV(0)); // Disable Multi-processor communication mode
UCSR0B &= ~(_BV(4)); // Disable receiver
UCSR0B |= _BV(3); // Enable transmitter
UCSR0B &= ~(_BV(2)); // Disable character size... mix avec autre
UCSR0C &= ~(_BV(7));
UCSR0C &= ~(_BV(6)); // Choisis le mode full aynchrone
UCSR0C &= ~(_BV(5));
UCSR0C &= ~(_BV(4)); // Disable parity bit
UCSR0C &= ~(_BV(3)); // Un seul bit de stop
UCSR0C |= _BV(2);
UCSR0C |= _BV(1); // 8bits character size
UCSR0C &= ~(_BV(0)); // Forcer a 0 car asynchrone
// Configuration BAUDRATE via util/setbaud.h
#define F_CPU 1843200 // définis vitesse clock internz
#define BAUD 9600 // baudrate a atteindre
#include <util/setbaud.h> // Se base sur F_CPU et BAUD pour calcule
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE; // définis tout deux dans util/setbaud
/*
* LANCEMET DES FRAMES
*/
unsigned char data = 0;
while(1){
// On attends que UDR0 soit dispo -- Check de UDRE
loop_until_bit_is_set(UCSR0A, 5);
UDR0 = data;
date ^= 1; // Passe de 0 a 1 et 1 a 0
}
return 0;
} |
Le programme sur le pc, lisant sur le port /dev/ttyACM0 (pc_main.c):
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| /*
* Test de reception serial simple...
* Reception via /dev/ttyAMC0 -> envoyé via Arduino & atmega_main.c
* 8bits de data, 0 bit de parity, 1 bit de stop.
*
*/
#include <stdio.h> // affichage
#include <unistd.h> // Read() et termios
// Pour Open() ...
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// Pour termios() ...
#include <termios.h>
int main(){
/**************** DECLARATION ****************/
int com_arduino;
struct termios termios_ACM0;
/* INIT */
// Récupère fd du port com arduino...
// -- uniquement en lecture
// -- le TTY ne devient pas le contrôleur du processus
if((com_arduino = open("/dev/ttyACM0", O_RDONLY | O_NOCTTY)) == -1){
perror("Erreur à l'ouverture du port com /dev/ttrACM0 -- ");
return 1;
}
else {
puts("/dev/ttyACM0 ouvert.");
}
// récupération de termios rattaché au ttyACM0
if(tcgetattr(com_arduino, &termios_ACM0) != 0){
perror("Erreur à l'obtention du termios de /dev/ttyACM0 -- ");
return 2;
}
else {
puts("termios /dev/ttyACM0 obtenu.");
}
/**************** SETUP ****************/
// Set baudrate 9600
if(cfsetispeed(&termios_ACM0, B9600) != 0){
perror("Impossible de set baudrate de /dev/ttyACM0 -- ");
return 3;
}
else {
puts("Set Baudrate de termios réussis.");
}
// Non-canonique, 8bits de data, 1bit de stop, pas de bit de parité
termios_ACM0.c_iflag &= ~INPCK; // Disable pit parity check
termios_ACM0.c_cflag &= ~CSIZE; // Mets a 0 size data
termios_ACM0.c_cflag |= CS8; // 8bits de data
termios_ACM0.c_cflag |= CREAD; // Enable receiver
termios_ACM0.c_cflag &= ~CSTOPB; // 1 seul stop bit
termios_ACM0.c_cflag &= ~PARENB; // Disable parity check
termios_ACM0.c_lflag &= ~ICANON; // Mode non-canonique
termios_ACM0.c_lflag &= ~ECHO; // No-Echo
/*
* MIN > 0, TIME == 0 (blocking read)
* read(2) blocks until MIN bytes are available, and returns up to the
* number of bytes requested.
*/
termios_ACM0.c_cc[VMIN] = 1; // Attente de 1byte
termios_ACM0.c_cc[VTIME] = 0; // 0 de delay
// Set termios
if(tcsetattr(com_arduino, TCSANOW, &termios_ACM0) != 0){
perror("Impossible de set termios de /dev/ttyACM0 -- ");
return 4;
}
else {
puts("Set de termios /dev/ttyACM0 réussis.");
}
/**************** LET'S GO' ****************/
puts("\nMise en place de la lecture...\n");
unsigned char ch_read = 0;
int size_read = 0;
while(1){
size_read = read(com_arduino, &ch_read, 1);
printf("size_read: %d || read: %d \n", size_read, ch_read);
ch_read = 0;
}
return 0;
} |
Le second programme me donne comme sortie :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
| /dev/ttyACM0 ouvert.
termios /dev/ttyACM0 obtenu.
Set Baudrate de termios réussis.
Set de termios /dev/ttyACM0 réussis.
Mise en place de la lecture...
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 8
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 8
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 8
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 8
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 8
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 8
size_read: 1 || read: 0
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 0
size_read: 1 || read: 4
size_read: 1 || read: 254
... |
Je ne comprends absolument pourquoi la lecture aussi "irrégulière", c'est à dire que j'obtiens parfois des suites de 0, parfois des 4 ou des 8, parfois des 254, ... Alors que je suis "censé" n'envoyer que des 0 et des 1.
Soit j'ai quelque chose de "faux", soit il y a une conversion faite par la platine Arduino pour le passage USB, auquel cas je n'ai pas trouvé l'information.. Bref.
Je patauge un peu, à vrai dire... Est-ce que quelqu'un aurait une petite idée pour me sortir de ce pétrin ?