www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme beim ADC-Wert auf LCD ausgeben


Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ihr MC-Gurus!

Ich habe mich gerade frisch hier angemeldet, das ist also mein erstes 
Posting.
Ganz kurz zu mir: Ich bin 24, Elektriker und Hobbyelektroniker.
Vor ca. 8 Jahren hab ich das erste mal mit MC's gebastelt, bis vor 
kurzem noch mit dem AT89C2051. Jetzt "arbeite" ich seit ca. einem Monat 
mit der atMega-Serie (mega32)
Programmiert habe ich bisher immer mit Assembler, da seh ich wenigstens 
durch^^ Bascom geht eigendlich auch, aber das wollt ich net kaufen, und 
die 4k waren sooo schnell voll^^
Bei C verstehe ich nur Banhof und komme garnicht mit klar.

Also, meine Testumgebung besteht aus dem Pollin Evaluation-board V2.0.1, 
dem Pollin Addon-Board V1.0 und einer Lochrasterkarte wo alles 
draufkommt was ich bei den anderen beiden Platinen vermisse.
Die beiden Polin-Karten habe ich schon leicht modifiziert, sodas ich 
zumindest die ADC-Grundbeschaltung dran habe, der MAX232 funktioniert 
und die Taster gegen Masse schalten.

Ich habe bereits das Tutorial "abgearbeitet".
Das LCD funktioniert wunderbar, nachdem ich mir die Tutorial-Routine auf 
8-Bit umgeschrieben habe.

*Nun zu meinem Problem:*

Ich habe das Tutorial-Programm zum ADC-Wert ausgeben 8Das einfache, ohne 
Umrechnung in Spannung) leicht geändet.(Taktfrequenz, MCU-Typ, 
LCD-Routinen)
Am PC empfange ich die Werte einwandfrei, ich kann mittels Poti schön 
die Spannung am Eingang einstellen und bekomme dementsprechend die 
Messwerte via Uart geleiftert.
Nun wollte ich den Wert auf das LCD schreiben und habe zum Umrechnen der 
16-Bit Zahl
1. einfach den ASCII-Code aus dem Register "Zeichen" nach "temp1" 
kopiert und an das LCD als Daten gesendet und
2. die 16-Bit-Umwandlung aus dem Tutorial genommen.
Beides funktioniert auf den ersten Blick auch.
Am PC kommt immer das richtig an, jedoch beim LCD nicht.
Von 00000-ca.00273 geht alles so wie es soll. Wenn ich dann am Poti 
weiterdrehe kommt jedoch nur noch auf dem PC der richtige Messwert an.
Auf dem LCD "zittern" die letzen 3 Stellen, gehen evtl sogar wieder 
etwas zurück (also Wert auf 00247 zB.) und springen dann plötzlich auf 
ca.11393
Am PC wird jedoch der richtige Wert angezeigt: 0000393
Wenn ich noch weiter drehe, zB. am PC auf 00411, steht auf dem LCD 
11511.
Bei 00543 am PC zeigt mir das LCD 11553 an.
Bei 00605 auf dem PC zeigt das LCD 11715.

Also irgendwas kommt offensichtlich durcheinander, wenn es wirkleich ein 
Wert wird, der nich mehr in 8bit gespeichert werden kann.

Das ADC-Test-Programm:

(Ja, ich weiss das z.B. XTAL und F_CPU das gleiche ist, aber ich bin ja 
noch am probieren. Ich habe beim Label Transmit die auskommentierten 
Zeilen gelassen. Damit wird einfach das über den UART gesendete Zeichen 
am LCD ausgegeben, inclusive CR und LF^^ nach dem Label no_round ist die 
aktuelle LCD-Ausgabe, welche die Umwandlung aus dem LCD-Tutorial 
benutzt)
.NOLIST
.INCLUDE "m32def.inc"
.LIST

.ifndef XTAL
.equ XTAL = 16000000
.endif

rjmp start

