Bien le bonjour
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):
Le programme sur le pc, lisant sur le port /dev/ttyACM0 (pc_main.c):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 second programme me donne comme sortie :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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; }
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 ...
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 ?
Partager