Bonjour à tous,
je tourne en rond sur un problème que je n'arrive pas à résoudre.
le but du jeux est de déclencher une série de 14 mesures à une fréquence de 700Hz à la suite d'un "TOP Départ"
matériellement, j'ai un ATmega32 et j'utilise AVR Studio 6 pour mon programme en C que j'envoie avec l'interface USBAsp dans mon composant.
le signal de départ est le 50Hz du secteur remis en forme par transfo + AOP pour ne pas descendre sous les 0V ni dépasser les 5V et raccordé sur ADC0 (broche PA0). au signal original, j'ai mis un trigger de schmitt pour détecter le passage à 0 et donc débuter la série de mesure par interruption et raccordé sur INT0 (broche PD2)
voilà donc ce que donne l'oscillo pour la synchro des deux signaux :
l'idée pour le programme était :
une boucle d'attente du bon nombre de mesure
une fois OK, je bloque toutes le IT, affiche toutes les mesures sur l'écran, je réactive INT0 tout en bloquant le compteur
INT0 :
je bloque les IT,
je désactive INT0,
charge le compteur,
réactive les IT
active le compteur
Timer 1:
je recharge le compteur
je fais ma mesure que je met dans un tableau
j'incrémente le nombre de mesure
voilà donc le programme en C que j'ai fait :
Code:#ifndef F_CPU #define F_CPU 16000000UL #endif #include <avr/io.h> #include "u8g.h" #include <util/delay.h> #include <avr/interrupt.h> #include <stdlib.h> #include <stdio.h> u8g_t Ecran; #define FREQ_ECH 700UL // fréquence à la quelle on veut mesurer #define NB_ECH 14 // nombre d'échantillons à mesurer uint16_t TC1_VAL = (65535UL - F_CPU / FREQ_ECH); // valeur pour Timer 1 pour la mesure à la bonne fréquence volatile uint8_t nb_mesure = 0; // nb de mesure prise **** en volatile pour eviter bug compilateur **** uint8_t data[NB_ECH]; // valeurs mesurées void adc_init() { // AREF = AVcc ADMUX = (1<<REFS0)|(1<<ADLAR); // ADC Enable and prescaler of 16 ADCSRA = (1<<ADEN)|(1<<ADPS2); } uint8_t adc_read(uint8_t ch) // mesure sur 8 bits { // select the corresponding channel 0~7 // ANDing with ’7? will always keep the value // of ‘ch’ between 0 and 7 ch &= 0b00000111; // AND operation with 7 ADMUX = (ADMUX & 0xF8)|ch; // start single convertion // write ’1? to ADSC ADCSRA |= (1<<ADSC); // wait for conversion to complete // ADSC becomes ’0? again // till then, run loop continuously while(ADCSRA & (1<<ADSC)); return (ADCH); } ISR(TIMER1_OVF_vect) { TCNT1 = TC1_VAL; // recharge le compteur data[nb_mesure] = adc_read(0); // enregistre la mesure nb_mesure++; // incrémente le compteur de mesure } ISR(INT0_vect) { cli(); GICR = 0; // désactive INT0 TCNT1 = 0xFFFE; // charge le compteur à une valeur proche pour la mesure sei(); TCCR1B = _BV(CS10); // active le comptage a une fréquence horloge = F_CPU } int main(void) { uint8_t i = 0; for (i = 0; i < NB_ECH; i++) data[i] = 0; DDRB = _BV(PB1); PORTB |= _BV(PB1); //allume l'écran PORTD = 0b00000000; // config du port D DDRD = ~(1<<PD2); // PORTD en sortie sauf PD2 où se trouve INT0 GICR = 1<<INT0; // Active INT0 MCUCR = 1<<ISC01 | 1<<ISC00; // Trigger INT0 sur front montant TCCR1A = 0; TCCR1B = 0; // bloque le comptage a une fréquence horloge = 0 TIMSK = _BV(TOIE1); // autorise l'interruption d'overflow TCNT1 = 0; // met le competur à 0 u8g_InitSPI(&Ecran, &u8g_dev_st7920_128x64_sw_spi,P N(1,7),PN(1,5), PN(1,0), U8G_PIN_NONE, U8G_PIN_NONE); // init écran GLCD adc_init(); // init du convertisseur analogique / numérique sei(); // active les interruptions while(1) { // boucle d'attente while (nb_mesure >= NB_ECH) //si j'ai fait assez de mesure ... { cli(); // bloque les IT PORTD = 0; // eteint la LED indicatrice ce mesure u8g_FirstPage(&Ecran); do { for (i = 0; i < NB_ECH; i++) { u8g_DrawLine(&Ecran, 4*i, data[i]>>2,4*(i+1), data[i+1]>>2); } } while( u8g_NextPage(&Ecran) ); TCCR1B = 0; // desactive le timer 1 : prescaler = 0 GICR = 1<<INT0; // réactive l'interruption 0 nb_mesure = 0; // réinitialise les mesures PORTD |= 1<<PD3; sei(); // activation des interruptions } } }
le soucis c'est que les valeur affichées sont déphasées d'une série de mesure à l'autre ce qui, il me semble, ne devrait pas arriver avec ce programme. ça fait comme si INT0 comptais pour rien !!!!
je vous ai fait une petite video pour voir le résultat, ça peu aider à comprendre :
j'ai du faire une bourde quelque part mais où ???
je vous vois déjà venir : les fusibles sont mal configurés.
sans doute, voilà donc ma config :
Low Fuse : 0xEE
High Fuse : 0xCF
donc si j'ai bien compris la doc : pas de Jtag, et horloge réglé sur quartz > 1MHz
merci
-----