Mio figlio frequenta l' universita' e studia progetto grafico e virtuale (traditore


Ho cercato quindi di realizzare un programma piu' semplice possibile per gestire un certo numero di LEDs (io ne ho usati 3 ma potrebbero essere molti di piu'). La semplicita' e' un requisito necessario poiche dovra' poi spiegare il programma all' esame. Non e' digiuno di programmazione ne di elettronica perche' e' un perito elettronico che poi (traditore

Quindi non ho usato timers ed ho realizzato il classico loop infinito sperando che il micro fosse abbastanza veloce. E devo dire che lo e' alla grande! E' andato oltre le mie aspettative. Il programma e' questo:
- Codice: Seleziona tutto
// Definizione dei bit di configurazione della MPU
#pragma config FOSC = IRC // Internal RC oscillator
#pragma config PLLEN = ON // 4 X PLL Enable bit
#pragma config PCLKEN = OFF // Primary Clock Enable Bit
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit
#pragma config PWRTEN = ON // Power-up Timer Enable bit
#pragma config BOREN = ON // Brown-out Reset Enable bits
#pragma config BORV = 19 // Brown-out Voltage (1,9V)
#pragma config WDTEN = OFF // Watchdog Timer Enable bit
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits
#pragma config MCLRE = ON // MCLR Pin Enable bit
#pragma config HFOFST = OFF // HFINTOSC Fast Start-up bit (The system clock is held off until the HFINTOSC is stable)
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit
#pragma config LVP = OFF // Single-Supply ICSP Enable bit
#pragma config XINST = OFF // Extended Instruction Set Enable bit
#pragma config CP0 = OFF // Code Protection bit
#pragma config CP1 = OFF // Code Protection bit
#pragma config CPB = OFF // Boot Block Code Protection bit
#pragma config WRT0 = OFF // Write Protection bit
#pragma config WRT1 = OFF // Write Protection bit
#pragma config WRTB = OFF // Boot Block Write Protection bit
#pragma config WRTC = OFF // Configuration Register Write Protection bit
#pragma config EBTR0 = OFF // Table Read Protection bit
#pragma config EBTR1 = OFF // Table Read Protection bit
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit
// file di definizioni della MPU
#include <p18f14k22.h>
// Defines porte di uscita per i LEDs
// LED rosso
#define LED_R LATCbits.LATC0
#define LED_R_DIR TRISCbits.TRISC0
// LED verde
#define LED_G LATCbits.LATC1
#define LED_G_DIR TRISCbits.TRISC1
// LED blu
#define LED_B LATCbits.LATC2
#define LED_B_DIR TRISCbits.TRISC2
unsigned char pos_pwm;
unsigned char liv_R,liv_G,liv_B; // livelli da 0 a 255 dei tre colori
unsigned short pos_spettro; // posizione da 0 a 767 nello spettro
char base_tempi; // bit attivato al completamento di un' onda
/******************************************************************************/
/* set_spettro */
/* calcola la configurazione dei tre colori in base alla posizione nello */
/* spettro */
/******************************************************************************/
void set_spettro(void)
{
short p;
p = pos_spettro;
if (p<256)
{
liv_R = 255 - p;
liv_G = p;
liv_B = 0;
}
else if (p<512)
{
p &= 0xff;
liv_R = 0;
liv_G = 255 - p;
liv_B = p;
}
else
{
p &= 0xff;
liv_R = p;
liv_G = 0;
liv_B = 255 - p;
}
}
/******************************************************************************/
/* inc_spettro */
/* incrementa la posizione dello spettro in modo circolare */
/******************************************************************************/
void inc_spettro(void)
{
if (pos_spettro != 767) pos_spettro++; else pos_spettro = 0;
}
/******************************************************************************/
/* inc_spettro */
/* decrementa la posizione dello spettro in modo circolare */
/******************************************************************************/
void dec_spettro(void)
{
if (pos_spettro) pos_spettro--; else pos_spettro = 767;
}
/******************************************************************************/
/* main function */
/* */
/******************************************************************************/
void main (void)
{
// inizializza le uscite dei LEDS
LED_R = 0;
LED_R_DIR = 0;
LED_G = 0;
LED_G_DIR = 0;
LED_B = 0;
LED_B_DIR = 0;
OSCCON |= 0x70; // seleziona clock a 16 MHz
// prova
liv_R = 255;
liv_G = 255;
liv_B = 255;
base_tempi = 0;
pos_spettro = 0;
while(1)
{
// gestione forme d' onda PWM
if (pos_pwm < liv_R) LED_R = 1; else LED_R = 0;
if (pos_pwm < liv_G) LED_G = 1; else LED_G = 0;
if (pos_pwm < liv_B) LED_B = 1; else LED_B = 0;
pos_pwm++;
if (!pos_pwm)
{
// accensione impulso di base tempi al completamento dell' onda
base_tempi = 1;;
}
// programma di dissolvenza incrociata
if (base_tempi)
{
base_tempi = 0;
inc_spettro();
set_spettro();
}
}
}
La regolazione PWM si ottiene tramite la variabile pos_pwm che va da 0 a 255. Il suo valore viene confrontato con i livelli di luminosita' dei 3 canali per avere la parte ON ed OFF del segnale di pilotaggio. Se il valore di pos_pwm e' piu' basso di quello del canale l' uscita e' ad 1 logico, se e' piu' altro l' uscita e' a 0. Semplicissimo direi.

Eventuali altre elaborazioni che dovro' fare (come quella di far scorrere lo spettro dei colori, per prova) va inserita dopo le linee di codice del PWM ricordandosi che e' un loop infinito e che deve funzionare veloce. Sono quindi da evitare chiamate a routines di ritardo. La cosa interessante e' che la frequenza dell cilco PWM e' piu' di 2500 Hz

Questo vuol dire che di canali ce ne possono stare un' infinita'. Basta infatti che la frequenza non scenda al di sotto dei 60 Hz e tutto va bene. Non e' stato necessario usare un timer perche' non interessa avere una frequenza sempre uguale sui LEDs. Basta che sia veloce.
E' chiaro che questo programma puo' anche essere implementato su altri micro, l' importante e' che siano abbastanza veloci. Ho notato che, con clock ad 1 MHz (il programma predispone un clock a 16 MHz) il risultato e' ancora abbastanza accettabile. Quindi potrebbe funzionare su un micro molto piu' lento, piccolo ed economico.
Buon proseguimento e buona programmazione.