Denkfehler? UART + Delay danach

Gast #3556761
Lesenswert?

Hallo! Ich habe ein Problem wo ich nach vielen Stunden einfach nicht 
weiter komme.

Ich bin mit einem ATMEGA32 am rumbasteln und möchte eine Box bauen 
welche Midi-Befehle nach Tastendruck sendet.

Hier ein Ausschnitt und eine kurze Erklärung dazu:
1
if ( !(PIND & (1<<PIND2)) )
2
  {
3
  
4
  
5
    PORTD |= (1<<PD7); //LED1 Einschalten
6
    PORTD &= ~( (1<<PD6) | (1<<PD5) ); //LED 2,3 Ausschalten
7
    send(192); // Sende 1. Byte "C0" (Kanalwelchsel)
8
    send(kanal); // Sende 2. Byte mit der int. var. Kanal
9
    _delay_ms(400); // Delay fkt. damit bei Tastendruck PIND2 nicht 1000 Midi-Befehle rausrattern...
10

11
  }

Im prinzip funktioniert alles. Jetzt wollte ich nur noch eine 
_delay_ms(200) Funktion beifügen um den Tastendruck ein wenig zu 
entprellen.
Also so habe ich mir das vorgestellt -> Taste wird gedrückt -> 1x "C0" 
senden -> 1x Kanal senden -> Warteschleife beginnen -> Taster wird 
losgelassen -> warteschleife hört auf.

Jetzt kommt es! Nach dem einfügen der delay fkt. sendet der auf einmal 
nicht mehr über den Uart. LED's werden geschaltet aber mehr nicht. In C 
wird doch alles "nacheinander" abgearbeitet oder sehe ich das irgendwie 
falsch?

Ich hoffe jemand kann mir bei dem Problem helfen.

Grüße
Gast #3556775
Lesenswert?

Schau Dir hier mal die Artikel und den Code von Peter Dannegger zur 
Tastenentprellung an. Es ist ohnehin ratsam, vor dem Posten mal zu 
schauen, ob es ähnliche Themen schon gegeben hat.

Allerdings gehst Du auch von einer falschen Annahme aus. Wenn die Taste 
losgelassen wird, dann wird die Funktion [c]delay_ms[\c] nicht 
unterbrochen. Sie wird weiter fortgesetzt, egal was Du mit der Taste in 
der Zwischenzeit machst.

Mir ist allerdings nicht klar, inwiefern Du "In C wird doch alles 
"nacheinander" abgearbeitet" als Begründung für Deine Annahme anführst. 
Vielleicht kann man Dir da noch helfen, wenn Du das mal näher erklärst.
Gast #3556780
Lesenswert?

1
void send(int c)
2
{
3
  while(!(UCSRA & (1<<UDRE)))  //Ausführen so lange wie UDRE gesetzt ist
4
  {
5
  }
6
  UDR = c; // Übergabe der der Midi-Bytes
7
}

Hier noch die Sendefunktion.

@Bitflüsterer - klar die delay-fkt. wird weiter "bearbeitet" bis die 
Zeit rum ist. Ich frage mich nur warum die 2 Midi befehle nicht gesendet 
werden wenn ich die delay-fkt. beifüge
Theoretisch sollten doch erst die 2 Bytes geschickt werden und danach 
soll die delay-fkt. erst starten.

Gruß
Gast #3557086
Lesenswert?

Nope, das ist genau mein Code welchen ich benutze.
Ohne die delay-fkt. klappt alles mit der delay-fkt. nicht mehr?!
Deswegen stelle ich mir immer noch die Frage was daran falsch ist, nach 
meinem uart Sendebefehl einfach eine delay-fkt. anzuhängen.
Das dieses "Entprellen" nicht sinnvoll ist sehe ich schon ein, ich 
möchte aber für meine weitere Bastelzukunft wissen warum das so nicht 
geht :)

Gruß
Gast #3557102
Lesenswert?

