[C] Besoin d'aide pour un PIC

Résolu/Fermé
Chomp - 24 juin 2009 à 10:13
 imul - 19 nov. 2009 à 16:05
Bonjour à tous,

Pour un examen de programmation je dois réaliser un projet sur un PIC 16F84A. Mon PIC est constitué de 2 afficheurs 7 segments (RA1 et RA2), de 2 boutons poussoirs(RA4 et RA3), d'un buzzer (RA0) et a un quartz à 3.2768MHz.
Le but de ce projet est un petit métronome ayant une vitesse de base de 60bpm(battements par minute). A l'appui du bouton gauche (RA4) les bpm descendent de 60, à l'appui du bouton droite (RA3) ils montent de 60. A l'appui des deux le métronome fait vibrer le buzzer à la vitesse des bpm.

Ma question principale est : comment dois-je faire pour avoir une boucle qui joue les temps en fonction des bpm avec le timer sachant que j'utilise une sub recevant les bpm ?

Cela fait 1 jour que je suis dessus cette boucle sans succès, et la programmation C n'est pas mon fort.

Merci de votre aide, si vous avez besoin de plus de précisions n'hésitez pas.
A voir également:

10 réponses

mamiemando Messages postés 33394 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 novembre 2024 7 803
24 juin 2009 à 10:47
Quand tu dis que le métronome bat à 60bpm ça veut donc dire qu'il bippe 60 fois plus vite que ta fréquence d'horloge ?

Parce qu'en fait le C propose des méthodes comme sleep permettant de bloquer l'exécution un temps donné. Du coup je ne vois pas trop l'intérêt de l'horloge qui semple avoir une fréquence plus rapide que ton horloge (du coup difficile de ce caler dessus à part une fois / 60 beats). Ou quelque chose m'a échappé ?
0
Quand je parle de 60 bpm, cela veut dire qu'il va faire 60 battements par minute, soit 1 par seconde. La durée du battement ne devrait pour bien pas excéder 0.3s
0
Changement, j'ai trouvé ce que je voulais en gros, me manque juste une chose : le sleep.
J'ai regardé plusieurs posts sur différents forums et rien ne marche.
J'ai essayé avec Sleep() et sleep(), avec des secondes et des millisecondes, j'ai essayé avec delay mais il ne fait pas un temps correcte alors que l'erreur est de 0.1% soit disant. Sleep() n'est pas reconnu.
Compilateur utilisé CC5X.

L'erreur :

sleep(1000) : Extra parameter in function call (The number of parameters supplied in the call do not match the function definition)

Avez-vous une idée ?
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
24 juin 2009 à 14:18
Il faut trouver l'équivalent sur ton compilateur.
fait un grep (une recherche) sur tout les fichier .h fournis avec le compilateur
Par contre, je trouve ton incrément de 60 assez énorme, les tempo en musique varient généralement de 40 à 200 bpm, un incrément, décrément de 10 serait un peu mieux.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33394 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 novembre 2024 7 803
24 juin 2009 à 14:27
Truc que j'aimerais comprendre, quelle est ta fréquence d'horloge ? Tu dis que tu arrives à rattraper l'évènement "j'ai un bip d'horloge", j'imagine que tu passes dans une callback (une fonction appelée sur cet évènement) à chaque temps d'horloge ?
0
@Char Snipeur :
L'incrémentation et décrémentation de 60 est voulue, je n'ai pas besoin d'un truc énorme, 5 fréquences me suffisent.

@mamiemando
Ma fréquence d'horloge est dans le premier post : 3.2768MHz.
0
mamiemando Messages postés 33394 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 novembre 2024 7 803
24 juin 2009 à 14:41
Et pour la seconde partie de ma fonction, est ce que tu as un point d'entrée dans ton code C à chaque temps d'horloge ? Plus précisément, comment en tires-tu parti dans ton code C ?

