Funkce pro jednoduchou práci s tlačítky na jakémkoliv portu

edit: :bulb: Vyřešeno, fungující kód vizte ke konci tématu.

Vytvořil jsem si kód pro zjišťování stavu tlačítka tak, aby eliminoval softwarově jeho zákmity a aby rozlišoval aktivaci po stisku nebo po puštění. Když jsem potřeboval pracovat s více tlačítky, kód jsem kopíroval a měnil názvy portů a pinů, to činilo můj kód nepřehledným, protože dlouhým. Chtěl jsem tedy nahradit kód tlačítek makrem, ale přes možnost použít parametry by nebylo výsledné volání makra dost jednoduché. Vytvořil jsem tedy funkci, která by měla být univerzální pro jakýkoliv port, jakýkoliv pin a dokázala by také rozlišit stisknutí nebo puštění tlačítka a měla by eliminovat zákmity (debounce switch). Fce funguje ale jen pro pin0, pro pin 1 a další už ne. Nevím proč, mořím se s tím druhý den a nemám nápady. Prosím o pomoc. Kdyby bylo něco nejasného, vysvětlím myšlenku, třeba jsem to jinak myslel a jinak - blbě naprogramoval, že princip z kódu není jasný. Díky, Pavel

#include <avr/io.h>             
#include "..\inc\mojelib1.h"   

#define DEBOUNCE waitms(30)

/**** definice funkcí ****/
	char tlacitko ( char PINX, char pin, char puvodni)
	{ 
	// pro předávání stavů platí:
	// bit0: 1=puštěno;           0=nebylo puštěno
	// bit1: 1=stisknuto;         0=nebylo stisknuto
	// bit2: 1=minulý stav byl 1; 0=minulý stav byl 0
	char vystup=0;
	char stav_tlacitka=0;

	stav_tlacitka = bit_is_set(PINX,pin);
	if ( (stav_tlacitka == 1) && ((puvodni & 0b00000100) == 0x00) ) 	//test zda bylo stisknuto a zda původně ne
	{
		DEBOUNCE;
		stav_tlacitka = bit_is_set(PINX,pin);
		if (stav_tlacitka == 1) 						//test zda je stále stisknuto
		{
		vystup = 0b00000010; //právě bylo stisknuto
		}
	}
	if (stav_tlacitka == 0 && ((puvodni & 0b00000100) != 0x00) ) //test zda bylo puštěno a zda původně ne
	{
		DEBOUNCE;
		stav_tlacitka = bit_is_set(PINX,pin);
		if (stav_tlacitka == 0)							//test zda je stále puštěno
		{
		vystup = 0b00000001; //právě bylo puštěno
		}
	}
	vystup = vystup | (stav_tlacitka << 2); //aby se na třetím místě odzadu objevila 1 když je stisknuto, 0 když není a zbytek neměnit
	return vystup;
	}
/**** /definice funkcí ****/

/////////////////////////////// MAIN //////////////////////////////
int main (void)
{
  DDRB  = 0x00;                    // všechny piny na PortB jako vstupní
  PORTB = 0xff;                    // pull-up na portu B zapnuto

  DDRD  = 0xff;                     // všechny piny na PortD jako výstupní
  PORTD = 0x00;                  // všechny LED zhasne

  char tlacB0 = 0;
  char tlacB1 = 0;

  //*********** nekonečná smyčka ***********//
	for(;;) 
	{
		

		tlacB1 = tlacitko (PINB, 1, tlacB1);
		if ((tlacB1 & 0b00000001) != 0x00 )
		{
		PORTD ^= (0b00000001);
		}


 	}
//*********** /nekonečná smyčka ***********//

}
/////////////////////////////// END MAIN //////////////////////////

Když část

tlacB1 = tlacitko (PINB, 1, tlacB1); if ((tlacB1 & 0b00000001) != 0x00 ) { PORTD ^= (0b00000001); }
změním tak, aby pracovala s pinem 0:

tlacB0 = tlacitko (PINB, 0, tlacB0); if ((tlacB0 & 0b00000001) != 0x00 ) { PORTD ^= (0b00000001); },
funguje to. Jakmile nuly vyměním za jiné číslo portu, neděje se nic.

:arrow_right: administrator: přejmenováno z "funkce pro jednoduchou práci s tlačítky"

