welcome: please sign in

Dateianhang 'multiswitch_encoder_robbe_einfach.c'

Herunterladen

   1 /**************************************************************************
   2 *Multiswitchmodul auf Basis eines Tiny44
   3 *Ausgabe ueber einen Pin mit 33K, sowie eine zweiten Pin fuer das Sync-Signal
   4 *
   5 *Sync entweder über ein einzelnes Sync-Signal, oder ueber PPM-Summe
   6 *
   7 *Eingang des PPM-Signals an PB2 (INT0), Ausgabe an PB0 (normal) und PB1 (Sync)
   8 *Alle Schalter sind per AD-Eingang angebunden
   9 *
  10 *
  11 *Int0 triggert auf neg. Flanke und startet Timer0. Der laeuft max. 2ms, falls in
  12 *der Zeit kein weiterer Int reinkommt, ist das Frame beendet, und der nächste Zustand 
  13 *wird an den Ausgang gegeben. Falls zur Laufzeit ein Int kommt, wird der Timer resetet
  14 *
  15 *
  16 ***************************************************************************/
  17 #include <avr/io.h>
  18 #include <avr/interrupt.h>
  19 
  20 
  21 /*************************************************************
  22 *MAKROS und #defines
  23 **************************************************************/
  24 #define FLAG_VARIABLE GPIOR0
  25 //FLAGS
  26 #define  	NEXT_VAL		0
  27 
  28 
  29 
  30 //Defines der Ausgangszustaende
  31 #define SW_SYNC		0
  32 #define SW_HIGH		1
  33 #define SW_LOW		2
  34 #define SW_MID		3
  35 
  36 //Schalterzuordnung
  37 #define AD_S1	0
  38 #define	AD_S2	1
  39 #define	AD_S3	3	
  40 #define	AD_S4	2
  41 #define	AD_S5	4
  42 #define	AD_S6	5
  43 #define	AD_S7	6
  44 #define	AD_S8	7
  45 
  46 
  47 //MAKROS
  48 #define CHECK_FLAG(A) (FLAG_VARIABLE & (1<<A))
  49 #define DEL_FLAG(A)	(FLAG_VARIABLE &= ~(1<<A))
  50 #define SET_FLAG(A)	(FLAG_VARIABLE |= (1<<A))
  51 //Schaltereingaenge
  52 
  53 
  54 #define OBERE_SCHRANKE		158
  55 
  56 #define UNTERE_SCHRANKE		78
  57 
  58 #define OUT_PORT	PORTB
  59 #define OUT_DDR		DDRB
  60 #define	OUT_PIN		PB0
  61 #define SYNC_PIN	PB1
  62 
  63 
  64 /*************************************************************
  65 *ISR
  66 **************************************************************/
  67 ISR(INT0_vect)
  68 	{	
  69 	//Timer starten oder zuruecksetzen
  70 	//Timer-Int-Flag loeschen
  71 	TIFR0 |= (1<<TOV0);
  72 	//Zaehlerregister loeschen
  73 //alte Version
  74 //	TCNT0 = 208;		//Preset, um Periode von 3ms zu erreichen
  75 //	TCCR0B |= (1<<CS01) | (1<<CS00);	//Prescaler 64, Timer startet
  76 //neuere Version -> kleinere Pause
  77 
  78 	//Timer reset
  79 	TCNT0 = 0;
  80 	TCCR0B |= (1<<CS01);	//Prescaler neu setzen
  81 	
  82 	}
  83 
  84 
  85 ISR(TIM0_OVF_vect)
  86 	//Timer anhalten, und neuen Zustand an den Ausgang geben, bzw. das Flag setzen
  87 	{
  88 	//Timer anhalten -> Prescaler loeschen
  89 	TCCR0B &= 0xF8;
  90 
  91 	SET_FLAG(NEXT_VAL);
  92 	}
  93 
  94 
  95 
  96 
  97 /*************************************************************
  98 *funktionen
  99 **************************************************************/
 100 
 101 void init_ports(void)
 102 	{
 103 	//Schalterport als Eingang;
 104 	DDRA = 0x00;
 105 	
 106 	DDRB  |= (1<<PB0) | (1<<PB1);		//die beiden Ausgangspins als Ausgang setzen
 107 	}
 108 
 109 void set_Ausgang(uint8_t zustand)
 110 	{
 111 	switch(zustand)
 112 		{
 113 		case SW_SYNC:
 114 			OUT_PORT &= ~(1<<SYNC_PIN);
 115 			OUT_DDR |= (1<<SYNC_PIN);
 116 			break;
 117 		case SW_LOW:
 118 			//Sync abschalten
 119 			OUT_DDR &= ~(1<<SYNC_PIN);
 120 			OUT_PORT &= ~(1<<SYNC_PIN);
 121 			//Pin auf Ausgang und low						
 122 			OUT_DDR |= (1<<OUT_PIN);
 123 			OUT_PORT &= ~(1<<OUT_PIN);
 124 			break;
 125 		case SW_MID:
 126 			//Sync abschalten
 127 			OUT_DDR &= ~(1<<SYNC_PIN);
 128 			OUT_PORT &= ~(1<<SYNC_PIN);	
 129 			//Pin auf Eingang und Pullup aus
 130 			OUT_DDR &= ~(1<<OUT_PIN);
 131 			OUT_PORT &= ~(1<<OUT_PIN);		
 132 			break;
 133 		case SW_HIGH:
 134 			//Sync abschalten
 135 			OUT_DDR &= ~(1<<SYNC_PIN);
 136 			OUT_PORT &= ~(1<<SYNC_PIN);
 137 			//Pin auf Ausgang und high						
 138 			OUT_DDR |= (1<<OUT_PIN);
 139 			OUT_PORT |= (1<<OUT_PIN);
 140 			break;		
 141 		default:
 142 			//Sync abschalten
 143 			OUT_DDR &= ~(1<<SYNC_PIN);
 144 			OUT_PORT &= ~(1<<SYNC_PIN);
 145 			//Pin auf Eingang und Pullup aus
 146 			OUT_DDR &= ~(1<<OUT_PIN);
 147 			OUT_PORT &= ~(1<<OUT_PIN);	
 148 			break;
 149 		}
 150 	}
 151 
 152 
 153 void init_int(void)
 154 	{
 155 	DDRB &= ~(1<<PB2);
 156 //	PORTB |= (1<<PB2);						//Pullup an ->nicht noetig, da extern vorhanden
 157 	MCUCR |= (1<<ISC01);					//triggern auf fallende Flanke
 158 	GIMSK |= (1<<INT0);						//Int freigeben
 159 	}
 160 
 161 
 162 void init_timer0(void)
 163 	{
 164 	//Normal-Modus, Prescaler 8, OFV-Int an
 165 //	TCCR0B |= (1<<CS01);			//Prescaler 8, wird erst durch den Int gestartet
 166 	TIMSK0 |= (1<<TOIE0);			//OFV-Int angeschaltet
 167 	}
 168 
 169 
 170 void init_ADC(void)
 171 	{
 172 	//Digital-Puffer abschalten
 173 	DIDR0 = 0xFF;
 174 
 175 	ADCSRB |= (1<<ADLAR);				//AD-Ergebnisse linksbuendig ->fuer ein 8-Bit-Ergebniss nur ADCH noetig
 176 	ADCSRA |= (1<<ADPS1);				//prescaler 4 ->250kHz		// | (1<<ADPS0);	//Prescaler auf 8 setzen
 177 	ADCSRA |= (1<<ADEN);				//AD-Wandler anwerfen
 178 
 179 	//Referenzspannung: VCC
 180 
 181 	ADCSRA |= (1<<ADSC);              		// eine ADC-Wandlung, um den Wandler warmlaufen zu lassen
 182 	while ( ADCSRA & (1<<ADSC) ) {}  		// auf Abschluss der Konvertierung warten 
 183 	
 184 	}
 185 
 186 /**/
 187 
 188 uint8_t ADCRead(uint8_t mux)		//liefert nur 8 Bit zurueck
 189 	//AD-Wandler-Funktion, bekommt den Kanal übergeben, liefert das Ergebnis zurück
 190 	{
 191 	uint8_t result;
 192 	result = 0;         			
 193 	ADMUX = mux;           // Kanal waehlen (falls andere Referenz als VCC -> aufpassen, liegt im gleichen register)
 194 	//Eigentliche Messung
 195 	ADCSRA |= (1<<ADSC);            	// eine Wandlung "single conversion"
 196 	while ( ADCSRA & (1<<ADSC) ) {}		// auf Abschluss der Konvertierung warten
 197 
 198 	result = ADCH;		   				//die obersten 8 Bit interessant -> nur das High-Byte lesen
 199  	return  result;
 200 	}
 201 
 202 uint8_t get_schalter_richtung(uint8_t schalter)
 203 	//Passt die Richtung der Schalter an, da sie durchs routen unterschiedlich an VCC ung GND hängen
 204 	//-> Schalter nach oben ergibt in jedem Fall "low", Schalter nach unten "high"
 205 	//-> wie beim Robbe-Orginal
 206 	{
 207 	if ((schalter == 1) || (schalter == 2) || (schalter == 3) || (schalter == 4))
 208 		{return 1;}
 209 	else
 210 		{return 0;}
 211 	}
 212 
 213 
 214 /*************************************************************
 215 *Main
 216 **************************************************************/
 217 int main(void)
 218 	{
 219 	uint8_t frame_counter;
 220 	uint8_t ad_ergebnis;	
 221 
 222 	frame_counter = 0;
 223 	ad_ergebnis	= 0;
 224 
 225 	FLAG_VARIABLE = 0;
 226 
 227 	init_ports();
 228 	init_ADC();
 229 	init_int();
 230 	init_timer0();
 231 	set_Ausgang(0xff);
 232 
 233 	sei();
 234 
 235 	for(;;)
 236 		{
 237 
 238 /**/
 239 		if(CHECK_FLAG(NEXT_VAL))	//Timer abgelaufen, neues Ergebniss anlegen
 240 			{
 241 			DEL_FLAG(NEXT_VAL);
 242 			frame_counter++;
 243 			switch (frame_counter)
 244 				{
 245 				case 1:
 246 					ad_ergebnis = ADCRead(AD_S1);
 247 					break;
 248 				case 2:
 249 					ad_ergebnis = ADCRead(AD_S2);
 250 					break;
 251 				case 3:
 252 					ad_ergebnis = ADCRead(AD_S3);
 253 					break;
 254 				case 4:
 255 					ad_ergebnis = ADCRead(AD_S4);
 256 					break;
 257 				case 5:
 258 					ad_ergebnis = ADCRead(AD_S5);
 259 					break;
 260 				case 6:
 261 					ad_ergebnis = ADCRead(AD_S6);
 262 					break;
 263 				case 7:
 264 					ad_ergebnis = ADCRead(AD_S7);
 265 					break;
 266 				case 8:
 267 					ad_ergebnis = ADCRead(AD_S8);
 268 					break;
 269 				default:
 270 					frame_counter = 0;	//->Sync ausloesen
 271 					break;
 272 				}		
 273 			if(frame_counter == 0)		//->Sync
 274 				{set_Ausgang(SW_SYNC);}
 275 
 276 			else	//kein sync, entsprechend Ausgang setzen
 277 				{
 278 				if (ad_ergebnis > OBERE_SCHRANKE)
 279 					{
 280 					if (get_schalter_richtung(frame_counter))
 281 						{set_Ausgang(SW_HIGH);}
 282 					else
 283 						{set_Ausgang(SW_LOW);}
 284 					}
 285 				else
 286 					{
 287 					if (ad_ergebnis < UNTERE_SCHRANKE)
 288 						if (get_schalter_richtung(frame_counter))
 289 							{set_Ausgang(SW_LOW);}
 290 						else
 291 							{set_Ausgang(SW_HIGH);}
 292 					else
 293 						{set_Ausgang(SW_MID);}
 294 					
 295 					}
 296 				}
 297 			}	//if(CHECK_FLAG(NEXT_VAL))
 298 		}	//for(;;)
 299 	
 300 	return 0;
 301 	}

Gespeicherte Dateianhänge

Um Dateianhänge in eine Seite einzufügen sollte unbedingt eine Angabe wie attachment:dateiname benutzt werden, wie sie auch in der folgenden Liste der Dateien erscheint. Es sollte niemals die URL des Verweises ("laden") kopiert werden, da sich diese jederzeit ändern kann und damit der Verweis auf die Datei brechen würde.
  • [laden | anzeigen] (2017-06-12 18:26:24, 7.2 KB) [[attachment:multiswitch_encoder_robbe_einfach.c]]
  • [laden | anzeigen] (2017-06-12 18:26:24, 17.8 KB) [[attachment:multiswitch_robbe_einfach_brd.png]]
  • [laden | anzeigen] (2017-06-12 18:26:24, 22.7 KB) [[attachment:multiswitch_robbe_einfach_sch.png]]
  • [laden | anzeigen] (2017-06-12 18:26:24, 15.8 KB) [[attachment:mutiswitch-robbe_einfach.zip]]
 Alle Dateien | Ausgewählte Dateien: löschen verschieben auf Seite kopieren auf Seite

Sie dürfen keine Anhänge an diese Seite anhängen!