Parce que manifestement ta fréquence d'horloge est très supérieure à celle du métronome. Il suffit donc d'ignorer le bon nombre de temps d'horloge pour que le métronome donne le bon tempo. Pour cela tu peux utiliser une variable statique.
0
Voici le code de ma sub :


void joue (unsigned int bpm){

OPTION = 0b11000111;
TMR0 = 0;
unsigned long i:16;
int frequence = 1;

while(1){

for(i=0;i<20;i++){
TMR0 = 0;
do {
RA0 = 1;
} while (TMR0 < frequence);

TMR0 = 0;
do{
RA0 = 0;
} while (TMR0 < frequence);
}

// ici le sleep en fonction des bpm

if (RA3 && RA4){
do{for(i=0;i<35000;i++);}
while(RA3 == 1 && RA4 == 1);
break;
} //if end

}//while end
} //void end

La première partie joue le son, la deuxième sert juste à sortir de cette sub pour retourner au main.
0
mamiemando Messages postés 33394 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 novembre 2024 7 803
24 juin 2009 à 21:16
Bon je suis désolée mais je ne suis pas sûre de comprends ton code. Si j'ai bien suivi les variables TMR0, RA0 etc... sont lue et écrite en parallèle par le programme C et le PIC.

Si j'ai bien compris TMR0 est un booleen dont on doit détecter les fronts montant pour détecter un battement d'horloge, RA0 est un booleen qui indique si le buzzer est actif ou non, RA3 et RA4 valent 1 si le bouton gauche ou droit est actif. La fonction joue() fait buzzer à la fréquence indiquée jusqu'à ce qu'une nouvelle fréquence soit spécifiée (RA3 et RA4 actifs simultanément).

Je suppose que tu testes pendant 35000 iterations que RA3 et RA4 sont simultanément pressés pour ne pas être perturbés par des parasites sur RA3 et RA4 ? (ce qui est un peu gênant car tu ne sais pas combien de temps tu vas bloquer le fil d'exécution et tu risques donc de ne pas sonner à la bonne fréquence !)

Dis-moi si je me trompe.

Avec le recul, je pense que tout l'intérêt du projet est justement d'utiliser sleep puisque sinon l'horloge ne sert à rien. Si je ne me suis pas craquée ça doit ressembler à ça :
void joue(int bpm){
    int TMRO;
    int nb_beat = 0;
    int ra3_and_ra4 = 0;

    // Le nombre de beats au bout du quel on l'on change le buzzer d'état
    int nb_beat_change = (60*327680)/(2*bpm);

    // Tant que RA3 et RA4 ne sont pas pressés simultanément pendant
    // 35 000 beats d'horloge, on continue à buzzer normalement.
    while(ra3_and_ra4 < 35000){

        // On attend que TMR0 soit à l'état bas.
        while(TMR0);

        // On attend que TMRO passe sur un front montant
        while(!TMRO);

        ++nb_beat;

        // On est sur un beat où il faut changer d'état
        // (multiple de nb_beat_change)
        if(!(nb_beat % nb_beat_change)) RA0 = !RA0;

        if(RA3 && RA4) ++ra3_and_ra4;
        else ra3_and_ra4 = 0;
    }
}

Avec cette méthode tu testes que ra3 et ra4 sont simultanément pressés pendant 35000 beats d'horloge. On fait une itération de while à chaque fois que TMRO passe de l'état bas à l'état haut (soit un beat d'horloge). Il faut ensuite faire une petite règle de trois pour compter le nombre de beat ou RA0 reste à l'état haut et à l'état bas. Si je ne me suis pas craquée, tout les "2*nb_beat_change" beat d'horloge, on a fait un beat à la bonne fréquence. A chaque fois qu'on atteint un nombre de beat d'horloge multiple de nb_beat_change, on sait que l'on doit changer l'état de RA0.

Je suis peut-être à côté de la plaque, je n'y connais pas grand chose en électronique, mais j'espère que ça t'aidera.

Bonne chance
0
ta commande Sleep ne marche pas car tu na pas du inclure la bonne bibliotheque :
il faut inclure : windows.h
0