#define SIGNAL_PIN 9 // Broche où le signal carré sera généré
volatile unsigned int ocr1a_value = 79; // Valeur initiale d'OCR1A pour 10 kHz
volatile unsigned int presDivT1[6] = {0, 1, 8, 64, 256, 1024}; // 0=stop 1=frequence/1 2=freq/8 3=freq/64 4=freq/256 5=freq/1024
volatile unsigned int indexpresDivT1 = 1;
unsigned long new_ocr1a_value;
unsigned long counter = 0;
unsigned long previousMillis = 0;
const unsigned long interval = 1000; // Intervalle de 1 seconde
void setup() {//************************************************SETUP***************************************************************
pinMode(SIGNAL_PIN, OUTPUT);
Serial.begin(9600); // Initialiser la communication série à 9600 bps
delay(3000);
noInterrupts(); // Désactiver les interruptions
// Configurer le timer 1
TCCR1A = 0; // Mettre le registre de contrôle A à 0
TCCR1B = 1;//indexpresDivT1; // Mettre prescaler timer1 à 1
TCNT1 = 0; // Initialiser le compteur à 0
bitSet(TCCR1B, WGM12); // Mode CTC (Clear Timer on Compare Match)
bitSet(TIMSK1, OCIE1A); // Activer l'interruption sur compare match
bitSet(TCCR1B, CS10); // Démarrer le timer avec un prescaler de 1
OCR1A = ocr1a_value; // Initialiser OCR1A
interrupts(); // Activer les interruptions
Serial.println("Entrer la fréquence :");
}
ISR(TIMER1_COMPA_vect,ISR_NAKED) {//**********************************Interruption Timer1***********************************************
//datasheet :13.2.2 Toggling the Pin
// Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the SBI instruction
// can be used to toggle one single bit in a port
//appel 7 cycles
asm volatile("sbi 3,1"); //sbi=>Set bit in I/O register , 3 => registre PINB , 2 => PINB1=pin 9 2 cycles (sbi ici inverse l'etat pin9)
reti(); //4 cycles
}
//a la sortie 13 cycles =0.812us
void loop() {//*******************************************************Loop****************************************************************
counter++; //sans interruption = 178500
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) { //en 1s 16000000 cycles
previousMillis = currentMillis;
Serial.print("Charge de l'interruption : ");
Serial.print(100-(8958/(16000000/counter)));
Serial.println("%");
counter = 0;
}
if (Serial.available() > 0) { // Vérifier s'il y a une nouvelle entrée série
unsigned long frequency = Serial.parseInt();
indexpresDivT1 = 1;
if (frequency > 0) {
counter=0;
new_ocr1a_value = (16000000 / (presDivT1[indexpresDivT1] * 2 * frequency)) - 1; // Calculer la nouvelle valeur de OCR1A
if (new_ocr1a_value <= 65535) { // S'assurer que la valeur est dans les limites de OCR1A
noInterrupts();
TCCR1A = 0; // Mettre le registre de contrôle A à 0
TCCR1B = 1; // Mettre prescaler timer1 à 1
bitSet(TCCR1B, WGM12); // Mode CTC (Clear Timer on Compare Match)
bitSet(TIMSK1, OCIE1A); // Activer l'interruption sur compare match
TCNT1 = 0; // Initialiser le compteur à 0
OCR1A = new_ocr1a_value; // Mettre à jour OCR1A avec la nouvelle valeur
interrupts();
Serial.print("Nouvelle fréquence : ");
Serial.print(frequency);
Serial.print(" Hz fréquence la plus proche : ");
Serial.print(16000000 / (presDivT1[indexpresDivT1]* 2 * (new_ocr1a_value + 1)));
Serial.print(" Hz, OCR1A = ");
Serial.println(new_ocr1a_value);
}
else {
Serial.println("Erreur : La fréquence est trop basse pour être gérée par le timer avec prescaler 1.");
for (indexpresDivT1 = 2; indexpresDivT1 < 6; indexpresDivT1++) { // Vérifier les autres prescalers si nécessaire
new_ocr1a_value = (16000000 / (presDivT1[indexpresDivT1] * 2 * frequency)) - 1;
if (new_ocr1a_value <= 65535) {
noInterrupts();
TCCR1A = 0; // Mettre le registre de contrôle A à 0
TCCR1B = indexpresDivT1; // Mettre le nouveau prescaler
bitSet(TCCR1B, WGM12); // Mode CTC (Clear Timer on Compare Match)
bitSet(TIMSK1, OCIE1A); // Activer l'interruption sur compare match
TCNT1 = 0; // Initialiser le compteur à 0
OCR1A = new_ocr1a_value; // Mettre à jour OCR1A avec la nouvelle valeur
interrupts();
Serial.print("Nouvelle fréquence : ");
Serial.print(frequency);
Serial.print(" Hz fréquence la plus proche : ");
Serial.print(16000000 / (presDivT1[indexpresDivT1] * 2 * (new_ocr1a_value + 1)));
Serial.print(" Hz, OCR1A = ");
Serial.print(new_ocr1a_value);
Serial.print(", prescaler = ");
Serial.println(TCCR1B);
break;
}
}
if (indexpresDivT1 == 6) {
Serial.println("Erreur : La fréquence est trop basse pour être gérée par le timer.");
}
}
} else {
Serial.println("Erreur : Entrée invalide.");
}
}
}