.def temp1     = r16         ; allgemeines temp Register, zur kurzfristigen Verwendung
.def temp2     = r17         ; Register für 24 Bit Addition, Lowest Byte
.def temp3     = r18         ; Register für 24 Bit Addition, Middle Byte
.def temp4     = r19         ; Register für 24 Bit Addition, Highest Byte
.def adlow     = r20         ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def adhigh    = r21         ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def messungen = r22         ; Schleifenzähler für die Messungen
.def ztausend  = r23         ; Zehntausenderstelle des ADC Wertes
.def tausend   = r24         ; Tausenderstelle des ADC Wertes
.def hundert   = r25         ; Hunderterstelle des ADC Wertes
.def zehner    = r26         ; Zehnerstelle des ADC Wertes
.def zeichen   = r27         ; Zeichen zur Ausgabe auf den UART
 
.equ F_CPU = 16000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
 
; Berechnungen
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
 
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif

.include "LCD_Routinen_8bit.asm"

; hier geht das Programm los
start:
    ldi     temp1, LOW(RAMEND)                  ; Stackpointer initialisieren
    out     SPL, temp1
    ldi     temp1, HIGH(RAMEND)
    out     SPH, temp1
 
;UART Initalisierung
 
    ldi     temp1, LOW(UBRR_VAL)                    ; Baudrate einstellen
    out     UBRRL, temp1
    ldi     temp1, HIGH(UBRR_VAL)
    out     UBRRH, temp1
 
    sbi     UCSRB, TXEN                         ; TX einschalten
 
; LCD Initialisieren
  rcall LCD_Init
  rcall LCD_Clear
  rcall LCD_Home

; ADC initialisieren: Single Conversion, Vorteiler 128
 
    ldi     temp1, (1<<REFS0)                   ; Kanal 0, interne Referenzspannung 5V
    out     ADMUX, temp1
    ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, temp1

    ldi     zeichen, 82
    rcall   transmit
    ldi     zeichen, 101
    rcall   transmit
    ldi     zeichen, 115
    rcall   transmit
    ldi     zeichen, 101
    rcall   transmit
    ldi     zeichen, 116
    rcall   transmit
    ldi     zeichen, 13         ; CR, Carrige Return (Wagenrücklauf)
    rcall   transmit
    ldi     zeichen, 10         ; LF, Line Feed (Neue Zeile)
    rcall   transmit



Main:
    clr     temp1
    clr     temp2
    clr     temp3
    clr     temp4
 
    ldi     messungen, 0        ; 256 Schleifendurchläufe
 
; neuen ADC-Wert lesen  (Schleife - 256 mal)
 
sample_adc:
    sbi     ADCSRA, ADSC        ; den ADC starten
 
wait_adc:
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses Bit gelöscht
    rjmp    wait_adc
 
; ADC einlesen:
 
    in      adlow, ADCL         ; immer zuerst LOW Byte lesen
    in      adhigh, ADCH        ; danach das mittlerweile gesperrte High Byte
 
; alle 256 ADC-Werte addieren
; dazu wird mit den Registern temp4, temp3 und temp2 ein
; 24-Bit breites Akkumulationsregister gebildet, in dem
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden
 
    add     temp2, adlow        ; addieren
    adc     temp3, adhigh       ; addieren über Carry
    adc     temp4, temp1        ; addieren über Carry, temp1 enthält 0
    dec     messungen           ; Schleifenzähler MINUS 1
    brne    sample_adc          ; wenn noch keine 256 ADC Werte -> nächsten Wert einlesen
 
; Aus den 256 Werten den Mittelwert berechnen
; Mathematisch eine Division durch 256
; Da aber 2^8 = 256 ist ist da einfach durch das weglassen des niederwertigsten Bytes
; erreicht werden
;
; allerdings wird der Wert noch gerundet
 
    cpi     temp2,128           ; "Kommastelle" kleiner als 128 ?
    brlo    no_round            ; ist kleiner ==> Sprung
 
; Aufrunden
    subi    temp3, low(-1)      ; addieren von 1
    sbci    temp4, high(-1)     ; addieren des Carry
 
