La tua soluzione e' valida, basta inserire la linea
- Codice: Seleziona tutto
while(input(PIN_A0));
e lui si blocca in attesa del rilascio.
Ma non e' una soluzione elegante.
Altra soluzione e' creare una variabile che memorizzi lo stato precedente del pulsante.
Partiamo dall' inzio.In generale il programma di un microcontrollore e' un loop infinito all' interno del quale vengono svolti alcuni processi. Affinche' ogni processo possa essere svolto, ogni processo deve evitare come la morte la presenza di loops che possano bloccare l' esecuzione. Bisogna quindi scrivere i processi in modo che nessuno di questi possa bloccare l' esecuzione del loop principale. Per questo scopo si usano dei flags che possono essere delle variabili booleane, magari dei soli bit, che si ricordano di alcune cose. Io di solito, se non ho problemi di memoria, uso dei bytes e finito il chiasso.
Creo un programma tipo questo:
- Codice: Seleziona tutto
// dichiarazione variabili globali visibili a tutto il programma
void main(void)
{
// dichiarazione variabili visibili solo al main
// inizializzazione hardware
// init. processo 1
// init. processo 2
// init. ...
// init. processo n
// Loop generale
while(1)
{
// processo 1
// processo 2
// ...
// processo n
}
}
In pratica si eseguono i vari processi in modo che sembri che vengano eseguiti contemporaneamente.
Nel tuo caso devi considerare la transizione da 1 a 0 di un ingresso. Il tuo processo deve quindi ricordarsi lo stato che l' ingresso aveva nel ciclo precendente, vedere se e' cambiato e, nel caso sia cambiato, fare un qualcosa (commutare l' uscita). Per semplificare il discorso io faccio conto di avere una funzione che mi legge l' ingresso che chiamero' leggi_ingresso() che mi rende un valore 0 o 1 che corrisponde allo stato dell' ingresso (sai che fantasia!). Allo stesso modo usero' una funzione che chiamero' scrivi_uscita che, indovina un po', mi scrive il valore di una variabile (0 o diverso da 0) nella mia uscita. Tu poi, con calma, sotituirai queste due funzioni con le operazioni necessarie per leggere l' ingresso e scrivere l' uscita.
E' ovvio che serve una variabile che tenga memoria dello stato precedente dell' ingresso, quindi la dichiariamo come StPr1.
Per evitare casini, nell' inizializzazione del processo leggeremo lo stato del pulsante. Nessuno dice che il pulsante deve per forza essere in stato inattivo nel momento in cui il micro viene acceso. Puo' essere che il micro venga acceso mentre il pulsante e' premuto. Quindi ci mettiamo tranquilli e lo leggiamo almeno una volta prima di iniziare tutto l' ambaradan del ciclo principale. Ora siamo tranquilli e possiamo pensare a cosa fare nel nostro processo. Ma vediamo a che punto siamo con il programma prima di andare avanti:
- Codice: Seleziona tutto
// dichiarazione variabili globali visibili a tutto il programma
void main(void)
{
// dichiarazione variabili visibili solo al main
char StPr1; // stato precedente delll' ingresso nel processo 1
// inizializzazione hardware
// init. processo 1
StPr1 = leggi_ingresso();
// init. processo 2
// init. ...
// init. processo n
// Loop generale
while(1)
{
// processo 1
// processo 2
// ...
// processo n
}
}
Ora viene il bello. Dobbiamo fare qualcosa solo se il nostro pulsante e' passato da iniattivo ad attivo, in tutti gli altri casi passiamo oltre, skippiamo tutto e lasciamo l' esecuzione agli altri processi. Quindi faremo qualcosa se StPr1 = 1 (stato precedente inattivo) e se lo stato attuale e' a 0 (attivo). Per lavorare tranquillo mi creo una variabile StAtt1 che mi rappresenta lo stato attuale dell' ingresso e che aggiorno all' inizio del processo. In ogni caso, sia che decidiamo di fare qualcosa o no, dovremo ricordarci, alla fine del processo, di memorizzare lo stato dell' ingresso nello stato precedente. Il nostro programma diventera':
- Codice: Seleziona tutto
// dichiarazione variabili globali visibili a tutto il programma
void main(void)
{
// dichiarazione variabili visibili solo al main
char StPr1; // stato precedente dell' ingresso nel processo 1
char StAtt1; // stato attuale dell' ingresso nel processo 1
// inizializzazione hardware
// init. processo 1
StPr1 = leggi_ingresso();
// init. processo 2
// init. ...
// init. processo n
// Loop generale
while(1)
{
// processo 1
StAtt1 = leggi_ingresso();
if ((StPr1 == 1) && (StAtt == 0))
{
// eseguo la gestione della transizione
}
StPr1 = StAtt1; // Aggiorno lo stato precedente
// processo 2
// ...
// processo n
}
}
Da adesso in poi la strada e' in discesa: possiamo pensare solo a quello che dobbiamo fare, cioe' a commutare l' uscita. Eppero' non abbiamo ancora deciso se l' uscita, all' atto dell' accensione del micro, dovra' essere a 1 o a 0. Poco male, inseriamo l' inizializzazione dell' uscita in questo momento al posto giusto, cioe' prima della prima lettura (scusa il gioco di parole

) dell' ingresso. Decidiamo che questa, all' atto dell' accensione, vale 0 (led spento).
Cio' detto,
Passiamo a commutare questa benedetta uscita. Beh, qui possiamo fare la cosa in modo canonico con una if ... else che controlla lo stato precedente o possiamo fare i fighetti negando l' uscita. Facciamo i fighetti (anche perche' e' tardi e sto per andare a nanna

) ma facciamolo bene e creiamoci anche una variabile che tiene il valore dell' uscita. Quindi la dichiariamo, la inizializziamo etc etc. ed otteniamo questo sorgente:
- Codice: Seleziona tutto
// dichiarazione variabili globali visibili a tutto il programma
void main(void)
{
// dichiarazione variabili visibili solo al main
char StPr1; // stato precedente dell' ingresso nel processo 1
char StAtt1; // stato attuale dell' ingresso nel processo 1
char Uscita1; // stato dell' uscita nel processo 1
// inizializzazione hardware
// init. processo 1
Uscita1 = 0;
scrivi_uscita(Uscita1);
StPr1 = leggi_ingresso();
// init. processo 2
// init. ...
// init. processo n
// Loop generale
while(1)
{
// processo 1
StAtt1 = leggi_ingresso();
if ((StPr1 == 1) && (StAtt == 0))
{
// eseguo la gestione della transizione
Uscita1 != Uscita1;
scrivi_uscita(Uscita1);
}
StPr1 = StAtt1; // Aggiorno lo stato precedente
// processo 2
// ...
// processo n
}
}
E il gioco e' fatto.
Domani mattina riguardero' quello che ho scritto e se ci sono degli errori lo correggero'. Non massacratemi se ho scritto fesserie ma sono molto stanco. 
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.