Abonnez-vous à notre Chaîne YouTube "Devenir Ingénieur" pour bénéficier de nouveaux projets et suivre l'actualité du blog
Sommaire
Principe de fonctionnement
Dans ce petit projet je vais vous expliquez comment générer un signal sinusoïdal, sinus cardinal, signal triangulaire, carre et aléatoire à base du PIC16F877. J’ai utilisé un convertisseur numérique analogique DAC de 8 bits à base du réseau R/2R, amplificateur à gain variable et un filtre basse bas pour lisser le signal et restitué la bande de base.
Ce mini-projet permet de générer 5 signaux analogiques et un signal TOR avec une fréquence fixe (vous pouvez modifier la fréquence en agissant sur les paramètres du TimerO).
- Signal sinusoïdal (SIN)
- Signal sinus cardinal (sin(x)/x) (SINC)
- Signal triangulaire symétrique (double rompes) (TRIANG1)
- Signal triangulaire simple rampe (TRIANG2)
- Signal carré (SQRT)
- Signal de bruit aléatoire (RAND)
Les boutons poussoirs STOP et START sert à lancer les signaux, chaque foie que vous voulez modifier la forme d’onde, vous appuyer d’abord sur STOP puis vous sélectionnez votre signal 🙂 ensuite START.
Résaau R/2R – Convertisseur Numérique Analogique 8 bits (DAC)
La tension de sortie correspond à chaque bit (D0-D7) (VCC=5V) :
Ce qui constitue un système binaire pondéré à base 2, chaque bit valant 2 puissances n. Le théorème de superposition indique que nous pouvons obtenir toutes les tensions comprises entre 0V et VCC par pas de VCC/256.
Ce réseau constitué de 2 sortes de résistances seulement constitue donc un convertisseur Numérique/Analogique (DAC) dont les éléments ne requièrent pas une très grande précision. (Contrairement à des réseaux par additions de courants dont certaines résistances ont une valeur 128 fois plus élevée que d’autres).
Amplificateur de tension et filtre lisseur de tension
La bande passante & le gain du filtre en fonction des potentiomètres RV1 & RV2
Résultats des simulations pour les signaux : Signal sinusoïdal et triangulaires :
Code MikroC
#define Sin_Val 16
#define Pas_Sin 1 // Prescaller 1/16
// Les vecteurs de 16 valeurs des signaux
unsigned char SineWave[Sin_Val] = {128, 179 , 222 , 249, 254, 238, 202, 154 , 101 , 53 , 17 , 1 , 6, 33,76, 127};
unsigned char SinCWave[Sin_Val] = {38, 68, 73, 35, 0, 38, 152, 255, 255, 152 ,38 ,0,35, 73,68,38};
unsigned char TrigWave1[Sin_Val] = {5 , 36, 73, 109, 146, 182, 219, 255, 255 , 219, 182, 146, 109, 73, 36, 0};
unsigned char TrigWave2[Sin_Val] ={0 , 17 , 34, 51, 68, 85, 102, 119, 136, 153, 170 , 187, 204, 221, 238, 255};
unsigned char SqrtWare[Sin_Val] ={0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255};
unsigned char Wave[Sin_Val]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned short int count = 0;
unsigned short int CountFreq=0, ValTimer0=255; // La prochaine version intègre l'option de varier la fréquence
unsigned char DataPortB=0;
unsigned char i=0;
// Fonction pour stopper le Timer0 (Stop)
void Timer_Disable(void)
{
INTCON.GIE = 0;
INTCON.PEIE = 0;
INTCON = 0;
INTCON.TMR0IE = 0;
INTCON.TMR0IF = 0;
PORTC=0;
}
// Fonction pour lancer le signal (Start)
void Timer_Enable(void)
{
INTCON.GIE = 1;
INTCON.PEIE = 1;
INTCON.TMR0IE = 1;
INTCON.TMR0IF = 1;
}
// Routine d'interruption (Timer0 ou PORTB)
void interrupt()
{
if(INTCON.INTF==1)
{
INTCON.INTF=0;
Timer_Disable();
}
if (INTCON.TMR0IF ==1)
{
INTCON.TMR0IE=0;
INTCON.TMR0IF = 0;
PORTC=Wave[count];
count+=Pas_Sin;
count = count % Sin_Val;
INTCON.TMR0IE = 1;
TMR0 = ValTimer0;
}
}
void main()
{
TRISC = 0x00; // PORTC en sortie
PORTC = 0x00; // Initialisation du portc à 0
TRISB = 0xFF; // bits 0-6 en entrés , le bit7 en sortie
PORTB.F7=0;
// Configuration du TIMER0 pour une fréquence de 2MHZ max (8MHz Fosc)
OPTION_REG.T0CS = 0; // bit 5 Source d'horloge (0 interne)
OPTION_REG.T0SE = 0; // bit 4 Type de front 0 our front montenat
OPTION_REG.PSA = 0; // bit 3 Activer le prediviseur
OPTION_REG.PS2 = 0; // bits 2-0 PS2:PS0: (0 à 255) pré-diviseur
OPTION_REG.PS1 = 0;
OPTION_REG.PS0 = 0;
TMR0 = 0; // Initialisation du TIMER0 à 0 (fréquence max)
// Interrupt Registers
INTCON.RBIE=1;
INTCON.TMR0IE = 1;
INTCON.GIE = 1;
INTCON.INTE=1;
OPTION_REG.INTEDG=1;
INTCON.TMR0IF = 0;
INTCON.RBIF=0;
while(1)
{
DataPortB = PORTB;
switch(DataPortB)
{
// Start
case 0x02 :
Timer_Enable();
break;
// Signal Sine
case 0x04 :
for(i=0;i<Sin_Val; i++) Wave[i] = SineWave[i];
Timer_Enable();
break;
// Signal Sinus cardinal (sin(x)/x)
case 0x08 :
for(i=0;i<Sin_Val; i++) Wave[i] = SinCWave[i];
Timer_Enable();
break;
// Signal triangulaire symétrique
case 0x10 :
for(i=0;i<Sin_Val; i++) Wave[i] = TrigWave1[i];
Timer_Enable();
break;
// Signal triangulaire non smétrique
case 0x20 :
for(i=0;i<Sin_Val; i++) Wave[i] = TrigWave2[i];
Timer_Enable();
break;
// Signal carré
case 0x40 :
for(i=0;i<Sin_Val; i++) Wave[i] = SqrtWare[i];
Timer_Enable();
break;
// Signal aléatoire
case 0x80 :
for(i=0;i<Sin_Val; i++) Wave[i] = floor(255.0*(double)rand()/32767.0);
Timer_Enable();
break;
}
}
}
Télécharger gratuitement le fichier du projet générateur des signaux à base du PIC16877 à fréquence fixe & DAC 8 bits R/2R :
- Codes MikroC du projet générateur des signaux à base du PIC16F877
- Montage ISIS du projet générateur des signaux à base du PIC16F877
1 thought on “Projet électronique : Générateur des signaux à base du PIC16877 à fréquence fixe & DAC 8 bits R/2R”