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

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