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:
.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
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?
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.
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
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