no_round:
 
;   Ergebnis nach adlow und adhigh kopieren
;   damit die temp Register frei werden
 
    mov     adlow, temp3
    mov     adhigh, temp4

;provisorishe LCD-Ansteuerung

  push temp2
  push temp3

  mov temp2, adlow
  mov temp3, adhigh
  rcall lcd_number16
  pop temp3
  pop temp2

;in ASCII umwandeln
; Division durch mehrfache Subtraktion
 
    ldi     ztausend, '0'-1     ; Ziffernzähler direkt als ASCII Code
Z_ztausend:
    inc     ztausend
    subi    adlow, low(10000)   ; -10,000
    sbci    adhigh, high(10000) ; 16 Bit
    brcc    Z_ztausend
                                    
    subi    adlow, low(-10000)  ; nach Unterlauf wieder einmal addieren
    sbci    adhigh, high(-10000); +10,000
 
    ldi     tausend, '0'-1      ; Ziffernzähler direkt als ASCII Code
Z_tausend:
    inc     tausend
    subi    adlow, low(1000)    ; -1,000
    sbci    adhigh, high(1000)  ; 16 Bit
    brcc    Z_tausend
                                    
    subi    adlow, low(-1000)   ; nach Unterlauf wieder einmal addieren
    sbci    adhigh, high(-1000) ; +1,000
 
    ldi     hundert, '0'-1      ; Ziffernzähler direkt als ASCII Code
Z_hundert:
    inc     hundert
    subi    adlow, low(100)     ; -100
    sbci    adhigh, high(100)   ; 16 Bit
    brcc    Z_hundert
                                    
    subi    adlow, low(-100)    ; nach Unterlauf wieder einmal addieren
    sbci    adhigh, high(-100)  ; +100
 
    ldi     zehner, '0'-1       ; Ziffernzähler direkt als ASCII Code
Z_zehner:
    inc     zehner
    subi    adlow, low(10)      ; -10
    sbci    adhigh, high(10)    ; 16 Bit
    brcc    Z_zehner
                                    
    subi    adlow, low(-10)     ; nach Unterlauf wieder einmal addieren
    sbci    adhigh, high(-10)   ; +10
 
    subi    adlow, -'0'         ; adlow enthält die Einer, Umwandlung in ASCII
 
;an UART Senden
    rcall lcd_home
    mov     zeichen, ztausend   ; Zehntausender Stelle
    rcall   transmit
    mov     zeichen, tausend    ; Tausender Stelle ausgeben
    rcall   transmit    
    mov     zeichen, hundert    ; Hunderter Stelle ausgeben
    rcall   transmit
    mov     zeichen, zehner     ; Zehner Stelle ausgeben
    rcall   transmit
    mov     zeichen, adlow      ; Einer Stelle ausgeben
    rcall   transmit
    ldi     zeichen, 13         ; CR, Carrige Return (Wagenrücklauf)
    rcall   transmit
    ldi     zeichen, 10         ; LF, Line Feed (Neue Zeile)
    rcall   transmit

 
    rjmp    Main
 
transmit:
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...
    rjmp    transmit
    out     UDR, zeichen        ; und Zeichen ausgeben
;    push temp1
;    mov temp1, zeichen
;    rcall LCD_Data
;    pop temp1
    ret
 

Und hier noch meine 8bit-LCD-Routinen:

(um die Macros locate und printflash erweitert, ausserdem testweise die 
16bit-Addition auch bei 100er und 10er-Stellen hinzugefügt)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                 LCD-Routinen                 ;;
;;                 ============                 ;;
;;               by Stefan Muster               ;;
;;nach Vorbild des Microcontroller.net-Tutorials;;
;;                                              ;;
;; 8bit-Interface                               ;;
;; DB0-DB7:       PortB                         ;;
;; RW:        PD3 - noch in Arbeit          ;;
;; RS:            PD4                           ;;
;; E:             PD5                           ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.equ LCD_PORT = PORTA  ;Datenport
.equ LCD_DDR  = DDRA
.equ LCD_Strg_PORT = PORTB
.equ PIN_RS   = 2    ;
.equ PIN_E    = 0
.equ Pin_RW    = 1
.equ LCD_Strg_DDR = DDRB

 ;sendet ein Datenbyte an das LCD