Jednoduché…

if ( (stav_tlacitka == 1) && ((puvodni & 0b00000100) == 0x00) )    //test zda bylo stisknuto a zda původně ne 

nahraď za

if ( (stav_tlacitka != 0) && ((puvodni & 0b00000100) == 0x00) )    //test zda bylo stisknuto a zda původně ne 

Makro bit_is_set totiž vrací jedničku, ale posunutou. :wink:

Pokud je to celý problém, může to být ještě jednodušší (nenulová hodnota = TRUE): if ( (stav_tlacitka) && ((puvodni & 0b00000100) == 0x00) )

Nebylo to sice jen tím způsobem testování, ale Divous mne nakopl, že nejde o jedničku jako 0x01 ale o binární jedničku kdesi v osmi bitech. Takže jsem kód jednak zúhlednil a našel vadný řádek:

vystup = vystup | (stav_tlacitka << 2); 

ten změnil na:
vystup = vystup | ((stav_tlacitka>>pin) << 2);
A výsledek je zde:

[code]#include <avr/io.h>
#include “…\inc\mojelib1.h”

#define DEBOUNCE waitms(30)

/**** definice funkcí ****/
char tlacitko ( char PINX, char pin, char puvodni)
{
// pro předávání stavů platí:
// bit0: 1=puštěno; 0=nebylo puštěno
// bit1: 1=stisknuto; 0=nebylo stisknuto
// bit2: 1=minulý stav byl 1; 0=minulý stav byl 0
char vystup = 0x00;
char stav_tlacitka = 0x00;

stav_tlacitka = (PINX &= (1<<pin));
if ( (stav_tlacitka) && (!(puvodni & 0b00000100)) ) 	//test zda bylo stisknuto a zda původně ne
{
	DEBOUNCE;
	stav_tlacitka = (PINX &= (1<<pin));
	if (stav_tlacitka) 									//test zda je stále stisknuto
	{
	vystup = 0b00000010; 							    //právě bylo stisknuto
	}
}
if ( !(stav_tlacitka) && (puvodni & 0b00000100) )   	//test zda bylo puštěno a zda původně ne
{
	DEBOUNCE;
	stav_tlacitka = (PINX &= (1<<pin));
	if (!(stav_tlacitka))								//test zda je stále puštěno
	{
	vystup = 0b00000001; //právě bylo puštěno
	}
}
vystup = vystup | ((stav_tlacitka>>pin) << 2); //aby se na třetím místě odzadu objevila 1 když je stisknuto, 0 když není a zbytek neměnit
return vystup;
}

/**** /definice funkcí ****/

/////////////////////////////// MAIN //////////////////////////////
int main (void)
{
DDRB = 0x00; // nastaví všechny piny na PortB jako vstupní
PORTB = 0xff; // pull-up na PortB povoleno

DDRD = 0xff; // všechny piny na PortD jako výstupní
PORTD = 0x00; // všechny LED na PortD zhasne

char tlacB0 = 0x00;
char tlacB1 = 0x00;
char tlacB3 = 0x00;
char tlacB4 = 0x00;

//*********** nekonečná smyčka ***********//
for(;:wink:
{
tlacB0 = tlacitko (PINB, 0, tlacB0);
if (tlacB0 & 0b00000001)
{
PORTD ^= 0b00000001;
}

	tlacB1 = tlacitko (PINB, 1, tlacB1);
	if (tlacB1 & 0b00000001)
		{
		PORTD ^= 0b00000010;
		}
	tlacB3 = tlacitko (PINB, 2, tlacB3);
	if (tlacB3 & 0b00000010)
		{
		PORTD ^= 0b00000100;
		}

	tlacB4 = tlacitko (PINB, 3, tlacB4);
	if (tlacB4 & 0b00000010)
		{
		PORTD ^= 0b00001000;
		}
}

//*********** /nekonečná smyčka ***********//
}
/////////////////////////////// END MAIN //////////////////////////
[/code]
Funguje přesně tak, jak bylo popsáno - jak bylo mé zadání. Jestli se někomu bude hodit, budu rád za smajlíka. Je možné také fci dát do extra souboru a includovat a pak je vlastní kód v hlavním programu velmi jednoduchý. Díky Vám za rady Pavel