Newsgroup: it.hobby.elettronica.digitale
Titolo: Settare il livello logico zero del pic

Salve a tutti, sono alle prime armi con la programmazione di
microcontrollori e sto cercando di scrivere un semplice programma che,
tramite l'aumento a 5 volts di voltaggio sul pin RA2, attivi un
interrupt che vari di volta in volta il livello logico (0 o +5volts)
dei due pin RC0 e RC1
---------------------------------------
#include <pic.h>
__CONFIG(
	INTIO
	//& PWRTDIS
	& MCLRDIS
	//& UNPROTECT
	//& BORDIS
	//& IESODIS
	//& FCMDIS
	& WDTDIS
	//& HS
	);
volatile unsigned short ledSwitch;
void interrupt ISR_Routine(void)
{
	if(!INTF)
		return;
	if(!ledSwitch)
	{
		PORTC = 0x3;
		ledSwitch = 1;
	}
	else
	{
		PORTC = 0x00;
		ledSwitch = 0;
	}
	INTF = 0;
}
// Routine programma
void main(void)
{
	TRISA = 0b00001111; //RA2 input mode
	PORTA = 0b11111111; //High level on A ports
	TRISC = 0x00; //All port C outputs
	PORTC = 0x00; //low level on C ports
	INTE = 1; //enable RA2/INT interrupts
	INTEDG = 0; //rising edge
	ANSEL = 0; //digital input for RA2
	//ANSELH = 0;
	//WPUA = 0;
	CM2CON0 = 0b10000111; //comparator with Vref (RA1) and RC5
	ledSwitch = 0;
	GIE = 1; //enable all un-masked interrupts
	while(1)
	{
	};
}
-----------------------------
Il programma funziona ma ogni volta che il livello logico torna a
zero, anche la prima volta appena avviato il micro, il livello logico
zero dei pin RC0 e RC1 non è 0 volts (o circa), ma 2 volts e mezzi
Da cosa può dipendere questo? Come posso risolvere il problema?
Grazie a chiunque tenterà di aiutarmi

 Da cosa può dipendere questo? Come posso risolvere il problema?
Ciao!
La cosa che mi viene in mente è che tu non abbia settato le porte A come 
digitali: le porte A da 0 a 5 vengono di default configurate come 
analogiche, per poter sfruttare il convertitore A/D.
Ti consiglierei quindi di aggiungere le istruzioni:
BANKSEL ADCON1
MOVLW	6
MOVWF	ADCON1
In questo modo tutte le porte A sono configurate come digitali.
Mi dispiace, in C non ti so aiutare!
Ciao!
-- 
Stefano M. (Italy)
WEB: 
http://www.lemming.it
"La necessità di parlare,  l'imbarazzo di non aver nulla da dire
e la brama di mostrarsi persone di spirito, sono tre cose capaci
di rendere ridicolo anche l'uomo più grande."         (Voltaire)

Ciao Stefano, grazie dell'aiuto ma le porte A erano già settate come
digitali:
ANSEL = 0; //digital input for RA2
questa riga dovrebbe impostarle tutte come digitali, non solo RA2.
Il problema scompare (le porte RC0 e RC1 tornano come dovrebbero a 0
volts) se elimino la riga
if(!ledSwitch)
        {
                PORTC = 0x3; <---- questa
                ledSwitch = 1;
        }
all'interno della routine dell'interrupt. Cosa significa questo?
------------------
30:                	if(!ledSwitch)
   006    1283     BCF 0x3, 0x5
   007    1303     BCF 0x3, 0x6
   008    0821     MOVF 0x21, W
   009    0420     IORWF 0x20, W
   00A    1D03     BTFSS 0x3, 0x2
   00B    2811     GOTO 0x11
31:                	{
32:                		PORTC = 0x03;
   00C    3003     MOVLW 0x3
   00D    0087     MOVWF 0x7
33:                		ledSwitch = 1;
   00E    3001     MOVLW 0x1
   00F    00A0     MOVWF 0x20
   010    2813     GOTO 0x13
34:                	}
35:                	else
36:                	{
37:                		PORTC = 0x00;
   011    0187     CLRF 0x7
38:                		ledSwitch = 0;
   012    01A0     CLRF 0x20
   013    01A1     CLRF 0x21
39:                	}
---------------------------
questo è il disassemblato pseudo-C, anche in assembler non vedo nulla
di sbagliato nell'istruzione MOVLW 0x3 / MOVWF 0x7, è la normale
procedura per copiare il flag W in PORTC no?

 ha scritto nel messaggio 
