PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : µC über rs232 an excel



freddy0815
08.02.2005, 14:00
hallo,

hab ein programm geschrieben, das 3 werte über rs232 an excel schickt, sobald man von excel aus zb auf nen knopf drückt. wenn ich das prog auf nem atmega32 im starterkit laufen lasse, funktioniert alles perfekt.

jetzt habe ich ne platine mit nem smd atmega32. über isp hab ich den programmiert. wenn ich jetzt über rs232 in excel die werte einlesen will, dann gibt er zwar 3 werte aus, wie er auch soll, aber leider nicht die richtigen. statt 54 gibt er zb 248 aus. die werte stehen im daten register.

hier mal der quellcode


.NOLIST
.INCLUDE "D:\m32def.inc"
.LIST

; Programmbeschreibung: Serielle Schnittstellenübertragung
; Das Programm sendet eine bestimmte Anzahl von Bytes über RS232.
; Sobald an RX (Port D Pin1) etwas (ein Byte) empfangen wird
; (zB durch ein Tastendruck am PC), wird eine Interruptroutine gestartet,
; die aus dem Datenspeicher (Beginn: Adresse $62) ein Byte nach dem anderen sendet.
; Wobei das erste Byte (in $60) die Anzahl der Bytes, die zu senden sind, angibt.
; Steht zB in $60 'C8' werden die nachfolgenden 200 Bytes gesendet.

; Maximal 1500 Messwerte ($5DC)

; Datenübertragung: Baudrate 4800, keine Parität, 8 Datenbits + 1 Stopbit

; ist URSEL in UCSRC '0' wird für I/O UBRRH verwendet. Bei '1' UCSRC.
; Hier können Anzahl der Daten- und Stopbits gesetzt werden

;-----Konstanten-----
.equ fck = 4000000
.equ baudrate = 4800

.equ baudconst = (fck / (baudrate * 16)) - 1

.equ rs_recv = 0 ; 1 = Byte empfangen ; 0 = kein Byte empfangen
.equ adresse_anzahl = $60 ; Adresse an der die Anzahl der Werte steht
.equ adresse_anzahl_high = $61
.equ startadresse_werte = $62 ; Adresse für der Start der Werte

;-----Variablen-----
.def byte_send = R16 ; Register für zu sendente Bytes
.def counter_send_low = R17 ; Register für die Anzahl der zu sendenten Bytes <256 Werte
.def counter_send_high = R18; Register für die Anzahl der zu sendenten Bytes >256 Werte
.def w = R19 ; Arbeitsregister
.def wi = R20 ; Interrupt-Arbeitsregister
.def rs_buf = R21 ; Buffer für empfangenes Byte
.def a_flag = R22 ; Flagregister

;----- Interrupt-Adressen -----
.cseg
.org $0000
rjmp main

.org $01A ; RS232 Empfangsinterrupt
rjmp rs232_recv ; RS232 Behandlungsroutine wenn etwas empfangen wird
; im UCSRA Register liegt RXC auf "1"

;----- I/O-Port Initialisierung -----
hdw_init:
ldi w, 0b11111111
out PORTD, w ; alle Pins am Port D auf 1 setzen
ldi w, 0b11111110
out DDRD, w ; Datenrichtung am Port D festlegen: 1 = Ausgang; 0 = Eingang
; Pin 1 am Port D Empfangen (= 0) RX
; Pin 2 am Port D Senden (= 1) TX


; Port B zB für LED-Anzeige
ldi w, 0b11111111
out PORTB, w ; alle Pins am Port B auf 1 setzen
ldi w, 0b11111111
out DDRB, w ; Datenrichtung am Port B = Ausgang
;----- Test für Daten senden -----
; Datenspeicher mit Werten füllen
test:
ldi w, 0b00000011 ; insgesamt werden 3 werte geschickt
sts $60, w
ldi w, 0b00000001
sts $61, w
ldi w, 0b11110000 ; 1.wert der an excel geschickt wird
sts $62, w
ldi w, 0b00000001 ; 2.wert der an excel geschickt wird
sts $63, w
ldi w, 0b11111110 ; 3.wert der an excel geschickt wird
sts $64, w
;----- UART Initialisierung -----
uart_init:
ldi w, baudconst
out UBRRL, w ; UBRR = USART Baud Rate Register
ldi w, 0
out UBRRH, w
ldi w, 0b00011000
out UCSRB, w ; RXEN und TXEN setzen
sbi UCSRB, RXCIE ; RS232 Interrupt freigeben

sei ; gibt alle Interrups frei
ret

;----- Routine für empfangene Bytes -----
rs_rec_up:
cbr a_flag, 1 << rs_recv; durch '1<<' wird eine '1' n-mal nach links geschoben
; für rs_recv = 0: 0b00000001
; für rs_recv = 1: 0b00000010
; rs_recv ist eine Konstante ("0")
; --> das erste Bit in a_flag wird somit gelöscht

mov w, rs_buf ; empfangenes Byte in w
out PORTB, w ; an Port B ausgeben (LED Anzeige)
rcall rs_send
ret

