« Micro contrôleurs AVR/Le langage C pour AVR » : différence entre les versions

Contenu supprimé Contenu ajouté
Ligne 102 :
=== Exercice 1 ===
Enlever les parenthèses des expressions suivantes lorsqu'elles peuvent être retirées.
<sourcesyntaxhighlight lang="C">
a=(25*12)+b;
if ((a>4) &&(b==18)) { }
((a>=6)&&(b<18))||(c!=18)
c=(a=(b+10));
</syntaxhighlight>
</source>
Évaluer toutes ces expressions pour a=6, b=18 et c=24
{{Solution|contenu=
<sourcesyntaxhighlight lang="c">
a = 25 * 12 + b;
if (a>4 && b==18) { } // impossible d'enlever les parenthèses restantes
a>=6 && b<18 || c!=18
c = a = b+10;
</syntaxhighlight>
</source>
Evaluation :
* a reçoit 318
Ligne 125 :
== Quelques types numériques ==
Les types du C AVR sont<ref>http://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html</ref> :
<sourcesyntaxhighlight lang="c">
unsigned char a;//8 bits, 0 to 255
signed char b; //8 bits, -128 to 127
Ligne 132 :
long e; //32 bits, -2147483648 to 2147483647
float f; //32 bits
</syntaxhighlight>
</source>
 
{{remarque|contenu=
Nous vous recommandons d'utiliser plutôt les types prédéfinis du compilateur C (du GNU)
<sourcesyntaxhighlight lang="c">
uint8_t a; //8 bits, 0 to 255
int8_t b; //8 bits, -128 to 127
Ligne 143 :
int32_t e; //32 bits, -2147483648 to 2147483647
float f; //32 bits
</syntaxhighlight>
</source>
 
Le gros avantage est que les tailles des types sont dans leurs noms :
Ligne 180 :
 
1° méthode pour positionner bit à bit :
<sourcesyntaxhighlight lang="c">
#define bit_set(var,bitno) ((var) |= 1 << (bitno))
#define bit_clr(var,bitno) ((var) &= ~(1 << (bitno)))
Ligne 186 :
bit_set(x,3); //now x=0b1001;
bit_clr(x,0); //now x=0b1000;*/
</syntaxhighlight>
</source>
2° méthode pour positionner plusieurs bits
<sourcesyntaxhighlight lang="c">
#define bits_on(var,mask) var |= mask
#define bits_off(var,mask) var &= ~0 ^ mask
Ligne 194 :
bits_on(x,0b0001); //now x=0b1011
bits_off(x,0b0011); //now x=0b1000 */
</syntaxhighlight>
</source>
 
=== Tests de bits en C ===
Ligne 205 :
Cette valeur prédéfinie est égale au masque lorsqu'on cherche à savoir si c’est un 1 ou à 0 partout dans le cas contraire.
Le test de gauche dans la figure ci-dessus peut donc s'écrire :
<sourcesyntaxhighlight lang="c">
// unsigned char Reg;
if ((Reg & 0x40) == 0x40) { //E.B. vraie si bit B6 à 1
...
}
</syntaxhighlight>
</source>
tandis que le test de droite s'écrit quant à lui
<sourcesyntaxhighlight lang="c">
// unsigned char Reg;
if ((Reg & 0x08) == 0x00) { //E.B. vraie si bit B3 à 0
...
}
</syntaxhighlight>
</source>
Il n’est pas possible de supprimer les parenthèses dans les deux programmes ci-dessus.
 
==== Utilisation d'une macro ====
Les tests d'un bit particulier en C peuvent aussi être réalisés de la manière suivante (http://www.microchipc.com/HiTechCFAQ/index.php)
<sourcesyntaxhighlight lang="c">
x=0b1000; //decimal 8 or hexadecimal 0x8
if (testbit_on(x,3)) a(); else b(); //function a() gets executed
Ligne 228 :
if (!testbit_on(x,0)) b(); //function b() gets executed
#define testbit_on(data,bitno) ((data>>bitno)&0x01)
</syntaxhighlight>
</source>
 
 
Ligne 267 :
* mettre à 1 les bits b0 et b7 et à 0 les bits b3 et b4
{{Solution|contenu=
<sourcesyntaxhighlight lang="c">
signed char p1;
p1 = p1 | 0x04; // mettre à 1 le bit b2
Ligne 276 :
p1 = p1 & 0xFE | 0x04 ; // mettre à 1 le bit b2 et à 0 le bit b0
p1 = p1 & 0xE7 | 0x81 ; // mettre à 1 les bits b0 et b7 et à 0 les bits b3 et b4
</syntaxhighlight>
</source>
}}
 
Ligne 282 :
Refaire l'exercice 2 en utilisant la macro "_BV" du compilateur C.
{{Solution|contenu=
<sourcesyntaxhighlight lang="c">
signed char p1;
p1 = p1 | _BV(2); // mettre à 1 le bit b2
Ligne 291 :
p1 = p1 & ~_BV(0) | _BV(2) ; // mettre à 1 le bit b2 et à 0 le bit b0
p1 = p1 & ~(_BV(3)|_BV(4)) | (_BV(0) | _BV(7)) ; // mettre à 1 les bits b0 et b7 et à 0 les bits b3 et b4
</syntaxhighlight>
</source>
}}
 
== Utiliser les registres de l'AVR (ATMegaXXX) en C ==
L'idéal, pour une écriture facile en langage C, serait de pouvoir écrire :
<sourcesyntaxhighlight lang="c">
// affectation d'une valeur dans un registre :
PORTB = val;
</syntaxhighlight>
</source>
qui pourrait mettre directement la valeur contenue dans la variable val dans un registre appelé PORTB. Pour cela, il faut que le compilateur C (gcc pour nous) connaisse le mot PORTB. En général, ce sera le cas si vous mettez l'entête
<sourcesyntaxhighlight lang="c">
#include <avr/io.h>
</syntaxhighlight>
</source>
en tout début de votre programme. Mais qu'en est-il pour les bits des registres ?
 
Ligne 310 :
=== Exemple de fichier d'en-tête pour gcc ===
Pour illustrer les questions de la section précédente de manière un peu plus concrète, voici un exemple partiel de fichier d'entête :
<sourcesyntaxhighlight lang="c">
/* Port D */
#define PIND _SFR_IO8(0x10)
Ligne 336 :
#define PB0 0
...
</syntaxhighlight>
</source>
Essayez de distinguer la définition d'un registre dans la première partie de la définition d'un bit dans la deuxième partie !
 
=== Les possibilités pour atteindre un bit particulier ===
Voici à travers un exemple comment accéder à un bit particulier pour le registre TWAR. On commence par présenter le fichier d'entête :
<sourcesyntaxhighlight lang="c">
....
/* TWAR */
Ligne 353 :
#define TWGCE 0
...
</syntaxhighlight>
</source>
Voici maintenant une utilisation :
<sourcesyntaxhighlight lang="c">
void main( void) {
....
Ligne 369 :
 
}
</syntaxhighlight>
</source>
=== Exercice 4 ===
Soit le fichier d'entête :
<sourcesyntaxhighlight lang = c>
/* TWCR */
#define TWINT 7
Ligne 382 :
/* bit 1 reserved (TWI_TST?) */
#define TWIE 0
</syntaxhighlight>
</source>
 
1°) Dessiner le registre correspondant
Ligne 395 :
 
Remarque : il existe une autre manière de faire ces mises à un et mises à 0 qui utilisent une macro « _BV » :
<sourcesyntaxhighlight lang="c">
void main( void) {
....
Ligne 407 :
}
</syntaxhighlight>
</source>
 
=== Exercice 5 ===
Comment peut-on utiliser la macro « _BV » pour mettre à 0 plusieurs bits à la fois  ?
 
== Annexe I : Le GNU C ==
Ligne 462 :
| '''_BV(x)'''
| positionne un bit spécifique
| <sourcesyntaxhighlight lang="C">char result = _BV(PINA6); // met 64 dans result</sourcesyntaxhighlight>
|-
| '''void sbi (uint8_t port, uint8_t bit)'''
| positionne un bit spécifique à 1
| <sourcesyntaxhighlight lang="C">sbi (PORTB, 3); //#define PORTB 0x18
sbi (PORTB, PINA3); </sourcesyntaxhighlight>
|-
| '''void cbi (uint8_t port, uint8_t bit)'''
| positionne un bit spécifique à 0
|<sourcesyntaxhighlight lang="C">cbi (PORTB, 3); //#define PORTB 0x18
cbi (PORTB, PINA3);</sourcesyntaxhighlight>
|-
| '''uint8_t bit_is_set (uint8_t port, uint8_t bit);'''
| teste si un bit spécifique est à 1
|<sourcesyntaxhighlight lang="C">//#define PINB 0x16
uint8_t result = bit_is_set (PINB, PINB3);</sourcesyntaxhighlight>
|-
| '''uint8_t bit_is_clear (uint8_t port, uint8_t bit);'''
| teste si un bit spécifique est à 0
|<sourcesyntaxhighlight lang="C">//#define PINB 0x16
uint8_t result = bit_is_clear (PINB, PINB3);</sourcesyntaxhighlight>
|-
| '''uint8_t inp (uint8_t port);'''
| lit un registre spécifique et retourne le résultat
|<sourcesyntaxhighlight lang="C">//#define SREG 0x3F
uint8_t res = inp (SREG);</sourcesyntaxhighlight>
|-
| '''uint16_t __inw (uint8_t port);'''
| lit un registre spécifique 16 bits et retourne le résultat
|<sourcesyntaxhighlight lang="C">//#define TCNT1 0x2C
uint16_t res = __inw (TCNT1);</sourcesyntaxhighlight>
|-
| '''uint16_t __inw_atomic (uint8_t port);'''
| lit un registre spécifique 16 bits et retourne le résultat sans interruption possible
|<sourcesyntaxhighlight lang="C">//#define TCNT1 0x2C
uint16_t res = __inw (TCNT1);</sourcesyntaxhighlight>
|-
| '''outp (uint8_t val, uint8_t port);'''
| sort une valeur spécifique sur un port spécifique
|<sourcesyntaxhighlight lang="C">//#define PORTB 0x18
outp(0xFF, PORTB);</sourcesyntaxhighlight>
|-
| '''__outw (uint16_t val, uint8_t port);'''
| sort une valeur spécifique 16 bits sur un port spécifique
|<sourcesyntaxhighlight lang="C">//#define OCR1A 0x2A
__outw(0xAAAA, OCR1A);</sourcesyntaxhighlight>
|-
| '''__outw_atomic (uint16_t val, uint8_t port);'''
| sort une valeur spécifique 16 bits sur un port spécifique sans interruption
|<sourcesyntaxhighlight lang="C">//#define OCR1A 0x0A
__outw_atomic(0xAAAA, OCR1A);</sourcesyntaxhighlight>
|}