lcd_data:
           push  temp2
           push  temp3
          
           in    temp3, LCD_Strg_PORT     
           sbr   temp3, (1<<Pin_RS)     ; RS auf 1 setzen
           out   LCD_Strg_PORT, temp3
           out   LCD_PORT, temp1         ; ausgeben
           rcall lcd_enable              
           rcall delay50us               ; Delay-Routine aufrufen

           pop   temp3
           pop   temp2
           ret                           ; zurück zum Hauptprogramm
 
 ; sendet einen Befehl an das LCD
lcd_command:                            ; wie lcd_data, nur ohne RS zu setzen
           push  temp2
           push  temp3

           in    temp3, LCD_Strg_PORT  ; schreibt den Zustand von LCD_Strg_PORT nach temp3
           ;cbr   temp3, Pin_RS      ; Setzt RS auf 0 (0=Befehl)
           andi  temp3, 0b11111011
           out   LCD_Strg_PORT, temp3  ; Gibt temp3 an LCD_Strg_PORT aus (jetzt mit RS=0)
           out   LCD_PORT, temp1    ; Gibt den Befehl an LCD_PORT aus
           rcall lcd_enable
           rcall delay50us
 
           pop   temp3
           pop   temp2
           ret
 
 ; erzeugt den Enable-Puls
lcd_enable:
           sbi LCD_Strg_PORT, PIN_E          ; Enable high
           nop                          ; 9 Taktzyklen warten
           nop
           nop
           nop
           nop
           nop
           nop
           nop
           nop
           cbi LCD_Strg_PORT, PIN_E          ; Enable wieder low
           ret                          ; Und wieder zurück                     
 
 ; Pause nach jeder Übertragung
delay50us: ;ret                            ; 50us Pause
           push temp1
           ldi  temp1, ( XTAL * 50 / 4 ) / 1000000
delay50us_:
           nop
           dec  temp1
           brne delay50us_
           pop temp1
           ret                          ; wieder zurück

 ; Längere Pause für manche Befehle
delay5ms:  ;ret                             ; 5ms Pause
           push temp1
           push temp2
           ldi  temp1, ( XTAL * 5 / 607 ) / 1000
WGLOOP0:   ldi  temp2, $C9
WGLOOP1:   dec  temp2
           brne WGLOOP1
           dec  temp1
           brne WGLOOP0
           pop temp2
           pop temp1
           ret                          ; wieder zurück
 
 ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
lcd_init:
           push  temp1
           push temp3
           in    temp1, LCD_Strg_DDR
           ori   temp1, (1<<PIN_E) | (1<<PIN_RS) ;| (1<<PIN_RW)
           out   LCD_Strg_DDR, temp1
           ldi temp1, 0xff
           out LCD_DDR, temp1


           ldi   temp3,6
powerupwait:
           rcall delay5ms
           dec   temp3
           brne  powerupwait
           ldi   temp1,    0b00000011   ; muss 3mal hintereinander gesendet
           out   LCD_PORT, temp1        ; werden zur Initialisierung
           rcall lcd_enable             ; 1
           rcall delay5ms
           rcall lcd_enable             ; 2
           rcall delay5ms
           rcall lcd_enable             ; und 3!
           rcall delay5ms
           ldi   temp1,    0b00110000   ; 8bit
           out   LCD_PORT, temp1
           rcall lcd_enable
           rcall delay5ms
           ldi   temp1,     0b00111000  ;System set
           rcall lcd_command
           ldi   temp1,    0b00001100   ; Display ein / Cursor aus / kein Blinken
           rcall lcd_command
           ldi   temp1,    0b00000100   ; inkrement / kein Scrollen
           rcall lcd_command
           pop   temp3
           pop temp1
           ret
 


 ; Sendet den Befehl zur Löschung des Displays