;----- Routine zum Senden von Bytes -----
rs_send:
rcall count_bytes ; übernimmt die Anzahl der zu übertragenen Werte
clr R27
ldi R26, startadresse_werte ; Low-Byte des Zeigeregisters X mit der Adresse $62 beschreiben
send_loop:
rcall read_bytes ; liest die Werte ein
udre_loop:
sbis UCSRA, UDRE ; überprüft, ob UDRE im Register UCSRA gesetzt ist, wenn ja (UDRE=1) überspringen
; UDRE = 1 Sender frei, UDRE = 0 Sender besetzt
rjmp udre_loop ; solange Sender frei
out UDR, byte_send ; Wert senden
dec counter_send_low ; erniedrigt den low-Zähler um 1
brne send_loop ; solange bis Zähler = 0
dec counter_send_high ; erniedrigt den high-Zähler um 1 (= 16bit Zähler)
brne send_loop ; solange bis Zähler = 0
ret ; wenn Zähler = 0 alle Werte gesendet
count_bytes:
clr R27 ; High-Byte des Zeigeregisters X löschen
ldi R26, adresse_anzahl ; Low-Byte des Zeigeregisters X mit der Adresse $60 beschreiben
ld counter_send_low, x+ ; läd in counter_send_high die Anzahl der zu sendenten Bytes für >256 Messwerte
ld counter_send_high, x ; läd in counter_send_low die Anzahl der zu sendenten Bytes für <256 Messwerte
ret
read_bytes:
ld byte_send, x+ ; läd in byte_send das zu sendente Byte und erhöht den Zeiger x um 1
ret

;----- Interruptroutine zum Empfangen von Bytes -----
rs232_recv:
in wi, SREG ; CPU-Status
push wi ; wi in Stackpointer

in wi, UDR ; Byte vom Empfänger laden
mov rs_buf, wi ; zwischenspeichern
sbr a_flag, 1<<rs_recv ; durch '1<<' wird eine '1' n-mal nach links geschoben
; für rs_recv = 0: 0b00000001
; für rs_recv = 1: 0b00000010
; rs_recv ist eine Konstante ("0")
; --> das erste Bit in a_flag wird somit gesetzt

pop wi ; Stackpointer zurück in wi
out SREG, wi ; zurück zur CPU

reti ; Return from Interrupt

;----- Hauptprogramm -----
main:
ldi w, HIGH(RAMEND) ; RAMEND: Speicherende des Chips
out SPH, w ; in Stackpointer schreiben
ldi w, LOW(RAMEND) ; RAMEND: Speicheranfang des Chips
out SPL, w ; in Stackpointer schreiben
clr a_flag ; "0" = nichts wurde empfangen
rcall hdw_init ; Hardware Initialisierung
ldi w, 0b01010101
out PORTB, w ; wenn jede 2. LED leuchtet = empfangsbereit

;----- Endlosschleife -----
; wartet auf ein Empfangsinterrupt
endlos:
sbrc a_flag, rs_recv ; wenn was empfangen wurde, dann rs_rec_up, ansonsten überspringen
rcall rs_rec_up
rjmp endlos ; Dauerschleife

die hardware muss eigentlich stimmen. kontakte alle überprüft (mehrmals). laufen lass ich das ganze mit dem internen quarz (1mhz mit 64ms)

kann das am internen quarz liegen?
steh grad ratlos rum...

danke mal
freddy0815

Vitis
08.02.2005, 20:57
Haste auch den COM passend konfiguriert?

bluebrother
09.02.2005, 17:03
hmm, was ich an der Ganzen Geschichte nicht kapier ist was da Excel mit zu tun hat. Tut sich denn was wenn du ein einfaches Terminal dranhängst? Ich hab keine Ahnung wie das mit Excel und der seriellen Schnittstelle tun soll ...

Vitis
09.02.2005, 19:12
Naja, Excel kann man mit VBasic-MOdulen erweitern, die dann auch
z.B. auf den COM zugreifen können.
Für mich stellt sich aber die Frage, obs nicht sinnvoller wär
mit VBasic ein Progrämmchen zu entwerfen, das dann die Werte in
ne Access Datenbank überträgt, dann is man n bissl flexibler was die
Weiterverwendung angeht.

PicNick
09.02.2005, 19:26
Na, da möcht ich doch wetten drauf.
Aber es kommt drauf an, was wann will, logo

Hellmut
09.02.2005, 21:57
Hallo Freunde

Was für Kode braucht man auf dem PC um die daten vom COm ins Excel zu senden?

Hellmut
09.02.2005, 22:06
Hallo Freunde

Das Thema beschäftigt mich. Ich würde eigentlich sehr gerne das Excel zum darstellen von Ergebnissen in Form von Kurven in einem Chart angezeigt haben wollen. Ich denke hier z.B. die neue Motorsteuerung an der stupsi, Kjion und Frank arbeiten. Wenn an z.B Werte einer Temeperatur-Überwachung am PC erfassen möchte und als Chart dargestellt während der Messung die Kurve updaten. geht das und was braucht man?

PicNick
10.02.2005, 07:19
Moin, du kannst den COM1-Input in eine File im CSV-Format mitzuloggen. dieses file kann man mit einfach EXcel aufmachen. Besser is natürlich Import mit VBasic direkt im Excel, aber da müßt ihr Freddy oder Vitis fragen. mfg