news:7b3448db-c9a3-4280...@y13g2000yqn.googlegroups.com...
Salve a tutti, sono alle prime armi con la programmazione di
microcontrollori e sto cercando di scrivere un semplice programma che,
tramite l'aumento a 5 volts di voltaggio sul pin RA2, attivi un
interrupt che vari di volta in volta il livello logico (0 o +5volts)
dei due pin RC0 e RC1
[...]
void interrupt ISR_Routine(void)
{
if(!INTF)
return;
if(!ledSwitch)
{
PORTC = 0x3;
ledSwitch = 1;
}
else
{
PORTC = 0x00;
ledSwitch = 0;
}
INTF = 0;
}
[...]
Se fai scattare l'interrupt di continuo, ci sarà un alternarsi continuo 
dello stato della variabile ledswitch e quindi dello stato dei led fra 
entrambi accesi ed entrambi spenti.
I 2,5V che ti ritrovi non sono altro che la media di ciò che il tuo tester 
riesce a leggere in questa continua alternanza....
A questo punto quindi, ti ritrovi con l'interrupt che è richiemato di 
continuo, ti consiglio di verificare che anche IOCA sia impostato a zero e 
di implementare in modo più completo la gestione della routine di interrupt.
Inoltre potrebbe anche esservi dei rimbalzi sul pin RA2, ma qui occorrerebbe 
vedere lo schema elettrico e d anche sapere il tipo di dispositivo che stai 
utilizzando.

 procedura per copiare il flag W in PORTC no?
Si, a parte che W non è un flag ma l'accumulatore, bisognerebbe 
controllare due cose:
1) Se la porta C è nella locazione 0x7.
2) Se si è nel banco giusto (gioia e dolore dei programmatori dei pic! :-o)
Mi dici che PIC stai usando?


Vi ringrazio intanto per le vostre risposte, ho postato il problema
anche in alcuni forum ma qui avete dato i migliori e più sinceri
consigli a mio parere. Cercherò di essere sintetico e dettagliato così
che la lettura di ciò che sto facendo sia facile e immediata (spero)
Il pic che sto programmando è un PIC16F690 (con convertitore analogico-
digitale che dovrei aver disabilitato con ADCON0 = 0 così non mi crea
casini) e lo sto provando su breadboard con le seguenti connessioni:
http://img22.imageshack.us/img22/4815/immagineaeu.jpg
Credo che purtroppo stia succedendo esattamente come ha scritto
Roberto dato che quando collego i 5 volts al piedino dell'interrupt,
RC0 e RC1 (le porte di output) segnano esattamente 5 volts (così come
voglio),
però quando non c'è nulla collegato al piedino dell'interrpt RA2, su
questo è presente un voltaggio di 0.05 volts circa (che non so da dove
arrivi... se da scosse elettrostatiche o se da moti browniani a
frequenza iperbassa o per magia magari) che credo faccia saltellare
ogni secondo fra lo zero logico e l'uno logico l'interrupt, portando i
piedini di output a circa 2.50 per le continue e velocissime
variazioni
Dunque ora che grazie a voi ho fatto il mio bel ragionamento vi chiedo
nuovamente consiglio perchè la mia soluzione è fallita:
void interrupt ISR_Routine(void)
{
	if(!INTF)
		return;
	if(!ledSwitch && (PORTA & 0b100)) // <-
	{
		PORTC = 0x03;
		ledSwitch = 1;
	}
	else
	{
		PORTC = 0x00;
		ledSwitch = 0;
	}
	INTF = 0;
}
ho pensato di leggere al momento dell'interrupt se il livello logico
della porta RA2 è veramente alto e in tal caso di attivare RC0 e RC1,
ma questo codice non funziona in quanto (PORTA & 0b100) non è mai vera
a quanto risulta dai test (anche se RA2 è impostato come input
digitale)
Dunque c'è un modo per impostare la soglia di attivazione dell'uno
logico per il pic nell'input digitale?
Il registro VRCON sembrerebbe fare al caso mio ma vale solo per il
comparatore

 nuovamente consiglio perchè la mia soluzione è fallita:
Secondo me potrebbe essere quanto ti ho scritto qui sopra.
Fammi sapere se così hai risolto!
Ciao


Allora, il circuito antirimbalzo non c'è, come faccio ad abbassare a
zero il voltaggio di un pin (RA2) che è già alto di per sè? (0.05
volts circa)
Il pin dovrebbe essere, secondo INTEDG = 0, al falling down del
livello (quando scende credo)
questo è il passaggio per RA2 come interrupt, l'ho riletto mille volte
e comunque non dice dettagliatamente nulla, rimanda alle rispettive
sezioni
----------------------
External interrupt on RA2/INT pin is edge-triggered;
either rising if the [[[ INTEDG (settato a zero)]]] bit
(OPTION_REG<6>) is
set, or falling, if the INTEDG bit is clear. When a valid
edge appears on the RA2/INT pin, the INTF bit
(INTCON<1>) is set. This interrupt can be disabled by
clearing the INTE control bit (INTCON<4>). The INTF
bit must be cleared in software in the Interrupt Service
Routine before re-enabling this interrupt. The RA2/INT
interrupt can wake-up the processor from Sleep, if the
INTE bit was set prior to going into Sleep. The status of
the GIE bit decides whether or not the processor
branches to the interrupt vector following wake-up
(0004h). See Section 14.6 “Power-Down Mode
(Sleep)” for details on Sleep and Figure 14-10 for
timing of wake-up from Sleep through RA2/INT
interrupt.
Note 1: Individual interrupt flag bits are set,
regardless of the status of their
corresponding mask bit or the GIE bit.
2: When an instruction that clears the GIE
bit is executed, any interrupts that were
pending for execution in the next cycle
are ignored. The interrupts, which were
ignored, are still pending to be serviced
when the GIE bit is set again.
Note: The ANSEL [[ settato a zero ]] and CM2CON0 [[settato in modo da
avere VREF+ come descritto da VRCON, ma il livello inferiore come
glielo dico? ]] registers
must be initialized to configure an analog
channel as a digital input. Pins configured
as analog inputs will read ‘0’.
---------------------------
C'è un modo per dire al comparatore (il secondo mi interessa) di
abbassare la soglia minima o almeno di settarla?
Che cos'è un circuito antirimbalzo? Potrebbe servirmi?

 volts circa)
Allora ti serve un pull-down: collega una resistenza tra RA2 e GND da 
10K e risolvi il tutto.
Ti ho preparato uno schemino con antirimbalzo e pull-down. Fammi sapere 
se tutto è ok!
[FIDOCAD]
MC 30 25 3 0 010
MC 60 85 0 0 040
MC 60 65 1 0 080
TY 65 65 4 3 0 0 0 * R1
TY 65 70 4 3 0 0 0 * 10K
MC 30 35 0 0 860
TY 35 35 4 3 0 0 0 * PULSANTE
TY 35 40 4 3 0 0 0 * N.A.
MC 80 60 0 0 073
TY 80 65 4 3 0 0 0 * RA2
TY 80 75 4 3 0 0 0 * PIC IN
MC 30 65 1 0 170
TY 35 65 4 3 0 0 0 * C1
TY 35 70 4 3 0 0 0 * 100nF
MC 30 85 0 0 040
LI 30 25 30 35 0
LI 30 50 30 65 0
LI 30 75 30 85 0
LI 30 60 80 60 0
LI 60 60 60 65 0
SA 30 60 0
LI 60 75 60 85 0
Ciao!


Ti ringrazio Stefano, però devo provare questa soluzione. Appena
l'avrò fatto ti farò risapere!

Ho provato con una resistenza in modo da "antirimbalzare" e devo dire
che hai ragione Stefano, ora l'interrupt funziona perfettamente e se
non fornisco al pin il voltaggio di 5 volts, non caccia fuori niente
sui piedini RC0 e RC1!
Ho ancora un paio di aggiustamenti per il progetto a cui sto lavorando
(devo fare in modo che dopo 2 secondi circa il voltaggio attivato su
RC0 e RC1 venga dimesso anche se RA2 è ancora a 5 volts e dovrei se
possibile fare in modo che il dispositivo vada in sleep mode e si
svegli con l'interrupt sul RA2) ma non voglio la pappa pronta e
chiederò aiuto qui soltanto se avrò problemi dopo aver scritto il mio
codice
Vi ringrazio di cuore intanto perchè senza di voi sarei ancora a
domandarmi perchè se il voltaggio è circa zero su RA2 i pin di output
cacciano 2.5 volts