lcd_clear:
           push  temp1
           ldi   temp1,    0b00000001   ; Display löschen
           rcall lcd_command
           rcall delay5ms
           pop   temp1
           ret

 ; Cursor Home
lcd_home:
           push  temp1
           ldi   temp1,    0b00000010   ; Cursor Home
           rcall lcd_command
           rcall delay5ms
           pop   temp1
           ret

.macro locate ;Zeile (0,1), Spalte (0...39) ;Positionierung der Ausgabeposition
           push temp1                    ;Register sichern
           ldi temp1,128+((@0 & 1)<<6)+(@1 & 63) ;Zeile in Bit 6, Spalte in den Rest
           rcall lcd_command          ;an LCD als Befehl ausgeben
           pop temp1                     ;Register wiederherstellen
.endmacro



 ; Einen konstanten Text aus dem Flash Speicher
 ; ausgeben. Der Text wird mit einer 0 beendet
.macro printflash ;Startadresse des Strings im Flash (als Label angegeben)
    ;Gibt einen String aus dem Flash an LCD aus
    ;Der Parameter beschreibt die Startadresse, 
    ;das Ende ist $00
           push zh                    ;verwendete Register
           push zl                    ;sichern
           ldi zh,high(2*@0)          ;Pointer
           ldi zl,low(2*@0)           ;setzen
           rcall lcd_printf           ;Aufruf...
           pop zl                     ;verwendete Register
           pop zh                     ;wiederherstellen
.endmacro

lcd_printf:   ;Wird vom Makro aufgerufen. Gibt Flash-String an LCD aus.
           push temp1                    ;Variable beschaffen
           lpm temp1,z+                  ;Zeichen holen
           tst temp1                     ;Ende-Kennung? 
           breq pc+3                  ;ja...
           rcall lcd_data             ;nein, ausgeben
           rjmp pc-4                  ;nochmal
           pop temp1                     ;Variable entsorgen
           ret                        ;fertig, zurück...


 ; Eine Zahl aus dem Register temp1 dezimal ausgeben
lcd_number:
           push  temp1
           push  temp2
           push  temp3

           mov   temp2, temp1
                                  ; abzählen wieviele Hunderter
                                          ; in der Zahl enthalten sind
           ldi   temp1, '0'
lcd_number_1:
           subi  temp2, 100
           brcs  lcd_number_2
           inc   temp1
           rjmp  lcd_number_1
                                          ;
                                          ; die Hunderterstelle ausgeben
lcd_number_2:
           rcall lcd_data
           subi  temp2, -100              ; 100 wieder dazuzählen, da die
                                          ; vorherhgehende Schleife 100 zuviel
                                          ; abgezogen hat

                                          ; abzählen wieviele Zehner in
                                          ; der Zahl enthalten sind
           ldi   temp1, '0'
lcd_number_3:
           subi  temp2, 10
           brcs  lcd_number_4
           inc   temp1
           rjmp  lcd_number_3

                                          ; die Zehnerstelle ausgeben
lcd_number_4:
           rcall lcd_data
           subi  temp2, -10               ; 10 wieder dazuzählen, da die
                                          ; vorhergehende Schleife 10 zuviel
                                          ; abgezogen hat

                                          ; die übrig gebliebenen Einer
                                          ; noch ausgeben
           ldi   temp1, '0'
           add   temp1, temp2
           rcall lcd_data

           pop   temp3
           pop   temp2
           pop   temp1
           ret

;**********************************************************************
;
; Eine 16 Bit Zahl ohne Vorzeichen ausgeben
;
; Übergabe:            Zahl im Register temp2 (low Byte) / temp3 (high Byte)
; veränderte Register: keine
;
lcd_number16:
           push  temp1
           push  temp2
           push  temp3
 
; ** Zehntausender **
           ldi   temp1, '0'-1