1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <util/delay.h>
4

5
void init_USART(void)
6
{
7
  UCSRB |= (1<<TXEN);          
8
  UCSRC |= (1<<URSEL)|(3<<UCSZ0);    
9
  UBRRH = 0;              //High=0
10
  UBRRL = 15;              //Low=15  bei 8MHz clock und 31250 Baud
11
}
12

13
void send(int c)
14
{
15
  while(!(UCSRA & (1<<UDRE)))  //Ausführen so lange wie UDRE gesetzt ist
16
  {
17
  }
18
  UDR = c; // Übergabe der der Midi-Bytes
19
}
20

21

22

23

24

25
void main()
26
{
27
init_USART();
28
int bank=0;
29
DDRA = 0xff; //PortA als Ausgang für BCD-Treiber setzen
30
PORTA = 0; //PortA --> 0 als Anfangswert schreiben (Bank anzeige)
31

32
DDRD = 0b11100011;  // Bit 2,3,4 Eingang setzen (Pin 16,17,18 Schalter für den Kanal) 
33
          // Bit 7,6,5 <-(LED S1,S2,S3)
34
          // Bit 0,1 Ausgang -> Uart
35
PORTD = 0b00011111; // Pullups schalten für taster
36

37

38

39

40
while(1)
41
{
42
  
43
  PORTA=bank;
44
  if ( !(PIND & (1<<PIND2)) )
45
  {
46
  
47
  
48
    PORTD |= (1<<PD7); //LED1 Einschalten
49
    PORTD &= ~( (1<<PD6) | (1<<PD5) ); //LED 2,3 Ausschalten
50
    send(192);
51
    send(bank);
52

53

54
  }
55

56
  if ( !(PIND & (1<<PIND3)) )
57
  {
58
    PORTD |= (1<<PD6); //LED2 Einschalten
59
    PORTD &= ~( (1<<PD7) | (1<<PD5) ); //LED 1,3 Ausschalten
60
    send(192);
61
    send(bank);
62

63
  
64
  
65
  }
66

67
  if ( !(PIND & (1<<PIND4)) )
68
  {
69
    PORTD |= (1<<PD5); //LED3 Einschalten
70
    PORTD &= ~( (1<<PD7) | (1<<PD6) ); //LED 1,2 Ausschalten
71
    send(192);
72
    send(bank);
73

74
  
75
  }
76

77
}
78
}

Bitteschööön
Gast #3557136
Lesenswert?

Sorry Leute, ich verstehe es gerade nicht?! Aber es klappt nun. Ich habe 
in meinem Programm noch vorher logische Abfragen über die Taster gemacht 
(bevor es in die While ging um zu entprellen...). Den ganzen klatsch 
habe ich weggelassen und dann mal wirklich meinen Code auf das 
"Grundgerüst" optimiert, so wie ich ihn gepostet habe. Ich sollte mich 
wohl mal mehr in die Thematik entprellen einlesen, denn so fummeleien 
führen wohl doch nicht zum gewünschten Ergebnis.

Nun klappt auch die delay-fkt. nach dem uart senden.
z.B.
1
if ( !(PIND & (1<<PIND3)) )
2
  {
3
    PORTD |= (1<<PD6); //LED2 Einschalten
4
    PORTD &= ~( (1<<PD7) | (1<<PD5) ); //LED 1,3 Ausschalten
5
    send(192);
6
    send(bank);
7
  _delay_ms(2000);
8

9
  
10
  
11
  }
 Die Zeit stimmt zwar nicht genau aber mit gefühl kann ich mir jetzt ein 
"einfaches" entprellen auf diese Art und weise bauen. Der µC soll 
sowieso nichts anderes machen als Befehle senden und an einen 
BCD-Treiber die aktuelle Bank-Zahl ausgeben.

Danke trotzdem!!!
Manchmal hilft es eine Nacht drüber zu schlafen :-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren