Hallo Leute,
bin noch relativ neu im µC Bereich und wollte nun zu Lernzwecken eine
ps2 Tastatur an den AVR schließen und die Signale per UART an einen PC
schicken.
Klappt auch theoretisch ganz gut, jedoch scheine ich falsche Daten zu
bekommen
Hier ertsmal mein code:
1
ISR(SIG_INTERRUPT1)
2
{
3
PORTB=(1<<PB0);//LED
4
5
while(PIND&(1<<PIND3));// wait for low clock
6
7
inti;
8
chardata;
9
//read 8 bit
10
for(i=0;i<8;i++)
11
{
12
while(!(PIND&(1<<PIND3)));// wait for clock high
13
while(PIND&(1<<PIND3));// wait for low clock
14
15
if(PIND&(1<<PIND0))
16
{
17
//PORTB = (1<<PB0); //LED
18
send_string("1");
19
}
20
else
21
{
22
send_string("0");
23
}}
24
}
25
26
27
intmain(void)
28
{
29
init_uart(UBRR_VAL);
30
31
DDRB=(1<<PB0);
32
DDRD&=~(1<<PD0);
33
DDRD&=~(1<<PD3);
34
35
//activate Pull up Resistor
36
PORTD|=(1<<PD0);
37
PORTD|=(1<<PD3);
38
39
//falling edge for INT1
40
MCUCR|=(1<<ISC11);
41
MCUCR&=~(1<<ISC10);
42
43
//Allow INT1
44
GICR|=(1<<INT1);
45
46
//Allow global interrupt
47
sei();
48
49
while(1)
50
{
51
}
52
53
return0;
54
}
Wenn ich die A Taste drücke empfange ich z.B "00000000" und beim Q
"01000000"
Kann mir da jemand Sagen was ich Falsch mache?
Zu allererst macht der Interrupt so eher wenig Sinn. Pro Interrupt
solltest du genau ein Bit lesen, ohne das rumgetue mit den whiles.
Vermutlich verpasst du mit deiner "Lösung" einige Bits.
Bei jedem low der Clock gibt es einen Bit. Wenn du dann nach dem low
erst auf ein low, ein high und ein low wartest, ist schonmal mindestens
ein Bit flöten, je nach Ausführungsgeschwindigkeit auch mehr.
Auch das Senden per UART sollte nicht im Interrupt geschehen. Das nimmt
nämlich wieder Zeit in Anspruch, während derer der Interrupt nicht
erneut feuern kann -> wieder verlorene Bits.
cygar schrieb:> Kann mir da jemand Sagen was ich Falsch mache?
Vermutlich brauchen deine send_strings im Interrupt zu lange.
Du kannst entweder die Uart wesentlich schneller als die PS2 machen,
oder dir überlegen, die du deine 0en und 1en am geschicktesten erst
irgendwo ablegst und dann erst schickst, wenn die ganze Empfangsaktion
schon gelaufen ist.
Siehe: Bitmanipulation
p.s.: KEIN array zum Speichern =)
p.p.s.: Wo hast du denn das mit dem SIG_INTERRUPT her? Das ist
steinalter, sogar veralteter Kram. Falls das aus einem Tutorial ist,
such dir ein anderes!
Zum Beispiel das AVR-GCC-Tutorial von hier.
Danke schonmal für eure Hilfe, hole jetzt jedes Bit einzeld per
Interrupt. Jedoch das mit der Bitmanipulation bekomme ich noch nicht hin
Vielen Danke
cygar
So hatte etwas wenig zeit aber mich jetzt noch mal ran gesetzt...
Frage jetzt pro interrupt nur 1 bit aber bekomme leiter komplett falsche
daten.
hier mein code:
Shifting per Variable sollte man vermeiden. Bei Fällen wie diesem hier
kann man ganz leicht Zyklen sparen, indem man es so programmiert.
1
ISR(INT1_vect)
2
{
3
staticuint16_ttmp;
4
PORTB=(1<<PB0);//LED
5
6
bit++;
7
//read bit
8
if(bit<=11&&bit>=1)
9
{
10
tmp<<=1;
11
if(PIND&(1<<PIND0))
12
tmp|=1;
13
}
14
if(bit==11)
15
{
16
a=tmp;
17
ausgabe=1;
18
bit=0;
19
tmp=0;
20
}
21
22
}
tmp habe ich hinzugefügt, da ich annehme, dass a global ist und du
damit die Datenübergabe ans Hauptprogramm realisierst. bit braucht
übrigens nicht global sein, falls es sonst nicht verwendet wird. Wenn
doch, dann aber volatile setzen, selbiges gilt für a und ausgabe.
Hallo Christopher,
danke für deinen Code, scheint bei mir aber noch nicht ganz zu klappen.
Die Werte die ich empfange scheinen falsch zu sein und sind auch nur
9bit land und nicht 11.
Bei meinem Code habe ich aber auch noch ein Problem hier habe ich 12
bits statt 11.
1
IST:
2
100001110000
3
SOLL:
4
10000111000
Man sieht das das 0. bit hier zu viel ist. Bei meiner Interruptroutine
zähle ich aber auch gleich am anfang den bit zähler hoch. Daran müsste
es liegen oder?
Wenn ich nun aber am ende der Routine den Zähler erhöhe, bekomme ich ich
zwar ab und zu den richtigen Wert beim drücken der A taste, jedoch
zwischendurch auch immer falsche Werte.. woran liegt das?
Vielen Danke!!
Dass du a gleichzeitig als temporäre Variable in der ISR und auch als
Übergabevariable verwendest ist schlecht. Je nachdem, wie schnell dein
Signal ist, kanns sein, dass du mit /a = 0/ nach send_string dir einen
Teil des ankommenden Signals löscht. Shiftest nun doch per Variable,
nagut, von mir aus.
Hab mir PS2 noch nie angeschaut aber du empfängst 11 Bit, verundest mit
Bits 9:1, shiftest dann um 1 nach rechts und hast dann Bits 9:1 des
Signals in den untersten 8 Bit von a. Schaut merkwürdig aus, aber
wenns passt, dann gut.
Was geht jetzt nicht?
cygar schrieb:> Mein Code funktioniert jetzt soweit wie er soll. Shifte aber immer noch> immer jedesmal wieder von vorne.
Den zweiten Satz kapier ich nicht.
PS: Übrigens wäre es besser, mit dem Input Capture eines Timers
zusätzlich zu den Signalflanken auch noch die Zeit zwischen 2 Flanken zu
messen. Somit kannst du schauen, ob das Signal von der Zeit her gültig
ist.
Hey,
alles funktionieren tut alles nur wurde mir auch von anderer Seite
gesagt das das shiften per Variable nicht so gut ist. Die Methode die du
gepostet hast scheint nicht ganz zu funktionieren und verstehe ich nicht
ganz.
Danke!!