lcd_number1:
           inc   temp1
           subi  temp2, low(10000)
           sbci  temp3, high(10000)
           brcc  lcd_number1
           subi  temp2, low(-10000)
           sbci  temp3, high(-10000)
           rcall lcd_data
 
; ** Tausender **
           ldi   temp1, '0'-1
lcd_number2:
           inc   temp1
           subi  temp2, low(1000)
           sbci  temp3, high(1000)
           brcc  lcd_number2
           subi  temp2, low(-1000)
           sbci  temp3, high(-1000)
           rcall lcd_data
 
; ** Hunderter **
           ldi   temp1, '0'-1
lcd_number3:
           inc   temp1
           subi  temp2, low(100)
           sbci  temp3, high(100)
           brcc  lcd_number3
           subi  temp2, low(-100)
           sbci  temp3, high(-100)
           rcall lcd_data
 
; ** Zehner **
           ldi   temp1, '0'-1
lcd_number4:
           inc   temp1
           subi  temp2, (10)
           brcc  lcd_number4
           subi  temp2, low(-10)
           sbci  temp3, high(-10)
           rcall lcd_data
 
; ** Einer **
           ldi   temp1, '0'
           add   temp1, temp2
           rcall lcd_data
 
; ** Stack aufräumen **
           pop   temp3
           pop   temp2
           pop   temp1
 
           ret

Ich hoffe ihr könnt mir helfen und mir sagen wo der Fehler versteckt 
ist.
Hab heut schon den halben Tag gesucht und komme nicht weiter.

Also, Danke schonmal im Vorraus für eure Hilfe!

Gruss Stefan

Autor: Z8 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dampf mal Deine Main ein:
______________________________________________________________________ 
___
Main:
    clr     temp1
    clr     temp2
    clr     temp3
    clr     temp4

    ldi     messungen, 0        ; 256 Schleifendurchläufe

; neuen ADC-Wert lesen  (Schleife - 256 mal)

sample_adc:
    sbi     ADCSRA, ADSC        ; den ADC starten

wait_adc:
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses 
Bit gelöscht
    rjmp    wait_adc

; ADC einlesen:

    in      adlow, ADCL         ; immer zuerst LOW Byte lesen
    in      adhigh, ADCH        ; danach das mittlerweile gesperrte High 
Byte

; alle 256 ADC-Werte addieren
; dazu wird mit den Registern temp4, temp3 und temp2 ein
; 24-Bit breites Akkumulationsregister gebildet, in dem
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden

    add     temp2, adlow        ; addieren
    adc     temp3, adhigh       ; addieren über Carry
    adc     temp4, temp1        ; addieren über Carry, temp1 enthält 0
    dec     messungen           ; Schleifenzähler MINUS 1
    brne    sample_adc          ; wenn noch keine 256 ADC Werte -> 
nächsten Wert einlesen

; Aus den 256 Werten den Mittelwert berechnen
; Mathematisch eine Division durch 256
; Da aber 2^8 = 256 ist ist da einfach durch das weglassen des 
niederwertigsten Bytes
; erreicht werden
;
; allerdings wird der Wert noch gerundet

    cpi     temp2,128           ; "Kommastelle" kleiner als 128 ?
    brlo    no_round            ; ist kleiner ==> Sprung

; Aufrunden
    subi    temp3, low(-1)      ; addieren von 1
    sbci    temp4, high(-1)     ; addieren des Carry

no_round:

  rcall lcd_number16

    rjmp    Main
______________________________________________________________________ 
______



Was passier dann?  Z8

Autor: Z8 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt sehe ichs:

>; Übergabe:     Zahl im Register temp2 (low Byte) / temp3 (high Byte)

no_round:

  mov temp2, temp3    ;!!!
  mov temp3, temp4    ;!!!
  rcall lcd_number16

  rjmp    Main

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für die Übergabe habe ich doch bei der provisorischen LCD-Ansteuerung 
folgende Zeilen:

;provisorishe LCD-Ansteuerung

  push temp2
  push temp3

  mov temp2, adlow
  mov temp3, adhigh
  rcall lcd_number16
  pop temp3
  pop temp2

