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 : 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
#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>

#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0x01 << (x))
#define LONGBIT(x) ((unsigned long)0x00000001 << (x))

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]; //__attribute__((section (".eeprom"))); // 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)
{
TCNT1 = 0xFFFE;			// charge le compteur à une valeur proche pour la mesure
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,PN(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