AVR GCC: čtení stavu PINu portu v subr. ext. přerušení INT4
Moderátor: Moderátoři
AVR GCC: čtení stavu PINu portu v subr. ext. přerušení INT4
ahoj,
mohu chtít v podprogramu ext. přerušení INTn číst stav pinu nějaké brány?
nedaří se mi takový to vstup přečíst.
tohle mi nechodí, ikdyž logický analyzátor ukazuje na PE3 log1, čte se do proměnné stavB pořád jen nula:
#define CHECK_BIT(BYTE,BIT)(BYTE&=(1<<BIT))
unsigned int NastavovanaHodnota=0; // globální proměnné
unsigned char stavB=0, pomocna=0;
ISR(INT4_vect)
{
cli();
stavB= ((PORTE & 0x08)>>3);
//stavB= CHECK_BIT(PORTE,3); // <<< nebo takto taky nechodí
sei();
switch(stavB)
{
case 0: NastavovanaHodnota--; break;
case 1: NastavovanaHodnota++; break;
default: pomocna++; break;
}
}
čtený pin PE3 mám při startu nastavený jako vstup DDRE=0xE7;
Děkuju předem
mohu chtít v podprogramu ext. přerušení INTn číst stav pinu nějaké brány?
nedaří se mi takový to vstup přečíst.
tohle mi nechodí, ikdyž logický analyzátor ukazuje na PE3 log1, čte se do proměnné stavB pořád jen nula:
#define CHECK_BIT(BYTE,BIT)(BYTE&=(1<<BIT))
unsigned int NastavovanaHodnota=0; // globální proměnné
unsigned char stavB=0, pomocna=0;
ISR(INT4_vect)
{
cli();
stavB= ((PORTE & 0x08)>>3);
//stavB= CHECK_BIT(PORTE,3); // <<< nebo takto taky nechodí
sei();
switch(stavB)
{
case 0: NastavovanaHodnota--; break;
case 1: NastavovanaHodnota++; break;
default: pomocna++; break;
}
}
čtený pin PE3 mám při startu nastavený jako vstup DDRE=0xE7;
Děkuju předem
Jestli se tak snažíš číst mechanický enkodér, tak ti tam můžou dělat neplechu zákmity. V obsluze přerušení povoluješ přerušení. Nevím, jak si s možnou reentrancí poradí samotné Cčko, ale ty tam používáš globální proměnné a to není dobré, to přerušení se může vyvolat několikrát po sobě a několikrát se do sebe vnořit.
Hlavní chyba bude ale v tom, že čteš PORTE a ne PINE.
Hlavní chyba bude ale v tom, že čteš PORTE a ne PINE.
Kód: Vybrat vše
// enkoder demo:
#define CHECK_BIT(BYTE,BIT) ((BYTE)&(1<<(BIT)))
volatile unsigned int NastavovanaHodnota = 0; // globální proměnné
ISR(<TBD>) // tohle je přerušení spouštěné hranou na pinu<>PE3
{
unsigned char stavE3;
stavE3 = CHECK_BIT(PORTE, 3); // PE3?
if (stavE3)
{
NastavovanaHodnota--;
}
else
{
NastavovanaHodnota++;
}
}
Myslím že v gcc v avr-libc je už toto makro hotové, stačí jej použít:
Kód: Vybrat vše
sfr_defs.h:#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
Edit2: Jo, má tam být PINE. To je pravda...
Naposledy upravil(a) frpr666 dne 29 bře 2016, 21:30, celkem upraveno 2 x.
Rozhodně globální proměnné musí být "volatile". Pak je překladač umístí vždy do datové paměti a ne do registrů. Tohle je (v závislosti na další části programu a kvůli optimalizaci) často zdrojem chyb.
Tj. definici napiš jako:
a ještě mně prosim prozraďte kterej Atmel má PORTE ![Smile :)](./images/smilies/icon_smile.gif)
Tj. definici napiš jako:
Kód: Vybrat vše
volatile unsigned char ...
![Smile :)](./images/smilies/icon_smile.gif)
ahoj, díky za reakce, jste rychlejší, toto je reakce na první odpověď:
díky už se to konečně pohlo, směr je je rozpoznán, čítá to ale většinou po dvou, až to poladím, dám vědět.
globální proměnné používám proto, abych je mohl zobrazit na displeji mimo podprogram přerušení.
v podprogramu přerušení po přečtení vstupu nechám čekat 10ms
na konci podprogramu přerušení shazuji bit příznaku pro čekající přerušení (je to tak?) CLEAR_BIT(EIFR,4);
protože další přerušení bývá obvykle za delší dobu než 200ms
to "několikrát se do sebe vnořit", to je pro mně novinka, je to opravdu tak?
díky moc
díky už se to konečně pohlo, směr je je rozpoznán, čítá to ale většinou po dvou, až to poladím, dám vědět.
globální proměnné používám proto, abych je mohl zobrazit na displeji mimo podprogram přerušení.
v podprogramu přerušení po přečtení vstupu nechám čekat 10ms
na konci podprogramu přerušení shazuji bit příznaku pro čekající přerušení (je to tak?) CLEAR_BIT(EIFR,4);
protože další přerušení bývá obvykle za delší dobu než 200ms
to "několikrát se do sebe vnořit", to je pro mně novinka, je to opravdu tak?
díky moc
Naposledy upravil(a) Enkoder dne 29 bře 2016, 21:37, celkem upraveno 1 x.
Když před tím povolíš přerušení, tak je to k ničemu, pokud se EIFR,4 nastaví, přerušení se okamžitě vyvolá znovu (a EIFR se tím následně shodí) a tím se vnoří samo do sebe (přeruší se vykonávaná obsluha INT4 a zavolá se znovu ta samá obsluha INT4).Enkoder píše:na konci podprogramu přerušení shazuji bit příznaku pro čekající přerušení (je to tak?) CLEAR_BIT(EIFR,4);
Naposledy upravil(a) lesana87 dne 29 bře 2016, 21:45, celkem upraveno 1 x.
Nastav si na začátku, aby externí přerušení bylo spouštěné hranou.
Potom nemusíš nic "čistit", všechno se udělá "samo". Nakonec ty globální proměnné nejsou tak špatné. Asi jediný způsob jak předat něco z / do ISR().
http://www.mikrocontroller.net/articles ... C3.B6schen
Kód: Vybrat vše
The falling edge of INTn generates asynchronously an interrupt request.
The rising edge of INTn generates asynchronously an interrupt request.
http://www.mikrocontroller.net/articles ... C3.B6schen
Naposledy upravil(a) frpr666 dne 29 bře 2016, 22:05, celkem upraveno 1 x.
![Very Happy :D](./images/smilies/icon_biggrin.gif)
PORTE má arduino s ATmega2560
k enkoderu jsem dal odpory 10k a kondíky 33nF.
budu sledovat diskuzi, opravím to až zítra
void Inicializace_INT4(void)
{
EICRB |= (1 << ISC41) | (1 << ISC40); // reakce přerušení INT4 na vzestupnou hranu
SET_BIT(EIMSK,4); // povol přerušení od INT4
}
díky moc