Salut,
Ma petite contribution de Noël : un petit programme très simple qui montre comment faire l'effet de "goutte d'eau" qui tombe qu'on voit sur les guirlandes à led de nos jours. (effet de trainée avec luminosité qui diminue par variation logicielle du taux de PWM dans la table)
Il peut bien sûr facilement être amélioré pour créer des choses plus sophistiquées.
Sa particularité : il n'utilise AUCUN cycle processeur
L'allumage des 8 leds est fait par transfert DMA de la FLASH vers le PORTA sans aucune exécution d'instructions.
Plateforme utilisée : EXPLORER16 avec un module processeur PIC32MX360F512L.
C'est mon premier petit programme entièrement développé sous la version beta de MPLAB X dont l'éditeur est un régal vis à vis de MPLAB v8.60
Bon Noël à tousCode:/********************************************************************* * * Effet "goutte d'eau" qui tombe avec variation du taux d'éclairage de 8 LEDS * Cet exemple montre comment transférer une table de la FLASH vers un port * sans utiliser un seul cycle du PIC32 (voir boucle while vide et pas de * programme d'interruption grâce à l'utilisation d'un canal de DMA) * Le transfert DMA est déclenché par une demande d'interruption du Timer23. * quand les transferts sont terminés le canal se réarme automatiquement * Platforme utilisée - Explorer16 avec PIC32MX360F512L * * Resources utilisées: * Timer 2 et Timer 3 * DMA canal 0 * Le PORTA * * Note pour la carte EXPLORER16 * PORTA broches RA0, RA1, RA4, RA5 non disponible en mode release à cause * du multiplexage des broches du JTAG. * En mode Debugger (debug) ou Programmer (release) il suffit de désactiver le * port JTAG en utilisant la fonction mJTAGPortEnable(0); * ********************************************************************/ #include <plib.h> /* PIC32 peripheral library */ // Bits de configuration pour horloge à 80MHz #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_2 #pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1 #pragma config FWDTEN = OFF, FSOSCEN = OFF, IESO = OFF, OSCIOFNC = OFF #define SYS_FREQ 80000000 // frequence de fonctionnement #define LED_BLINK_RATE 100 // période de resfresh LED en ms // Tableau des patterns des LEDs (goutte d'eau qui tombe sur 8 leds // Limiter le tableau à 256 octets : taille maximum de transfert du DMA static const unsigned char LED_pattern[15][8]= { {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00}, {0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x40,0x00}, {0xE0,0xE0,0xE0,0xE0,0xE0,0x60,0x20,0x00}, {0xF0,0xF0,0xF0,0xF0,0x70,0x30,0x10,0x00}, {0xF8,0xF8,0xF8,0x78,0x38,0x18,0x08,0x00}, {0xFC,0xFC,0x7C,0x3C,0x1C,0x0C,0x04,0x00}, {0xFE,0x7E,0x3E,0x1E,0x0E,0x06,0x02,0x00}, {0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00}, {0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00}, {0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00}, {0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00}, {0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00}, {0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00}, {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }; int main(void) { DDPCONbits.JTAGEN = 0; // désactiver le port JTAG sur EXPLORER16 int dmaChn=0; // Selectionner le canal DMA 0 // Initialiser le PORTA en sortie pour 8 leds mPORTASetPinsDigitalOut(0xFF); // PORTA en sortie (EXPLORER16) mPORTAClearBits(0xFF); // Eteindre les LEDs (EXPLORER16) // Initialiser le canal de DMA 0, priorité 0, mode par défaut // Autoriser le mode AUTO qui réarme automatiquement le canal de DMA à la fin DmaChnOpen(dmaChn, 0, DMA_OPEN_DEFAULT|DMA_OPEN_AUTO); // Initialiser les paramètres de transfert : // Adresses source & destination, taille source et destination, // et le nombre d'octets par event DmaChnSetTxfer(dmaChn, LED_pattern, (void*)&LATA, sizeof(LED_pattern), 1, 1); // Initialiser la condition de trigger du canal de DMA 0 // Utilisation des Timer2 + Timer3 (Timer3 déclenche le transfert DMA 0) DmaChnSetEventControl(dmaChn, DMA_EV_START_IRQ(_TIMER_3_IRQ)); // Autoriser le canal de DMA sélectionné DmaChnEnable(dmaChn); // Lire la fréquence à laquelle le bus périphérique fonctionne int pbFreq=SYS_FREQ/(1<<mOSCGetPBDIV()); // Initialiser les Timer2 et Timer3 (Le Timer 2 controle les Timer2+3) OpenTimer23(T2_ON | T2_SOURCE_INT | T2_PS_1_1, (pbFreq/10000)*LED_BLINK_RATE); while(1) { // Le DMA s'occupe de tout. Aucune interruption // 100% de la bande passante du CPU reste disponible } }
a+
-----