Contrôlez la luminosité et la vitesse avec un PWM matériel (CCP1 + Timer2)
Le PWM (Pulse Width Modulation — Modulation de Largeur d'Impulsion) consiste à faire varier le rapport cyclique d’un signal rectangulaire pour contrôler la puissance moyenne délivrée à un composant.
Au lieu de fournir une tension continue (ex : 2,5V), le PIC alterne rapidement entre 0V et 5V. Avec un rapport cyclique de 50%, la charge reçoit en moyenne ~2,5V. En faisant varier ce rapport de 0% à 100%, on contrôle la luminosité d'une LED ou la vitesse d'un moteur.
Le PIC16F877A intègre des modules CCP (Capture/Compare/PWM) capables de générer un PWM matériel, sans charger inutilement le processeur.
Sur le PIC16F877A, le PWM matériel CCP1 sort généralement sur la broche RC2/CCP1. Pense à mettre la broche en sortie via TRISC et à configurer correctement Timer2.
| Registre | Rôle |
|---|---|
| CCP1CON | Mode CCP1 (PWM = 0b00001100) + 2 bits LSB du duty |
| PR2 | Période PWM (Timer2) |
| CCPR1L | Duty cycle (8 bits MSB) |
| T2CON | Prescaler / activation de Timer2 |
| TRISC | Direction des broches (RC2 en sortie) |
| ADCON1 | Configuration analogique / numérique (utile selon le montage) |
TRISCbits.TRISC2 = 0;But : sortir un PWM sur RC2/CCP1 et faire un effet “respiration” (fade in / fade out).
/* * Projet : PWM matériel CCP1 sur PIC16F877A (RC2) * Auteur : JLQDeveloppement * Compilateur : XC8 */ #include <xc.h> #define _XTAL_FREQ 4000000 // (Optionnel) Ajoute tes #pragma config selon ton projet static void initPWM_CCP1(void) { // Configure les broches analogiques si nécessaire ADCON1 = 0x06; // RC2 en sortie (broche CCP1) TRISCbits.TRISC2 = 0; // Période PWM via Timer2 // Exemple : PR2 = 249, prescaler 1:4 -> ~1kHz à Fosc=4MHz PR2 = 249; // Duty initial ~50% (10 bits : 0..1023) CCPR1L = 125; CCP1CONbits.DC1B = 0; // Activer CCP1 en mode PWM CCP1CONbits.CCP1M = 0b1100; // Timer2 ON, prescaler 1:4 T2CONbits.T2CKPS = 0b01; T2CONbits.TMR2ON = 1; // Petite attente pour stabiliser Timer2/PWM __delay_ms(10); } static void setDuty10bits(unsigned int duty) { // duty : 0..1023 (10 bits) if(duty > 1023) duty = 1023; CCPR1L = duty >> 2; CCP1CONbits.DC1B = duty & 0x03; } void main(void) { initPWM_CCP1(); unsigned int i; while(1) { // Fade in for(i = 0; i <= 1023; i += 6) { setDuty10bits(i); __delay_ms(5); } // Fade out for(i = 1023; i > 0; i -= 6) { setDuty10bits(i); __delay_ms(5); } } }
TMR2ON=1, pas de PWM.TRISC2=0).PR2 et le prescaler.FPWM = Fosc / (4 × Prescaler × (PR2 + 1))
Exemple : Fosc = 4 MHz, Prescaler = 4, PR2 = 249 :
F = 4 000 000 / (4 × 4 × 250) = 1000 Hz (1 kHz)
Le rapport cyclique est sur 10 bits (0–1023), soit 1024 niveaux de réglage.