Forum: Mikrocontroller und Digitale Elektronik Hilfe beim übersetzen von AVR-Bascom nach AVR-Assembler


von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

Das hier ist meine erstes projekt das ich in Assembler fertig stellen 
möchte. ( Deshalb seit bitte nicht so streng mit mir )

Also ich habe in AVR-Bascom ein kleines Programm mit ca. 20 zeilen. Ich 
möchte das Programm nun im AVR Studio mit Assembler benutzen und hab so 
meine Probleme das Ganze zu Übersetzen.


Das Programm macht folgendes (ist eine RGB LED Steuerung, mit PWM):

Es empfängt über die serielle Schnittstelle einen String mit 3 werten 
(Beispiel: "256 256 256" oder "145 45 220" oder "1 1 1"), die drei Werte 
sind RGB Werte von 0 - 256. die werten werden dann weiter an die 3 PWM 
Ports gegeben und Regeln diese.

Bascom Code:
1
$regfile "m8def.dat"
2
$crystal = 4000000
3
$baud = 9600
4
5
Ddrb = &B00001110
6
7
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
8
Config Timer2 = Pwm , Pwm = On , Compare Pwm = Clear Up , Prescale = 1
9
10
Dim Wert As String * 20                                     'Die Variable wo der Eingelesene Wert vom UART reinkommt
11
Dim Farbe(3) As String * 20                                 'Das Array mit den durch SPLIT einzelnen Farben
12
Dim Gruen As Integer                                        'Die Farben als Integer wo die String rein sollen
13
Dim Rot As Integer
14
Dim Blau As Integer
15
Dim Bcount As Byte
16
17
Do
18
  Input "" , Wert                                           'Hier wird der UART gelesen
19
  Bcount = Split(wert , Farbe(1) , " ")                     'Hier wird der eingelesene String in 3 Teile nämlich R, G und B gesplittet
20
  Rot = Val(farbe(1))                                       'Die Versuche einen String in ein Integer zu konvertieren
21
  Gruen = Val(farbe(2))
22
  Blau = Val(farbe(3))
23
  Compare1a = Rot                                           'Die PWM Kanäle
24
  Compare1b = Gruen
25
  Compare2 = Blau
26
Loop
27
End


So und jetzt möchte ich das ganze in AVR Assembler, hier mal was ich bis 
jetzt zu sammen habe:
1
.include "m8def.inc"
2
 
3
.def temp = R16
4
 
5
.equ F_CPU = 4000000                            ; Systemtakt in Hz
6
.equ BAUD  = 9600                               ; Baudrate
7
 
8
; Berechnungen
9
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
10
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
11
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
12
 
13
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
14
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
15
.endif
16
 
17
.org 0x00
18
        rjmp main
19
 
20
.org URXCaddr                                   ; Interruptvektor für UART-Empfang
21
        rjmp int_rxc
22
 
23
; Hauptprogramm
24
 
25
main:
26
 
27
    ; Stackpointer initialisieren
28
 
29
    ldi     temp, LOW(RAMEND)
30
    out     SPL, temp
31
    ldi     temp, HIGH(RAMEND)
32
    out     SPH, temp
33
 
34
    ; Port D = Ausgang
35
 
36
    ldi     temp, 0xFF
37
    out     DDRD, temp
38
 
39
    ; Baudrate einstellen
40
 
41
    ldi     temp, HIGH(UBRR_VAL)
42
    out     UBRRH, temp
43
    ldi     temp, LOW(UBRR_VAL)
44
    out     UBRRL, temp
45
 
46
    ; Frame-Format: 8 Bit
47
 
48
    ldi     temp, (1<<URSEL)|(3<<UCSZ0)
49
    out     UCSRC, temp
50
 
51
    sbi     UCSRB, RXCIE                    ; Interrupt bei Empfang
52
    sbi     UCSRB, RXEN                     ; RX (Empfang) aktivieren
53
    
54
    sei                                     ; Interrupts global aktivieren
55
    
56
loop:
57
    rjmp loop                               ; Endlosschleife
58
 
59
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde
60
 
61
int_rxc:
62
    push    temp                            ; temp auf dem Stack sichern
63
    in      temp, UDR                       ; empfangenes Byte lesen,
64
                                            ; dadurch wird auch der Interrupt gelöscht
65
    out     PORTD, temp                     ; Daten ausgeben
66
    pop     temp                            ; temp wiederherstellen
67
    reti                                    ; Interrupt beenden


So momentan wäre ich schon froh wenn ich die Drei Werte in so was wie 
einer variablen hätte oder noch besser wenn ich wüsste wie ich dies dann 
an die 3 Hardware PWM Ports übergebe

Schon mal vielen Dank im Voraus für die Hilfe!!!


MFG Daniel

von Winfried (Gast)


Lesenswert?

Stell lieber eine konkrete Frage, wo genau du nicht weiterkommst. Ein 
Teilproblem, was man schnell überblicken kann. Sich in dein ganzes 
Projekt einzudenken ist sehr zeitraubend... Wer hat schon Lust dazu?

von Daniel (Gast)


Lesenswert?

Also mir wäre schon sehr geholfen wenn ich wüsste wie ich in Assembler 
eine Zeichen kette also

"145 45 220"

Die als Trennzeichen ein Leerzeichen hat in 3 einzelne Variablen bekomme 
->

"145"
"45"
"220"

Die dann später an die PWM übergeben werden kann.

von Otto (Gast)


Lesenswert?

Wenn die Zeichenkette z. b. von einem Terminalprogramm kommt, nimmst Du 
ein Zeichen zur Synchtonisation (z. B. "#").

Im Assemblerprogramm wartest Du auf dieses Zeichen, nullst Du einen 
Zähler.

1. Nun schreibst Du die 3 folgenden ASCII-Zeichen in eine Variable. Die 
3 Zeichen müssen vorher von ASCII in Dezimal umgewandelt werden:

2. "ASCII-Zeichen" - $30 (Offset) = Wert

3. Die 3 folgenden Werte jeweils mit der Wertigkeit multiplizieren 
(100-10-1) und addieren.

Mit erreichen des Blank erhöhst Du den Zähler (der als Zeiger auf die 
Specherzelle dient) und wiederholst den Vorgang ab 1.

Otto

von spess53 (Gast)


Lesenswert?

Hi

>Also mir wäre schon sehr geholfen wenn ich wüsste wie ich in Assembler
>eine Zeichen kette also...

Als erstes musst du herausfinden, wie das Stringende gekennzeichnet 
wird. Üblicherweise CR($0D), LF($0A).
Dann brauchst du einen Puffer im RAM:

         .dseg
puffer:  .byte 20

In den werden die Zeichen, die die UART empfängt, bis zum Stringende 
gespeichert. Bei Stringende ein Flag setzen, das deiner 'loop' mitteilt, 
das ein String empfangen wurde. In der 'loop' bastelst du aus den 
ASCII-Zeichen die Werte und lädst die in die Register.

Was mir allerdings etwas schleierhaft ist: Timer1 ist ein 16-Bitter 
(0..65535) und Timer2 ein 8-Bitter (0..255).

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Ignoriere bitte den letzten Satz. Ich hatte die Zeile übersehen:

>Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm ....

MfG Spess

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.