AVR GCC: čtení stavu PINu portu v subr. ext. přerušení INT4

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Enkoder
Příspěvky: 12
Registrován: 29 bře 2016, 02:00

AVR GCC: čtení stavu PINu portu v subr. ext. přerušení INT4

#1 Příspěvek od Enkoder »

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

Uživatelský avatar
lesana87
Příspěvky: 3296
Registrován: 20 zář 2014, 02:00

#2 Příspěvek od lesana87 »

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.

Uživatelský avatar
frpr666
Příspěvky: 1051
Registrován: 28 pro 2009, 01:00

#3 Příspěvek od frpr666 »

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++;
  }
}
CHECK_BIT(BYTE,BIT) vrací 0, pokud je vstup v 0, jinak vrací jakoukoliv nenulovou hodnotu
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))
Edit1: To je kouzlo jazyka C, x=0 -> false, x<>0 -> true
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.

Uživatelský avatar
lesana87
Příspěvky: 3296
Registrován: 20 zář 2014, 02:00

#4 Příspěvek od lesana87 »

Máš tam tu samou školáckou chybu jako Encoder, čteš PORTE, ale máš číst PINE.

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#5 Příspěvek od FHonza »

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:

Kód: Vybrat vše

volatile unsigned char ...
a ještě mně prosim prozraďte kterej Atmel má PORTE :)

Enkoder
Příspěvky: 12
Registrován: 29 bře 2016, 02:00

#6 Příspěvek od Enkoder »

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
Naposledy upravil(a) Enkoder dne 29 bře 2016, 21:37, celkem upraveno 1 x.

Uživatelský avatar
lesana87
Příspěvky: 3296
Registrován: 20 zář 2014, 02:00

#7 Příspěvek od lesana87 »

FHonza píše:a ještě mně prosim prozraďte kterej Atmel má PORTE :)
Nevím, kterej je Atmel, ale AVR třeba ATmega64, 128, 640, 1280...

Uživatelský avatar
lesana87
Příspěvky: 3296
Registrován: 20 zář 2014, 02:00

#8 Příspěvek od lesana87 »

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);
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).
Naposledy upravil(a) lesana87 dne 29 bře 2016, 21:45, celkem upraveno 1 x.

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#9 Příspěvek od FHonza »

jasně no. nějak sem na ně zapomněl ... omlouvám se

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#10 Příspěvek od FHonza »

Když chceš v přerušení zakázat další přerušení, tak po vstupu do obsluhy přerušení vynuluj příslušný bit v EIMSK. Na konci před opětovným povolením v EIMSK vymaž příslušný bit v EIFR zápisem jedničky. Opravdu se nuluje zápisem jedničky.

Uživatelský avatar
frpr666
Příspěvky: 1051
Registrován: 28 pro 2009, 01:00

#11 Příspěvek od frpr666 »

Nastav si na začátku, aby externí přerušení bylo spouštěné hranou.

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.
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
Naposledy upravil(a) frpr666 dne 29 bře 2016, 22:05, celkem upraveno 1 x.

Uživatelský avatar
lesana87
Příspěvky: 3296
Registrován: 20 zář 2014, 02:00

#12 Příspěvek od lesana87 »

Zákmity na INT vstupu mu to "samo" neošetří, když má povolené přerušení.

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#13 Příspěvek od FHonza »

frpr666 píše:Nakonec ty globální proměnné nejsou tak špatné.
Nejsou, ale musí být volatile když jsou použity v přerušení.

Uživatelský avatar
frpr666
Příspěvky: 1051
Registrován: 28 pro 2009, 01:00

#14 Příspěvek od frpr666 »

@lesana87
s tím vnořováním samo do sebe nesouhlasím. Myslím, že tam bylo něco jako že se z ISR vrátí řízení zpět, provede se alespoň jedna instrukce a pak se zase (případně) zavolá ISR.

Enkoder
Příspěvky: 12
Registrován: 29 bře 2016, 02:00

#15 Příspěvek od Enkoder »

:D to je fajn parta tady, jsem mezi inteligenty
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

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“