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 PIC12F683 intègre un module CCP1 (Capture/Compare/PWM) capable de générer un PWM matériel, sans “charger” le processeur.
Sur le PIC12F683, le PWM matériel CCP1 sort généralement sur la broche GP2 (fonction alternative CCP1). Pense à mettre la broche en sortie via TRISIO et à configurer le mode analogique si besoin.
| 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 |
| TRISIO | Direction des broches (GP2 en sortie) |
| ANSEL | Mode analogique/numérique (selon usage) |
But : sortir un PWM sur GP2/CCP1 et faire un effet “respiration” (fade in / fade out).
/* * Projet : PWM matériel CCP1 sur PIC12F683 (GP2) * Auteur : JLQDeveloppement * Compilateur : XC8 */ #include <xc.h> #define _XTAL_FREQ 4000000 // (Optionnel) Ajoute tes #pragma config selon ton projet static void initPWM_CCP1(void) { // Oscillateur interne 4 MHz (exemple) OSCCON = 0b01100000; // Désactiver l'analogique si tu veux 100% numérique (recommandé ici) ANSEL = 0; // GP2 en sortie (CCP1), le reste selon besoin // TRISIO: 1 = entrée, 0 = sortie TRISIObits.TRISIO2 = 0; // GP2 sortie // 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; // 8 bits MSB CCP1CONbits.DC1B = 0; // 2 bits LSB // Activer CCP1 en PWM CCP1CONbits.CCP1M = 0b1100; // Timer2 ON, prescaler 1:4 T2CONbits.T2CKPS = 0b01; // 01 = 1:4 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; // 8 bits MSB CCP1CONbits.DC1B = duty & 0x03; // 2 bits LSB } 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.TRISIO2=0).ANSEL (souvent ANSEL=0 pour une LED).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.