Forum: Mikrocontroller und Digitale Elektronik S-Bus-Dekoder - Interpretations / Programm / Verständnisproblem


von Andreas D. (dandy)


Angehängte Dateien:

Lesenswert?

Hallöchen, ich bräuchte mal wieder Hilfe bei einem S-Bus Dekoder.

Ich möchte einen S-Bus -> PWM - Konverter programmieren. Dazu, versuche 
ich nun erst einmal den S-Bus zu dekodieren, um auf einem Display 
dezimal den Wertebereich jedes Kanals angezeigt zu bekommen. Doch egal 
was ich wie programmiere, ich bekomme immer nur Zahlenmüll angezeigt. 
Vielleicht habe ich die spezifikationen des Busses nicht verstanden, 
oder ich mache programmtechnisch einen Fehler.. ?!

Nun, zu meiner Hardware:

Ich benutze zum testen einen ATMega 16 mit 16 MHz externem 
Taktoszillator. Da der S-Bus ja ein invertierter serieller Bus sein 
soll, gebe ich das Signal, generiert aus einem FrSky X8R Empfänger 
invertiert auf den RX des Mega 16. (Bild - S-Bus-invert.png)
Ein Display 2x16 hängt am Port-C.

Die Hardware des Prozessors initialisiere ich wie folgt:
1
reset:        ldi r16, HIGH (RAMEND)
2
          out SPH, r16
3
          ldi r16, LOW(RAMEND)
4
          out SPL, r16      ;Stack
5
          ldi r16, 0xFF
6
          out DDRC, r16      ;Port-C-Ausgang
7
          com r16
8
          out PORTC, r16      ;Port-C-Low
9
          out DDRD, r16      ;Port-D-Eingang
10
          ldi r16, 0b11111110    
11
          out PORTD, r16      ;Pullups setzen, bis auf RX - PD-0
12
          ldi r16, 0b00000001
13
          out DDRB, r16      ;PB-0 ausgang, da dort eine LED hängt
14
          clr r16
15
          out PORTB, r16      
16
          out UBRRH, r16      ;Bit-Rate-Register-High nullen
17
          ldi r16, 9
18
          out UBRRL, r16      ;Bit Rate Register Low = 9 (UBBR = ( fosc/16*Baud) -1 ) = (16000000 / (16*100000)) = 10 -1 = 9 )
19
          ldi r16, 0b10010000
20
          out UCSRB, r16      ;RX Enable und RX Complete Interrupt Enable
21
          ldi r16, 0b10101110
22
          out UCSRC, r16      ;Gerade Paritaet / 2 Stop Bits (Obwohl für empfänger laut Datenblatt nicht konfigurierbar) und 8 Bit Charakter Size

Die UART (RX-Complete) Interrupt Routine (Zurzeit nach vielen 
versuchen):
1
uartrxok:      in r2, SREG
2
          push r20
3
          push r21
4
          push r22
5
          push YL
6
          push YH
7
          sbrc r19, 0      ;gesetzt wenn Startbyte empfangen wurde
8
          rjmp getdata    ;dann empfange Datenbates der einzelnen Kanäle
9
          in r21, UDR      ;Datenregister einlesen
10
          cpi r21, 0b11110000  ;mit Startbyte vergleichen
11
          brne enduartint    ;kein Startbyte dann ende
12
          sbr r19, 1      ;Statusbit für datenempfang setzen
13
          ldi r22, 24      ;Zähler für 24 Bytes einstellen
14
          sts $006C, r22    ;Zähler sichern
15
          ldi YL, LOW ($0070)  ;Ram Zeiger Setzen
16
          ldi YH, HIGH($0070)
17
          sts $006A, YL    ;Ram Zeiger sichern
18
          sts $006B, YH
19
          cbi PORTB, 0    ;LED aus schalten
20
          rjmp enduartint    ;und ende
21
getdata:      in r20, UDR      ;Datenregister einlesen
22
          lds YL, $006A    ;Aktuellen Ram-Zeiger laden
23
          lds YH, $006B
24
          lds r22, $006C    ;Aktuellen Byte Zähler laden
25
          st Y+, r20      ;Empfangenes Datenbyte ins Ram schreiben und Ram Zeiger um 1 erhöhen
26
          sts $006A, YL    ;Ram Zeiger wieder sichern
27
          sts $006B, YH
28
          dec r22        ; Byte Zähler um 1 verringern
29
          breq enddata    ;wenn alle bytes empfangen dann ->enddata
30
          sts $006C, r22    ;sonst Byte Zähler wieder sichern
31
          rjmp enduartint    ;und ende
32
enddata:      cbr r19, 1      ;Statusbyte wieder löschen
33
          sbr r19, 2      ;Statusbit für fertigen Empfang setzen
34
          sbi PORTB, 0    ;LED einschalten
35
enduartint:      pop YH
36
          pop YL
37
          pop r22
38
          pop r21
39
          pop r20
40
          out SREG, r2
41
          reti

