- Messaggi: 14
- Ringraziamenti ricevuti 0
switch case e pulsanti
- simoblack
- Autore della discussione
- Nuovo Utente
Less
Di più
6 Anni 8 Mesi fa #1
da simoblack
switch case e pulsanti è stato creato da simoblack
Buon sabato a tutti,
scrivo qui perchè penso che sia la sezione più adatta all'argomento. Sto sperimentando con una demo board con su un MSP430f149, vorrei imparare a gestire questi processori e imparare qualcosa in più del C. Premetto che non ho grandi conoscenze del linguaggio, per cui non me ne vogliate se commetto errori "madornali".
Sto sperimentando per familiarizzare con lo 'switch case'. Ho scritto un piccolo codice che di seguito inserisco. La mia intenzione è pilotare tre led con la pressione di un solo pulsante (si, in rete ci sono milioni di esempi che potrebbero fare al caso mio, ma si riferiscono quasi sempre ad arduino e vorrei capire a fondo ciò che sto facendo, non mi piace scopiazzare codice). Il codice che ho scritto funziona, gestisce correttamente i 'case', l'unico problema riguanda la pressione del pulsante, alla pressione il loop continua a leggere il pulsante non fermando l'incremento, quindi il led che rimarrà acceso è del tutto casuale. Ora lasciando da parte eventuale codice per gestire il bounce (per il momento risolvo con un filtro analogico, non voglio mettere carne al fuoco), c'è qualcuno che mi mette sulla strada da seguire?
scrivo qui perchè penso che sia la sezione più adatta all'argomento. Sto sperimentando con una demo board con su un MSP430f149, vorrei imparare a gestire questi processori e imparare qualcosa in più del C. Premetto che non ho grandi conoscenze del linguaggio, per cui non me ne vogliate se commetto errori "madornali".
Sto sperimentando per familiarizzare con lo 'switch case'. Ho scritto un piccolo codice che di seguito inserisco. La mia intenzione è pilotare tre led con la pressione di un solo pulsante (si, in rete ci sono milioni di esempi che potrebbero fare al caso mio, ma si riferiscono quasi sempre ad arduino e vorrei capire a fondo ciò che sto facendo, non mi piace scopiazzare codice). Il codice che ho scritto funziona, gestisce correttamente i 'case', l'unico problema riguanda la pressione del pulsante, alla pressione il loop continua a leggere il pulsante non fermando l'incremento, quindi il led che rimarrà acceso è del tutto casuale. Ora lasciando da parte eventuale codice per gestire il bounce (per il momento risolvo con un filtro analogico, non voglio mettere carne al fuoco), c'è qualcuno che mi mette sulla strada da seguire?
Code:
#include <msp430.h>
#define button (P1IN & BIT6)
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // disabilito il chiwawa
P2DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4; // imposto le uscite
int i = 0;
while (1){
if (button){ // se premo button aumento i di una unità
i=i+1;}
if (i==4)
i=0;
switch (i){
case 1: // se i = a 1 accendi P2.0
P2OUT = (!BIT0 + BIT1 + BIT2 + BIT3 + BIT4);
break;
case 2: // se i = a 2 accendi P2.1
P2OUT = (BIT0 + !BIT1 + BIT2 + BIT3 + BIT4);
break;
case 3: // se i = a 3 accendi P2.2
P2OUT = (BIT0 + BIT1 + !BIT2 + BIT3 + BIT4);
break;
case 0 : // se i = a 0 spegni tutto
P2OUT = (BIT0 + BIT1 + BIT2 + BIT3 + BIT4);
break;
}
}
}
Si prega Accesso o Crea un account a partecipare alla conversazione.
- Cosimix
- Elit Utente
Less
Di più
- Messaggi: 198
- Ringraziamenti ricevuti 26
6 Anni 8 Mesi fa #2
da Cosimix
Risposta da Cosimix al topic switch case e pulsanti
Salve!
L'ideale per gestire una situazione simile sarebbe quello di utilizzare un interrupt alla pressione del pulsante, ma visto l'intento "didattico" volto a familiarizzare con lo switch-case, puoi anche farne a meno.
Come spesso accade, non c'è un'unica soluzione per risolvere il problema.
L'idea è quella di "congelare" in qualche modo l'avvenuta pressione del pulsante, attraverso una variabile (o più variabili).
Ti propongo una soluzione, forse non bellissima. Sicuramente si potrà snellire in qualche modo:
In pratica il meccanismo si basa sulla memorizzazione della pressione del pulsante attraverso la variabile stato_precedente.
Quando premi il pulsante, il codice da te scritto veniva letto diverse volte in una frazione di secondo, andando a "spazzolarsi" tutti i case dello switch. In questo caso, invece, blocchi l'esecuzione dei vari case perché blocchi l'incremento della variabile i. In che modo? Attraverso il valore logico alto della variabile stato_precedente, la quale non ti fa più accedere all'if contenente la variabile i. Quando rilasci il pulsante, la variabile stato_precedente torna al valore logico basso.
Nel case 4 puoi notare l'azzeramento della variabile i, in modo tale da ricominciare dal case 1 alla nuova pressione del pulsante.
Non ho modificato la parte relativa alle uscite perché non ho ben capito il modo in cui sono collegati i LED. In base a quello che hai scritto, al pin del microcontrollore dovrebbe essere connesso il catodo.
Per quanto riguarda il pulsante, assumo quanto chiarito nell'altro topic, ossia la presenza dei resistori di pull-up. In caso contrario, devi togliere il not logico all'if.
Saluti,
Cosimo
L'ideale per gestire una situazione simile sarebbe quello di utilizzare un interrupt alla pressione del pulsante, ma visto l'intento "didattico" volto a familiarizzare con lo switch-case, puoi anche farne a meno.
Come spesso accade, non c'è un'unica soluzione per risolvere il problema.
L'idea è quella di "congelare" in qualche modo l'avvenuta pressione del pulsante, attraverso una variabile (o più variabili).
Ti propongo una soluzione, forse non bellissima. Sicuramente si potrà snellire in qualche modo:
Code:
#include <msp430.h>
#define button P1IN & BIT6
void main(void) {
WDTCTL = WDTPW | WDTHOLD; // Disabilito il chiwawa
P2DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4; // Imposto le uscite
P2OUT = BIT0 + BIT1 + BIT2 + BIT3 + BIT4; // Tutti i LED spenti
unsigned char i = 0; // Questa variabile conta il numero di pressioni del pulsante
unsigned char stato_attuale = 0; // E' lo stato (pressione) attuale del pulsante
unsigned char stato_precedente = 0; // E' lo stato (pressione) precedente del pulsante
int delay = 0; // Variabile da utilizzare per il ritardo
while(1)
{
stato_attuale = button; // Memorizzo lo stato attuale del pulsante
for (delay = 0; delay < 10000; delay++); // Elimina questo ritardo se è già presente un anti-rimbalzo hw
// Qui entra in gioco il meccanismo relativo al controllo della pressione del pulsante:
if(!stato_attuale && stato_precedente == 0)
{
i = i+1; // Incremento i ad ogni pressione
}
stato_precedente = !stato_attuale; // Aggiorno lo stato del pulsante
switch (i)
{
case 1: // se i = a 1 accendi P2.0
P2OUT = (!BIT0 + BIT1 + BIT2 + BIT3 + BIT4);
break;
case 2: // se i = a 2 accendi P2.1
P2OUT = (BIT0 + !BIT1 + BIT2 + BIT3 + BIT4);
break;
case 3: // se i = a 3 accendi P2.2
P2OUT = (BIT0 + BIT1 + !BIT2 + BIT3 + BIT4);
break;
case 4: // se i = a 0 spegni tutto
P2OUT = (BIT0 + BIT1 + BIT2 + BIT3 + BIT4);
i=0; // Azzero la variabile i per ripetere la sequenza dello switch-case
break;
}
}
}
In pratica il meccanismo si basa sulla memorizzazione della pressione del pulsante attraverso la variabile stato_precedente.
Quando premi il pulsante, il codice da te scritto veniva letto diverse volte in una frazione di secondo, andando a "spazzolarsi" tutti i case dello switch. In questo caso, invece, blocchi l'esecuzione dei vari case perché blocchi l'incremento della variabile i. In che modo? Attraverso il valore logico alto della variabile stato_precedente, la quale non ti fa più accedere all'if contenente la variabile i. Quando rilasci il pulsante, la variabile stato_precedente torna al valore logico basso.
Nel case 4 puoi notare l'azzeramento della variabile i, in modo tale da ricominciare dal case 1 alla nuova pressione del pulsante.
Non ho modificato la parte relativa alle uscite perché non ho ben capito il modo in cui sono collegati i LED. In base a quello che hai scritto, al pin del microcontrollore dovrebbe essere connesso il catodo.
Per quanto riguarda il pulsante, assumo quanto chiarito nell'altro topic, ossia la presenza dei resistori di pull-up. In caso contrario, devi togliere il not logico all'if.
Saluti,
Cosimo
Si prega Accesso o Crea un account a partecipare alla conversazione.
- simoblack
- Autore della discussione
- Nuovo Utente
Less
Di più
- Messaggi: 14
- Ringraziamenti ricevuti 0
6 Anni 8 Mesi fa #3
da simoblack
Risposta da simoblack al topic switch case e pulsanti
Ciao Cosimix, ho provato il codice che hai proposto, funziona. Nel frattempo avevo fatto qualche piccola ricerca ed ero orientato verso la possibilità che mi hai suggerito. Ora me lo studio per bene, vediamo se riesco a metterci del mio. Grazie intanto, gentilissimo come sempre
Si prega Accesso o Crea un account a partecipare alla conversazione.
- Cosimix
- Elit Utente
Less
Di più
- Messaggi: 198
- Ringraziamenti ricevuti 26
6 Anni 8 Mesi fa #4
da Cosimix
Risposta da Cosimix al topic switch case e pulsanti
Di nulla. Tienici aggiornati.
Saluti,
Cosimo
Saluti,
Cosimo
Si prega Accesso o Crea un account a partecipare alla conversazione.
- simoblack
- Autore della discussione
- Nuovo Utente
Less
Di più
- Messaggi: 14
- Ringraziamenti ricevuti 0
6 Anni 8 Mesi fa #5
da simoblack
Risposta da simoblack al topic switch case e pulsanti
Ciao, come già detto ho studiato sul codice suggerito da Cosimix, ho aggiunto qualcosa per pilotare un display a sette segmenti con quattro cifre (di cui per il momento ne comando solo una). Per ora ho ottenuto un counter da 0 a 9 che incrementa di una cifra ad ogni pressione del pulsante. Prima di andare avanti vorrei soffermarmi ad analizzare un piccolo passaggio...
bene, vorrei capire nello specifico che ragionamento seguire per partorire il codice proposto da Cosimix relativo ai flag del controllo pulsante. Quindi vediamo fino a che punto ho capito:
-In partenza metto le valiabili "stato_attuale" e "stato_precedente" a 0.
-Successivamente scrivo nella variabile "stato_attuale" il valore di "button" che nel mio caso essendo con resistenza di pull-up equivale ad 1.
-l'espressione scritta nella prima if dice (!stato_attuale && stato_precedente ==0), subito dopo scrivi in "stato precedente il not di "stato_attuale" che nel frattempo ha cambiato il suo stato in conseguenza della pressione del tasto. Ora quello che non ho chiaro, per avere questo cambio così, viene sfruttato il piccolissimo ritardo che intercorre tra un cambio di stato e l'altro del pulsante?
Scusate per le domende banali, ma per me non sono sempre così immediate
Code:
/*Il circuito che vado a pilotare si compone di un pulsante collegato al pin P1.6 con resistenza di pull-up,
un display a sette segmenti con anodo comune composto da 4 cifre. Le porte P2.x sono utilizzate dalla P2.0 alla P2.6
per il controllo dei segmenti da A a G ed il pin P2.7 per il DP. Le porte P3.x sono utilizzate per le cifre ed
i punti L1 - L2 - L3. Da P3.0 a P3.3 sono connesse le cifre da 1 a 4.*/ *
#include <msp430.h>
#define button P1IN & BIT6
#define ZERO P2OUT = 0b11000000
#define UNO P2OUT = 0b11111001
#define DUE P2OUT = 0b10100100
#define TRE P2OUT = 0b10110000
#define QUATTRO P2OUT = 0b10011001
#define CINQUE P2OUT = 0b10010010
#define SEI P2OUT = 0b10000010
#define SETTE P2OUT = 0b11111000
#define OTTO P2OUT = 0b10000000
#define NOVE P2OUT = 0b10010000
void main(void) {
WDTCTL = WDTPW | WDTHOLD; // Disabilito il chiwawa
P2DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // Imposto le uscite P.2
P3DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // Imposto le uscita P.3
unsigned char i = 0; // Questa variabile conta il numero di pressioni del pulsante
unsigned char stato_attuale = 0; // E' lo stato (pressione) attuale del pulsante
unsigned char stato_precedente = 0; // E' lo stato (pressione) precedente del pulsante
int delay = 0; // Variabile da utilizzare per il ritardo
while(1)
{
P3OUT = BIT3; //imposto P3.3 a 1
stato_attuale = button; // Memorizzo lo stato attuale del pulsante
for (delay = 0; delay < 10000; delay++); // antirimbalzo
// Qui entra in gioco il meccanismo relativo al controllo della pressione del pulsante:
if(!stato_attuale && stato_precedente == 0)
{
i = i+1; // Incremento i ad ogni pressione
}
if (i==10) // Se i è 10 riporto i a 0
i=0;
stato_precedente = !stato_attuale; // Aggiorno lo stato del pulsante
switch (i)
{
case 1:
P2OUT = (UNO);
break;
case 2:
P2OUT = (DUE);
break;
case 3:
P2OUT = (TRE);
break;
case 4:
P2OUT = (QUATTRO);
break;
case 5:
P2OUT = (CINQUE);
break;
case 6:
P2OUT = (SEI);
break;
case 7:
P2OUT = (SETTE);
break;
case 8:
P2OUT = (OTTO);
break;
case 9:
P2OUT = (NOVE);
break;
case 0:
P2OUT = (ZERO);
break;
}
}
}
-In partenza metto le valiabili "stato_attuale" e "stato_precedente" a 0.
-Successivamente scrivo nella variabile "stato_attuale" il valore di "button" che nel mio caso essendo con resistenza di pull-up equivale ad 1.
-l'espressione scritta nella prima if dice (!stato_attuale && stato_precedente ==0), subito dopo scrivi in "stato precedente il not di "stato_attuale" che nel frattempo ha cambiato il suo stato in conseguenza della pressione del tasto. Ora quello che non ho chiaro, per avere questo cambio così, viene sfruttato il piccolissimo ritardo che intercorre tra un cambio di stato e l'altro del pulsante?
Scusate per le domende banali, ma per me non sono sempre così immediate
Si prega Accesso o Crea un account a partecipare alla conversazione.
Moderatori: Mauro Laurenti, StefA
Registrati al sito
Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.
Forum - Ultimi messaggi
-
- Freedom III e compilazioni fallite
- da Mauro Laurenti
-
- MODULO GSM SIM900A
- da FABRIZIO
-
- LTerminal - nuove funzioni
- da Mauro Laurenti
-
- Aggiornamento sito completato
- da Mauro Laurenti
-
- registro a scorrimento PIPO in cascata
- da Mauro Laurenti