Ukazka C++ pro děti

Pavel Hudecek edizon na seznam.cz
Úterý Březen 30 20:08:39 CEST 2021


Dobrý den všem,

Udělal jsem malou ukázku programu v C++ pro děti na kroužek, prosím o zhodnocení, zda v tom nejsou nějaký nevhodný věci:-)
(celé je to pro Xnano416 mající 1 LED a 1 tlačítko)
Otázka je, jak se to zmrší posláním v mailu…

#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU		(20000000UL/6UL)
#define LED_bit		5 // LEDka
#define TL_bit		4 // tlačítko
#define TEST_bit	3 // test přerušení osciloskopem
#define TEST_bit2	2 // test čekání osciloskopem

#define TL_jeStisk	((PORTB.IN & (1<<TL_bit)) == 0)

volatile unsigned int	ms=0;
volatile unsigned char	msSync=0;

void cekej(unsigned int n); // prototyp funkce - jen aby za ním bylo vidět jak funkce vypadá

class clTlac { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

public:
	clTlac() { // konstruktor - spusti se pri vytvoreni objektu ----------------------------
		PORTB.PIN4CTRL = PORT_PULLUPEN_bm;
		// zapnout pull-up pro tlačítko
	}

	void cek() { // cekani na stisk --------------------------------------------------------
		while(TL_jeStisk) cekej(0);
		while(!TL_jeStisk) cekej(0);
	}
	
	void stisk(); // udalost stisku tlacitka - jen deklarace
	
	bool stav=false;
};

class clLED { // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	
	friend void cekej(unsigned int n);
	// friend smí i do private
	
public:
	const unsigned int PMAX = F_CPU / 1000UL;
	const unsigned int P1 = PMAX / 100;	

	clLED() { // konstruktor - spusti se pri vytvoreni objektu -----------------------------
		PORTB.OUTSET	= 1<<LED_bit; // nastavit na 1, aby LEDka nesvítila od začátku
		PORTB.DIR = (1<<LED_bit) | (1<<TEST_bit) | (1<<TEST_bit2) ; // zapnout výstupy pro LED
		PORTB.PIN5CTRL = PORT_INVEN_bm; // Invertovat, aby LED svitila pri 1 (1 v datech)
		
		PORTMUX_CTRLC = PORTMUX_TCA02_ALTERNATE_gc;
		TCA0_SINGLE_CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc;
		TCA0_SINGLE_CTRLB = TCA_SINGLE_CMP2EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
		TCA0_SINGLE_CTRLC = 0;
		TCA0_SINGLE_CTRLD = 0;
		TCA0_SINGLE_PER = F_CPU / 1000UL;
		TCA0_SINGLE_INTCTRL = TCA_SINGLE_OVF_bm;
		TCA0_SINGLE_INTFLAGS = TCA_SINGLE_OVF_bm;
		TCA0_SINGLE_CMP2 = P1;
		TCA0_SINGLE_CTRLA |= TCA_SINGLE_ENABLE_bm;
		__asm__("sei");
	}

	void svitit(uint8_t proc) { // rozsvitit na zadane % -----------------------------------
		TCA0_SINGLE_CMP2 = P1 * proc;
		tim = 0;
	}
	
	void blikat(unsigned int t, unsigned char h, unsigned char l) { // ---------------------
		tim  = t;
		cnt  = 0;
		pwmH = P1 * h;
		pwmL = P1 * l;
		TCA0_SINGLE_CMP2 = pwmH;
	}
	
	unsigned int procToPWM(unsigned char n) { // prevod procent na PWM ---------------------
		return P1 * n;
	}
	
	
private:
	unsigned int pwmL = 0, pwmH = PMAX, tim  = 0, cnt  = 0;
	
	void togglePwm() { // prehodit PWM z low na hi / naopak --------------------------------
		if (TCA0_SINGLE_CMP2 == pwmH)
		TCA0_SINGLE_CMP2 = pwmL;
		else
		TCA0_SINGLE_CMP2 = pwmH;
	}

};

// Tady se podle tříd clTlac a clLED vytvoří objekty Tlacitko a Led. To spustí jejich konstruktory.
clTlac	Tlacitko;
clLED	Led;

void cekej(unsigned int n) { // ==============================================
	static bool tlacStickPred=false;
	
	__asm__("cli");
	ms=0;
	__asm__("sei");
	
	while(1) {
		PORTB.OUTTGL = (1<<TEST_bit2);
		
		if (msSync==1) { // ----------------------------------------
			msSync=0;
			
			Tlacitko.stav = TL_jeStisk;
			
			if (Led.tim>0) { // je zapnute blikani
				if (++Led.cnt>Led.tim) {
					Led.cnt=0;
					Led.togglePwm();
				}
			}
			
		} // if (msSync==1)
		
		if (!tlacStickPred && Tlacitko.stav) { // právě bylo stisknuto, vyvolat událost
			Tlacitko.stisk();
		}
		tlacStickPred=Tlacitko.stav;
		
		__asm__("cli");
		if (ms>=n) break;
		__asm__("sei");
	} // while(1)
	__asm__("sei");
}

// implementace obsluhy události stisk tlačítka
void clTlac::stisk() { // ===================================================
	static bool b=false;
	
	// zatímco v mainu se čekat musí, tady se naopak nesmí
	if (b) {
		Led.blikat(200, 100, 0);
	} else {
		Led.blikat(200, 60, 30);
	}
	b = !b;
}

int main(void) { // ###########################################################
	
	// tady nic neni: inicializace je v konstruktorech
	
	Led.blikat(100, 70, 20);
	
	while (1) { // ---------------------------------------------------

		// je jedno co tu je, hlavně že to obsahuje čekání
		cekej(100);
		Tlacitko.cek();
		
	}
}

ISR (TCA0_OVF_vect) { // =====================================================
	PORTB.OUTTGL = (1<<TEST_bit);
	ms++;
	msSync=1;
	
	TCA0_SINGLE_INTFLAGS = TCA_SINGLE_OVF_bm;
}

Díky,
PH
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20210330/44af1ca2/attachment.html>


Další informace o konferenci Hw-list