Nachdem alle bytes empfangen wurden versuche ich einzig und alleine die 
Daten für den ersten Kanal heraus zu holen. Da die daten ja nahtlos 
zusammenhängen sollen (so wie ich es verstanden habe) und 11 Bit 
betragen und somit aus den ersten 8 Bits des ersten Bytes plus den 3 
Bits des zweiten Bytes bestehen und das höchstwertige Byte Rechts liegen 
soll schiebe ich die bits folgendermaßen in der nächsten Routine 
zurecht. Erst fünf mal nach rechts und dann 11 bits links in 2 leere 
register um das höchstwertige bit wieder links für die dezimal 
umrechnung zu haben)
1
ortbits:      push YL
2
          push YH
3
          push r20
4
          push r21
5
          push r22
6
          ldi YL, LOW ($0070)
7
          ldi YH, HIGH($0070)
8
          clr r21
9
          clr r22
10
          ld r17, Y+
11
          ld r18, Y
12
          ror r17
13
          ror r18
14
          ror r17
15
          ror r18
16
          ror r17
17
          ror r18
18
          ror r17
19
          ror r18
20
          ror r17
21
          ror r18
22
          ldi r20, 11
23
loop10:        ror r17
24
          ror r18
25
          rol r21
26
          rol r22
27
          dec r20
28
          brne loop10
29
          sts $0090, r21
30
          sts $0091, r22
31
          pop r22
32
          pop r21
33
          pop r20
34
          pop YH
35
          pop YL
36
          ret

danach erfolgt die dezimal Umwandlung dieser beiden ergebnis bytes (aus 
den Ram Zellen $0090 und $0091) und werden aufs Display ausgegeben. (Das 
funktioniert auch) Man sieht auch, dass sich die Zahlen ändern, wenn ich 
den Knüppel für kanal 1 bewege, aber eben total wirr, als wenn... tja 
wenn ich das wüsste... Als wenn ich die daten falsch interpretiere... 
als wenn der Uart nicht richtig konfiguriert und ich keine Ahnung welche 
Bytes erhalte... Als wenn ich falsch sortiere.. oder oder oder. Ich 
weiss es nicht. Mittlerweile verstehe ich nur noch Bahnhof.

Vielleicht hat ja jemand von euch den Bus schon erfolgreich über den 
UART decodiert und kann mir mal stützend unter die Arme greifen. Wäre 
echt dankbar, denn ich weiss grad nicht mehr weiter, geschweige denn was 
ich falsch mache.

Falls noch weitere infos benötigt werden, bitte sagen. Ansonsten erst 
mal besten Dank für eure mühe.

Gruß, Andy

von Andreas D. (dandy)


Lesenswert?

Falls es hilft, das S-Bus protokoll habe ich aus folgendem PDF...

S-BUS protocol
Note- Much of this first page is from mbed, but it was written for the 
original s.bus using the "FASST MULT" mode. Here's the original page 
link-
http://mbed.org/users/Digixx/notebook/futaba-s-bus-controlled-by-mbed/
The protocol is 25 Byte long and is send every 14ms (analog mode) or 7ms 
(highspeed mode). One Byte = 1 startbit + 8 databit + 1 paritybit + 2 
stopbit (8E2), baudrate = 100'000 bit/s, so one bit takes 10 
microseconds.
The highest bit is send first, so data "00000000001" = 1024
The logic is inverted out of the receiver.
[startbyte] [data1] [data2] .... [data22] [flags][endbyte]
startbyte = 11110000b (0xF0)
data 1-22 = [ch1, 11bit][ch2, 11bit] .... [ch16, 11bit] (ch# = 0 bis 
2047) channel 1 uses 8 bits from data1 and 3 bits from data2 channel 2 
uses last 5 bits from data2 and 6 bits from data3 etc.
flags = bit7 = ch17 = digital channel (0x80) bit6 = ch18 = digital 
channel (0x40) bit5 = Frame lost, equivalent red LED on receiver (0x20) 
bit4 = failsafe activated (0x10) bit3 = n/a bit2 = n/a bit1 = n/a bit0 = 
n/a
endbyte = 00000000b (Prior to the s.bus2 capable receivers, and the 
R7003SB)

(as captured)
100001111100111111111100111011111000111111000000111111111100100111111100 
11110111100
011111110100011111111110011011111100011111011100011111111000011111111110 
01110111110
001111110110001111111111001011111110001111011110001111111010001111111111 
00110111111
0001111101110001111111100001111111111001111111111

(inverted before FC input)
011110000011000000000011000100000111000000111111000000000011011000000011 
00001000011
100000001011100000000001100100000011100000100011100000000111100000000001 
10001000001
110000001001110000000000110100000001110000100001110000000101110000000000 
11001000000
1110000010001110000000011110000000000110000000000

(inverted before FC input and grouped in 12 bit bytes)
011110000011 (Start byte)
000000000011 (data 1)
000100000111 CH1
000000111111 CH2
000000000011 CH3
011000000011 CH4
000010000111 CH5
000000010111 CH6
000000000011
001000000111 CH7
000001000111 CH8
000000001111
000000000011 CH9
000100000111 CH10
000000100111 CH11
000000000011
010000000111 CH12
000010000111 CH13
000000010111 CH14
000000000011
001000000111 CH15
000001000111 CH16
000000001111 (data 22)
000000000011 (flags byte) DCH1, DCH2, Frame lost, failsafe activated, 
rest are NA
000000000011 (11 added by dead space between frames)

von Andreas D. (dandy)


Lesenswert?

Hat sich erledigt. Habs hin bekommen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.