#include <avr/io.h> int main (void) { DDRB = 0xFF; //Met le port B en sortie PORTB = 0x0F; //Met les 4 bit de poids faible à 1 et les 4 bits de poids fort à 0 DDRC = 0x00; //Met le port C en entrée asm volatile("nop;"); //Necessaire pour la synchronisation lors de la lecture d'une pin - Voir datasheet : I/O Port-Reading the Pin Value PORTB = PINC; //Copie les niveaux logique du port C sur le port B return 0; }
Remarque : DDRx indique la direction de chaque pin (1 : sortie, 0 : entrée) , PORTx sert de registre pour fixer les niveaux logiques en sortie, PINx sert à lire les niveaux logiques en entrée.
La valeur de PINC doit être fixée manuellement avant que l'instruction PORTB = PINC; ne soit exécutée.
#include <avr/io.h> int main (void) { DDRB = 0xFF; //Met le port B en sortie PORTB |=(1<<1)|(1<<3)|(1<<5)|(1<<7); //Met les bits 1,3,5,7 à l'état haut PORTB &=~((1<<3)|(1<<5)); //Met les bits 3 et 5 à l'état bas DDRB &=~((1<<3)|(1<<5)); //Met les bits 3 et 5 en entrée return 1; }
Quand vous faites : PORTB |= X vous faites un OU logique entre X et PORTB ce qui permet de ne pas influer sur l'état précédent des bits de PORTB qui ne sont pas modifiés.
PORTB = 0x0F; // Soit en binaire 0b00001111 PORTB |=(1<<1)|(1<<3)|(1<<5)|(1<<7); //Met les bits 1,3,5,7 à l'état haut
PORTB correspondra à la valeur binaire 0b10101111, les bits 0 et 2 n'ont pas étaient modifiés. Si par contre vous faites :
PORTB = 0x0F; // Soit en binaire 0b00001111 PORTB =(1<<1)|(1<<3)|(1<<5)|(1<<7); //Met les bits 1,3,5,7 à l'état haut mais met aussi tous les autres bits à 0
PORTB correspondra à la valeur binaire 0b10101010, les bits 0 et 2 ne sont pas conservés mais ca vous fait une instruction en assembleur en moins.
Même principe pour “&=”.
#include <avr/io.h> unsigned char port; // Type unsigned char donc sur 8bits comme un port du µC int main (void) { DDRB = 0xFF; //Met le port B en sortie port=1+2; PORTB = port; return 1; }
Vous pouvez aussi utiliser _BV() pour mettre à l'état haut un bit particulier.
ex : _BV(3) est totalement equivalent à 1«3
En regardant le code en assembleur on voit bien qu'il n'y a aucune différence :
: PORTB |= _BV(3); //Met le bit 3 à l'état haut +00000069: 91800038 LDS R24,0x0038 Load direct from data space +0000006B: 6088 ORI R24,0x08 Logical OR with immediate +0000006C: 93800038 STS 0x0038,R24 Store direct to data space
: PORTB |= (1<<3); //Met le bit 3 à l'état haut +00000069: 91800038 LDS R24,0x0038 Load direct from data space +0000006B: 6088 ORI R24,0x08 Logical OR with immediatespace +0000006C: 93800038 STS 0x0038,R24 Store direct to data
#include <avr/io.h> int main (void) { DDRB = 0xFF; //Met le port B en sortie PORTB |= _BV(1)|_BV(3)|_BV(5)|_BV(7); //Met les bits 1,3,5,7 à l'état haut PORTB &=~(_BV(3)|_BV(5)); //Met les bits 3 et 5 à l'état bas return 1; }
Cette petite bibliothèque est à télécharger.
Son utilisation va permettre de définir un bit d'un port
ex : #define LED3 SBIT (PORTA, 3)
ex : cette ligne définit que la LED numéro 3 est reliée au bit 3 du registre PORTA
ex : #define BP2 SBIT (PIND, 2)
ex : cette ligne définit que le bouton poussoir numéro 2 est relié au bit 2 du registre PIND
#include <util/sbit.h> #define LED3 sbit (PORTA, 3) #define BP2 sbit (PIND, 2) int main (void) { DDRA = 0xFF; //Met le port A en sortie DDRD = 0x00; LED3 =1; //Allume la led 3 // teste BP2 et éteint la LED 3 if (BP2 == 1) { LED3 =0; } return 1; }