2017-06-10 3 views
-1

J'utilise un ATmega328. Je fais actuellement plusieurs mesures en utilisant l'ADC 10 bits. Je voudrais stocker les valeurs qu'il convertit en variables afin de pouvoir fonctionner avec elles. Par exemple:AVR in C - Enregistrement de la valeur du registre dans la variable

int a; 
(...) 
ADMUX = 0b01000011; //Vref = 5V, ADC3 
ADCSRA |= (1<<ADSC); //Starts conversion 
while(!(ADCSRA & (1<<ADIF))); //Wait until it finishes 
ADCSRA |= (1<<ADIF); //Clear flag 

Supposons que l'ADC stocké dans la valeur 576ADCH:ADCL. Est-il possible de réaliser, d'une manière ou d'une autre, la variable a pour prendre cette même valeur? (c'est-à-dire a=576;).

Répondre

1

Le complet résultat Registre 16 bits should be accessible as such:

a = ADC; 

Mais si vous voulez lire les deux parties manuellement, puis

a = ADCL; 
a |= ADCH << 8; 

qui doit être fait dans deux états distincts à la force ADCH à lire en dernier. Les modules d'E/S ont un registre temporaire pour maintenir l'octet haut, empêchant le module lui-même de corrompre la valeur lue s'il change la valeur du registre. (c'est-à-dire si l'ADC termine une autre conversion et stocke la nouvelle valeur.)

Si vous avez des interruptions qui accèdent au CAN (ou devez utiliser la valeur à a), vous devrez les désactiver pendant la durée de la access (cela vaut également pour a = ADC, car il est également compilé en plusieurs lectures de 8 bits).

+0

Ceci est susceptible de corruption. Voir la réponse ci-dessous. – TomServo

+0

@JLH, point. Notez cependant que le texte dans la note d'application va "Si la fonction d'interruption accède aux mêmes ressources, l'accès doit être fait une opération atomique". S'il n'y a pas d'interruptions qui accèdent à l'ADC, il n'y a pas de problème. – ilkkachu

+0

À partir du code OP, il n'est pas clair si un autre ADC - ou autre chose - pourrait être lancé pendant que celui-ci est stocké. Mieux vaut prévenir que guérir. – TomServo

1

La réponse ci-dessus est proche, vient encore un peu court sur la base des recommandations du fabricant de la puce. Pour être sûr, vous devez suivre les instructions de la référence faisant autorité ci-dessous.

Il suffit de désactiver les interruptions juste avant et les restaurer après:

unsigned int a; // 16-bit word 
// other code 
cli(); 
a = ADCL; 
a |= ADCH << 8; 
sei(); 

Chaque exemple dans cette référence du fabricant de puces suit ce modèle pour 16 bits atomique lit et écrit. Référence: AVR Application Note 072.

+0

* Une autre mesure ADC * ne peut pas arriver - Une fois que vous avez lu 'ADCL', l'AVR verrouille le registre ADC contre les changements du CAN jusqu'à ce que vous ayez lu ADCH. Voir le manuel. Pourquoi une routine de service d'interruption devrait être capable de corrompre la valeur 'a' à moins qu'elle ne m'échappe pour l'instant. Il ne devrait cependant pas essayer * d'utiliser * la valeur 'a' à moitié mise à jour. – tofro

+0

@tofro Assez vrai pour autant que cela se passe, mais à moins que nous voyions ** tout ** du code OP, nous ne pouvons pas savoir ce qui pourrait se passer d'autre. Je n'ai jamais, jamais mal tourné en suivant les instructions dans AVR072. – TomServo