Vitis
10.02.2005, 08:36
@Helmut, klar geht das, keine große Sache

Da braucht man garnicht viel dazu,
Excel, VBasic oder Access
ICh für meinen Teil würd's wie gesagt direkt in Basic machen,
da man da eine EXE Datei mit machen kann, die dann auch auf Rechnern
ohne den anderen Microsoft gesumse laufen kann.
Die Daten einfach wie gesagt in nen CSV oder DBF oder MDB laufen lassen
und in Excel importieren oder im MDB ne Chartansicht der Datenbank
einbauen und fertig.
VBasic bringt an sich schon alles mit was man braucht um ein
"Terminalprogramm" zu realisieren, das mitlogt.
COM-Schnittstelle kann direkt programmiert werden und Datenbankanbindung über Jet-Modul oder Ausgabe in Datei
sind serienmäßig. (zumindest bei VB6).
Man muß sich nur n bisschen reinfummeln.
Bei mir ists da kein besonderes Problem, da ich eh vorwiegend in Basic bzw. Bascom arbeite, nur ne etwas andere Syntax, aber die Grundfunktion der Befehle ist die gleiche.

Du brauchst in VB dann die Komponente MSComm (Microsoft Comm Control) (rechtsklick in der Komponentenleiste -> Komponenten -> Microsoft Comm Control -> Checkbox aktivieren -> übernehmen)
Dann wird ne Komponente eingefügt, die als Telephon dargestellt wird. Das kommt daher, das VB den COM noch mit Modem in verbindung bringt und selbiges auch darüber gesteuert werden kann.

das Objekt plazierst Du dann irgendwo auf der Anwendungsoberfläche und schon kannste im Eigenschaftenfenster die Konfiguration des COM den du zur Kommunikation mit deinem Board benutzen willst einstellen.

So in der Art gehts dann weiter, VBasic halt.

Schaltelemente start-Messung Stop-Messung plazieren, Code dahinter etc. pp. 3-4 Stunden gefummel und die Anwendung is fertig, die Daten können schön in ne Datenbank laufen :-b

Hellmut
10.02.2005, 12:35
Hallo Vitis

Ich stehe jetzt vor dem Problem eigentlich viel zu viele offene Aufgaben bei meinen Projekt "schwimmender Roboter" zu haben. Mich noch auf den PC zu konzentriern schaffe ich nicht mehr. Fragen:

1. Deine Schilderungen, da werden die Daten imbtach-Betrieb in eine CSV-Datei geschrieben, diese kann man dann bekannter Weise anschliessend im Excel öffnen. Geht es auch und wie, das man ein Excel Chart auf dem Schirm am PC hat und während der Versuchsausführung die Kurve auf dem Chart verfolgen kann? Stell dir vor man überwacht in der Entwicklungsphase die Erwärmung einer Motorsteuerung unter Last und möchte die Temperatur oder den Strom im Chart verfolgen und engreifen, sobald es kritisch wird, bzw. die Software nicht korrekt reagiert. Das ist sicher für viele interessant. Könntest du das entwickeln und bereitstellen?

Vitis
10.02.2005, 18:17
das ginge schon, ist aber nicht besonders sinnvoll mit Excel.

Excel hat das Problem, das es ziemlich an die Prozessorleistung geht.
Ich würde wie beschrieben mit VBasic oder noch flotter mit VC++ arbeiten,
da eine kleine graphische Darstellung einbauen (das geht durchaus) für
den Messbetrieb, die Daten speichern in DBF oder CSV für spätere
detailiertere Auswertungen mit Excel.
Im Übrigen kann man diese Dateiformate auch sehr schön mit PHP bearbeiten,
wenn man die Daten z.B. auf ner Website veröffentlichen will. Ich hab sowas für meine Webseitenstatistik konstruiert, geht prima.

Ich hab so ein VBasic Programm nicht gerade rumliegen, wär
für mich als ausenstehender, da ich je weder das Datenformat am COM,
noch die Anzeigeart kenne ziemlich schwierig zu realisieren.

Ich würd schon sagen du bist ein großer Junge und kannsts selber.
Hab auch ziemlich viel um die Ohren davon mal abgesehen.
Das Problem mit den vielen Aufgaben hab ich auch :-k

Dino Dieter
10.02.2005, 23:31
Hallo Helmut

Schau mal bei http://www.b-kainka.de/msrwin.htm vorbei.

Da gibt es 2 oder 3 dlls zum runterlagen, für die Port Zugriffe.

Die kannst du dann in Excel oder Word ansprechen und die RS232
Daten einlesen. Geht dann alles mit VBA.

MFG
Dieter

Hellmut
12.02.2005, 14:36
Danke Vitis und Dieter

Mit VBA kenn ich mich schon etwas aus, da werde ich Dieters Vorschlag folgen. Vitis, wer kann der kann, wer nicht kann, der sollte sich dessen besser selber bewusst sein. Dieters Weg ist sicher weder so elegant wie deiner, möchte dir aber trotzdem danken.