Wenn ich jetzt bei no_round adlow und adhig direkt durch die Register 
ersetze, funktioniert die UART-Ausgabe ja nicht mehr. Dann müsste ich 
die umschreiben (was eigendlich kein Problem ist).

Wenn ich mein Main einkürze, so wie du es vorschlägst hätte ich ja keine 
Ausgabe der Daten mehr, oder seh ich das falsch?
Aber danke für die Antworten.

Was ich noch vergessen hatte: Ich programmiere mit dem AVR-Studio V4.16 
und die Programme werden per Ponyprog2000 V2.06f Beta übertragen.

Gruss Stefan

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hab jetzt ein wenig weiter experimentiert.
Ich habe die komplette UART-Ansteuerung mal rausgenommen (so wie Z8 
vorgeschlagen hat, inclusive der Übergebe in den richtigen Registern^^)
Das Problem besteht weiterhin.
Dann habe ich mein 4x16 LCD angschlossen -> das gleiche.
So, jetzt hab ich in der ersten LCD-Zeile konstant "01" ausgegeben, 2 
Leerzeichen, dann die über UART gesendeten ASCII-Zeichen.
In der 2. Zeile stehen die von LCD_number16 ausgegebenen Zeichen, in der 
3. und 4. Zeile wird adlow und adhigh als binärzahl ausgegeben.
Über die serielle Schnittstelle funktioniert nach wie vor alles super, 
jedoch beim LCD nicht.
Wenn ich z.B. den ADC-Wert 270 einstelle, "Zittern" einige Nullstellen, 
also springen kurz auf 1, selbst die 0 vom 01 in der ersten Zeile!!!
Ausserdem habe ich bei den Variablen in Zeile 1 und 2 ein Zeichen zu 
viel.
Kann es sein das ich ein Timingproblem beim LCD habe? Wenn ja, verstehe 
ich nur nicht, warum dann z.B. ein konstanter Text richtig ausgegeben 
wird.

Also, ist es möglich das solch komischen Werte durch ein falsches Timing 
entstehen?

Gruss Stefan

EDIT: Hab gerade festgestellt, das alle Variablen, also auch die binären 
nach kurzer Zeit eine Stelle mehr haben (die sich allerdings nie 
verändert).

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, hab den Fehler gefunden, denk ich.
Das LCD lief noch über PortA mit DB0-DB7.
Der benutzte ADC-Eingang ist PA.0 ...
Wenn ich da jetzt ne analoge Spannung anlege, erkennt das LCD das 
irgendwann als High (1) und dann gibts halt keine 0 mehr, sondern 
nurmehr Einsen.
Hab jetzt die LCD-Routine angepasst, das die Datenleitungen an Port C 
sind, aber irgendwie funktioniert da was nicht. initialisiert wird 
irgendwie, aber Zeichen kommen keine raus... auch nicht mit meinem 
Tstprogramm was bisher immer funktioniert hat.

Gruss Stefan

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

JTAG-Fuse

MfG Spess

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort, hat aber leider nix gebracht.
Egal ob Jtag an oder aus, es will nicht funktionieren.
Hab es jetzt an PortD angeschlossen, wo es allerdings auch niht auf 
anhieb klappte. Erst nachdem ich das Programm nochmals assembliert und 
neu geladen hatte (ohne auch nur ein Zeichen zu ändern) geht es jetzt.

Kann es sein, das das AVR-Studio ab und zu beim Assemblieren die 
änderungen nicht mitassembliert?

EDIT:
So, weitergebastelt, also Uart auskommentiert, und siehe da: Der 
Analogwert wird korrekt als Dezimalzahl und die Register adlow und 
adhigh werden korrekt als Binärzahl dargestellt. Auch der "statische" 
Text wird ohne Fehler angezeigt!

JUPPIIIIIIIII! Es geht!!!!
Jetzt muss ich nur noch rausfinden, warum es an PortC nicht geht^^

Gruss Stefan

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.