www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Programmoptimierung


Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie schon einige male hier erwähnt, bin ich gerade dabei eine Temperatur 
Mess und Regelungssteuerung zu bauen (es sollen dann mal in einem 
Versuchshaus verschiedene Grenzflächentemperaturen und Feuchtigkeiten 
gemessen werden).
Die Hauptarbeit wir in Java passieren, ich benutze den mc nur als 
Interface zum PC. Klappt auch alles soweit, das Protokoll ist so, das 
ich verschiednen Strings sende mit vorgeschaltetem Multiplexer und dann 
den jeweiligen ADC-Wert empfange (über temperaturabhängigen Widerstand). 
Gebaut habe ich es mit dem Atmega8L8.

Ich habe jedoch noch das Problem, dass manchmal noch undefnierbare 
Zeichen gesendet werden, habe ich noch einen Haken im Programm, bzw. was 
könnte ,man besser machen? , hier der Code:
.include "m8def.inc"
 
.def temp1     = r16
.def sensornr  = r17         ; allgemeines temp Register, zur kurzfristigen Verwendung
.def multinr   = r18         ; allgemeines temp Register, zur kurzfristigen Verwendung
.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 = 1000000                            ; Systemtakt in Hz
.equ BAUD  = 4800                               ; Baudrate
 
; Berechnungen
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  
 
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))      
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
 
.org 0x00
        rjmp main
 
.org URXCaddr
        rjmp int_rxc
 
; Schleife
main:
    
    ; Stackpointer initialisieren
 
    ldi     temp1, HIGH(RAMEND)
    out     SPH, temp1
    ldi     temp1, LOW(RAMEND)
    out     SPL, temp1
 
    ; Port B = Ausgang
   ; cbi = auf 0 setzen
  ; sbi = auf 1 setzen
    ldi     temp1, 0xFF
    out     DDRB, temp1
    ldi     temp1, 0xFF
    out     DDRD, temp1
;Vorbelegung auf Multi Kanal 0 -> String bei Temperatursenden
  ldi     multinr, '0'       ; Beginn des Strings


 
    ; Baudrate einstellen
 
    ldi     temp1, HIGH(UBRR_VAL)
    out     UBRRH, temp1                
    ldi     temp1, LOW(UBRR_VAL)
    out     UBRRL, temp1
 
    ; Frame-Format: 8 Bit
 
    ldi     temp1, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
    out     UCSRC, temp1
 
    sbi     UCSRB, RXCIE                ; Interrupt bei Empfang
    sbi     UCSRB, RXEN                 ; RX (Empfang) aktivieren
    sbi     UCSRB, TXEN                 ; #TX einschalten
   
    sei                                 ; Interrupts global aktivieren

  
loop:
    rjmp loop                           ; Endlosschleife
 
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde
 
int_rxc:
    push    temp1                        ; temp auf dem Stack sichern
    in      temp1, sreg                  ; SREG sichern
    push    temp1
    
    in      temp1, UDR                   ; UART Daten lesen

;Abfragen der UART-Eingabe:
;Multiplexer einstellen:

    cpi     temp1, '0'                  ; Multiplexer Kanal 0
    breq    int_multi_0                   


    cpi     temp1, '1'                  ; Multiplexer Kanal 1
    breq    int_multi_1                  


;Relaissteuerung für Temperatursteuerung
    cpi     temp1, 'r'                  ; Relais 1 auf 0
    breq    int_rxc_R0                   ; 

    cpi     temp1, 't'                  ; Relais 1 auf 1
    breq    int_rxc_R1                   ; 



;ADC Kanal auswählen
    cpi     temp1, 's'                  ; ADC1
    breq    int_rxc_S                   ; wenn  gleich, dann zu int_rxc_S

    cpi     temp1, 'a'                  ; ADC2
    breq    int_rxc_A                   ; wenn  gleich, dann zu int_rxc_A


;relais 1 auf PD4 schalten 2 Zustaände 1 oder 0
int_rxc_R0:
    cbi     PORTD, 4                    
    rjmp    int_rxc_2                   


int_rxc_R1:

    sbi     PORTD, 4                    
    rjmp    int_rxc_2                   


;Multiplexer Kanal 0 --> cbi = 0
int_multi_0:
    cbi     PORTB, 0                    
    cbi     PORTB, 1                   
    cbi     PORTB, 2
  ldi     multinr, '0'       ; Beginn des Strings
                    
    rjmp    int_rxc_2                   


;Multiplexer Kanal 1
int_multi_1:
    sbi     PORTB, 0                    
    cbi     PORTB, 1                   
    cbi     PORTB, 2
  ldi     multinr, '1'       ; Beginn des Strings
    rjmp    int_rxc_2             


int_rxc_S:
; nur wenn "S" aufgerufen wird, sende ich den ADC-Wert 0
;*************************************************************************************************    
;*************************************************************************************************    
;*************************************************************************************************    
     ldi temp1, (0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0)    
  ;ldi temp1, (1<<REFS0)

  out     ADMUX, temp1
    ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, temp1
  clr     temp1

  ldi     sensornr, 'T'       ; Beginn des Strings
    ;rcall   transmit
  rcall   AusgabeADC ; gehe zur Prozedur Ausgabe
  rjmp    int_rxc_2                   ; Zu int_rxc_2 springen



int_rxc_A:
; nur wenn "A" aufgerufen wird, sende ich den ADC-Wert 1
;*************************************************************************************************    
;*************************************************************************************************    
;*************************************************************************************************    
     ldi temp1, (0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(1<<MUX0)    
  ;ldi temp1, (1<<REFS0)

  out     ADMUX, temp1
    ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, temp1
  clr     temp1

  ldi     sensornr, 'F'       ; Beginn des Strings
    ;rcall   transmit
  rcall   AusgabeADC ; gehe zur Prozedur Ausgabe
  rjmp    int_rxc_2                   ; Zu int_rxc_2 springen





AusgabeADC: ;allgemeine Routine zum Ausgeben eines ADC-Wertes
;ADC-Wert lesen

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
 
;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
 
    ;Senden beginnt mit T und endet mit X
    mov     zeichen, sensornr
  rcall   transmit
    mov     zeichen, multinr
  rcall   transmit
  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, 'X'       ; Ende des Strings
    rcall   transmit
    ldi     zeichen, ' '       ; Ende des Strings
    rcall   transmit







;*************************************************************************************************    
;*************************************************************************************************    
;*************************************************************************************************    
  rjmp    int_rxc_2                   ; Zu int_rxc_2 springen



; senden eines Strings
  
transmit:
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...
    rjmp    transmit
    out     UDR, zeichen        ; und Zeichen ausgeben
    ret
  

int_rxc_2:
;alles wieder herstellen


  pop     temp1
    out     sreg, temp1                  ; SREG wiederherstellen
    pop     temp1                        ; temp wiederherstellen

    reti                  ;wieder zurück



Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich habe jedoch noch das Problem, dass manchmal noch undefnierbare
>Zeichen gesendet werden,

Dann schliess besser mal einen Quarz an.

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, können diese vom internen Quarz kommen?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ok, können diese vom internen Quarz kommen?

Es gibt keinen internen Quarz beim ATMega.
Sende doch mal dauernd nur ein Zeichen z.B. 'A'.
Wenn du dann Fehler bekommst ist der interne
Oszillator zu ungenau. Dann musst du den kalibrieren
oder besser gleich einen Quarz anschliessen.

Autor: Quarzfinder (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interner Quarz? Belege? Datenblatt? Gelesen? Woher?
Meinst du den RC-Schwinger den man noch kalibrieren muss damit er auf 
der gewünschten Frequenz schwingt und der mit der temperatur "furchtbar" 
wegdriftet..?
Interner Quarz also.

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Äähm, ich habe mich nun entschlossen einen externen Quarz zu nehmen, ich 
hatte den auch schon dran. Nun noch die Fusebits einstellen über 
Burn-o-mat -> lief auch gut, nur... jetzt antwortet der Atmega8 nicht 
mehr ??????? warum verläßt er mich, er war doch noch so jung?????

--> das war der befehl:
C:\WinAVR-20100110\bin\avrdude.exe -C 
C:\WinAVR-20100110\bin\avrdude.conf -p m8 -P lpt1 -c alex  -u -U 
hfuse:w:0xD9:m -U lfuse:w:0xE7:m

hier der Programmer im  Conf:
programmer
  id    = "alex";
  desc = "Alex - Direct connection ISP";
  type = par;
  reset = 9;
  sck = 6;
  mosi = 7;
  miso = 10;
#  errled = <num> ;                          # pin number
  rdyled = 4;
#  pgmled = 4;
#  vfyled = 4;
;

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-U lfuse:w:0xE7:m

Du hast ihn auf ext. RC-Oscillator geflasht.

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ja das war ja meine Absicht, doch er antwortet nicht mehr!?

Autor: hmmm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum quälst du den Mikro mit rechnen und den UART mit ünnötiger 
Datenübertragung ;) ?

Umrechnen kann dein PC viel besser .. sogar in Java ;)

Aber aufpassen, Java kennt kein unsigned !

Autor: Nico Sch. (nico22)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
RC-Oscillator != Crystal Oscillator(=Quartz)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ja das war ja meine Absicht, doch er antwortet nicht mehr!?

Ein Quarz ist aber ein ext. Crystal Oscillator.

Autor: Michael S. (Firma: electro-tester) (michael0307)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ,

RC-Oszillator != Quarz    // ;-)

siehe: AVR Fuses

Grüße....

Wir sind die Borg, Widerstand ist Spannung durch Stromstärke.

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist das die Ursache, dass der mc garnicht mehr antwortet? also vom 
avrdue garnicht mehr erkannt wird (rc=-1)?



@hmmm (komischer Name)
meinst u nur as hi und low-bite schicken, aber dennoch muss ich die 
Strings davorsetzen, damit das PC-Programm die Nachricht zuordnen kann 
(Protokoll)

Autor: Nico Sch. (nico22)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit deiner Fuse-Einstellung kann der Mikrocontroller den Takt nicht 
verwerten. Kein Takt, keine laufende CPU. Keine laufende CPU, keine 
Reaktion.

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, ich habe meinen Atmega beerdigt, war nicht der erste...
mit dem Mute der Verzweiflung habe ich nun einen neuen genommen und 
diesen mit Burn-o-mat und als crystal auf 3-8mhz und small output swing 
geändert, und er läuft und das Program tut auch das was es soll (im 
Moment nur einen Text senden).

Nun könnten wir wieder zum Programm kommen .... low und hi bite zum PC?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Ich habe jedoch noch das Problem, dass manchmal noch undefnierbare
>Zeichen gesendet werden, habe ich noch einen Haken im Programm, bzw. was
>könnte ,man besser machen? , hier der Code:

Warum machst du die ganze Verarbeitung im RXC-Interrupt? Interrupts 
sollte man so kurz wie möglich machen. Es reicht, wenn deine 
Interruptroutine so aussieht:
int_rxc:
  in temp1,UDR
  reti

Die Bearbeitung erfolgt im Hauptprogramm:
    clr temp1
loop:
    test temp1
    breq loop

    ....              ;Bearbeitung

    clr temp1
    rjmp loop         ; Endlosschleife

MfG Spess

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

UART habe ich umgestellt auf reines Senden der high und low-byte - 
klappt.
Interrupt umstellen habe ich jetzt hier am Schreibtisch gemacht, ohne zu 
testen, wäre so der Weg?:

.include "m8def.inc"
 
.def temp1     = r16
.def sensornr  = r17         ; allgemeines temp Register, zur kurzfristigen Verwendung
.def multinr   = r18         ; allgemeines temp Register, zur kurzfristigen Verwendung
.def adlow     = r20         ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def adhigh    = r21         ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def zeichen   = r27         ; Zeichen zur Ausgabe auf den UART

 
.equ F_CPU = 4000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
 
; Berechnungen
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  
 
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))      
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
 
.org 0x00
        rjmp main
 
.org URXCaddr
        rjmp int_rxc
 
; Mainprogramm
main:
    
    ; Stackpointer initialisieren
 
    ldi     temp1, HIGH(RAMEND)
    out     SPH, temp1
    ldi     temp1, LOW(RAMEND)
    out     SPL, temp1
 
    ; Port B = Ausgang
    ; cbi = auf 0 setzen
    ; sbi = auf 1 setzen
    ldi     temp1, 0xFF
    out     DDRB, temp1
    ; Port B = Ausgang
    ldi     temp1, 0xFF
    out     DDRD, temp1
;Vorbelegung auf Multi Kanal 0 -> String bei Temperatursenden
    ldi     multinr, '0'       ; Beginn des Strings


 
    ; Baudrate einstellen
 
    ldi     temp1, HIGH(UBRR_VAL)
    out     UBRRH, temp1                
    ldi     temp1, LOW(UBRR_VAL)
    out     UBRRL, temp1
 
    ; Frame-Format: 8 Bit
 
    ldi     temp1, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
    out     UCSRC, temp1
 
    sbi     UCSRB, RXCIE                ; Interrupt bei Empfang
    sbi     UCSRB, RXEN                 ; RX (Empfang) aktivieren
    sbi     UCSRB, TXEN                 ; TX (Senden) einschalten
   
    sei                                 ; Interrupts global aktivieren

int_rxc:
    push    temp1                        ; temp auf dem Stack sichern
    in      temp1, sreg                  ; SREG sichern
    push    temp1
    in      temp1, UDR                   ; UART Daten lesen

    reti ; raus aus dem Interrupt

    clr temp1  
;Schleife
loop:
 
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde

;Abfragen der UART-Eingabe:
;Multiplexer einstellen:

    cpi     temp1, '0'                  ; Multiplexer Kanal 0
    breq    int_multi_0                   


    cpi     temp1, '1'                  ; Multiplexer Kanal 1
    breq    int_multi_1                  


;Relaissteuerung für Temperatursteuerung
    cpi     temp1, 'r'                  ; Relais 1 auf 0
    breq    int_rxc_R0                   ; 

    cpi     temp1, 't'                  ; Relais 1 auf 1
    breq    int_rxc_R1                   ; 



;ADC Kanal auswählen
    cpi     temp1, 'a'                  ; ADC1
    breq    int_rxc_S                   ; wenn  gleich, dann zu int_rxc_S

    cpi     temp1, 's'                  ; ADC2
    breq    int_rxc_A                   ; wenn  gleich, dann zu int_rxc_A
    
    rjmp loop                           ; Endlosschleife

;relais 1 auf PD4 schalten 2 Zustände 1 oder 0
int_rxc_R0:
    cbi     PORTD, 4                    
    rjmp    int_rxc_2                   


int_rxc_R1:

    sbi     PORTD, 4                    
    rjmp    int_rxc_2                   


;Multiplexer Kanal 0 --> cbi = 0
int_multi_0:
    cbi     PORTB, 0                    
    cbi     PORTB, 1                   
    cbi     PORTB, 2
  ldi     multinr, '0'       ; Beginn des Strings
                    
    rjmp    int_rxc_2                   


;Multiplexer Kanal 1
int_multi_1:
    sbi     PORTB, 0                    
    cbi     PORTB, 1                   
    cbi     PORTB, 2
  ldi     multinr, '1'       ; Beginn des Strings
    rjmp    int_rxc_2             


int_rxc_S:
; nur wenn "S" aufgerufen wird, sende ich den ADC-Wert 0
;*******************************************************
     ldi temp1, (0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0)    

  out     ADMUX, temp1
    ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, temp1
  clr     temp1

  ldi     sensornr, 'T'       ; Beginn des Strings
  rcall   AusgabeADC ; gehe zur Prozedur Ausgabe
  rjmp    int_rxc_2                   ; Zu int_rxc_2 springen



int_rxc_A:
; nur wenn "A" aufgerufen wird, sende ich den ADC-Wert 1
;*******************************************************
     ldi temp1, (0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(1<<MUX0)    

  out     ADMUX, temp1
    ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, temp1
  clr     temp1

  ldi     sensornr, 'F'       ; Beginn des Strings
  rcall   AusgabeADC ; gehe zur Prozedur Ausgabe
  rjmp    int_rxc_2                   ; Zu int_rxc_2 springen


AusgabeADC: ;allgemeine Routine zum Ausgeben eines ADC-Wertes
;ADC-Wert lesen

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
 
;an UART Senden
 
    ;Senden beginnt mit T und endet mit X
    mov     zeichen, sensornr   ;alphanumetrisch A-K
    rcall   transmit
    mov     zeichen, multinr    ;0 bis 7    
    rcall   transmit
    mov     zeichen, adlow      ; low-Wert ausgeben
    rcall   transmit
    mov     zeichen, adhigh     ; high-Wert ausgeben 
    rcall   transmit
    ldi     zeichen, 'X'       ; Ende des Strings
    rcall   transmit
    ldi     zeichen, ' '       ; Blank am Ende für Tests im Hypertemonal
    rcall   transmit


;*************************************************************  
   rjmp    int_rxc_2                   ; Zu int_rxc_2 springen

; senden
  
transmit:
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...
    rjmp    transmit
    out     UDR, zeichen        ; und Zeichen ausgeben
    ret

int_rxc_2:
;alles wieder herstellen

    pop     temp1
    out     sreg, temp1                  ; SREG wiederherstellen
    pop     temp1                        ; temp wiederherstellen

    ret                  ;wieder zurück


Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh je, dat lüppt so nicht habe ich festgestellt, kann mir einer einen 
Tip geben, was ich noch ändern muss?

Gruß
Pfeiffy

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>    sei                                 ; Interrupts global aktivieren

>int_rxc:
>    push    temp1                        ; temp auf dem Stack sichern
>    in      temp1, sreg                  ; SREG sichern
>    push    temp1
>    in      temp1, UDR                   ; UART Daten lesen
>
>    reti ; raus aus dem Interrupt

>    clr temp1
>;Schleife
>loop:

Was soll denn die Interruptroutine in deinem loop?

MfG Spess

Autor: Holger P. (holg_i)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde das versenden so machen:
;Senden beginnt mit T und endet mit X
  mov     zeichen, sensornr
  rcall   transmit
  mov     zeichen, multinr
  rcall   transmit

  in      adlow, ADCL         ; immer zuerst LOW Byte lesen
  in      adhigh, ADCH        ; danach das mittlerweile gesperrte High Byte
 
; in ASCII umwandeln
; Division durch mehrfache Subtraktion
 
    ldi     zeichen, '0'-1     ; Ziffernzähler direkt als ASCII Code
Z_ztausend:
    inc     zeichen
    subi    adlow, low(10000)   ; -10,000
    sbci    adhigh, high(10000) ; 16 Bit
    brcc    Z_ztausend
    rcall   transmit
                                    
    subi    adlow, low(-10000)  ; nach Unterlauf wieder einmal addieren
    sbci    adhigh, high(-10000); +10,000
 
    ldi     zeichen, '0'-1      ; Ziffernzähler direkt als ASCII Code
Z_tausend:
    inc     zeichen
    subi    adlow, low(1000)    ; -1,000
    sbci    adhigh, high(1000)  ; 16 Bit
    brcc    Z_tausend
    rcall   transmit
                                    
    subi    adlow, low(-1000)   ; nach Unterlauf wieder einmal addieren
    sbci    adhigh, high(-1000) ; +1,000
 
    ldi     zeichen, '0'-1      ; Ziffernzähler direkt als ASCII Code
Z_hundert:
    inc     zeichen
    subi    adlow, low(100)     ; -100
    sbci    adhigh, high(100)   ; 16 Bit
    brcc    Z_hundert
    rcall   transmit
                                    
    subi    adlow, low(-100)    ; nach Unterlauf wieder einmal addieren
    sbci    adhigh, high(-100)  ; +100
 
    ldi     zeichen, '0'-1       ; Ziffernzähler direkt als ASCII Code
Z_zehner:
    inc     zeichen
    subi    adlow, low(10)      ; -10
    sbci    adhigh, high(10)    ; 16 Bit
    brcc    Z_zehner
    rcall   transmit        
                                    
    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
    mov     zeichen,adlow
    rcall   transmit

    ldi     zeichen, 'X'       ; Ende des Strings
    rcall   transmit
    ldi     zeichen, ' '       ; Ende des Strings
    rcall   transmit

Spart dir Register

.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

und macht es übersichtlicher. Da du die allema nicht mehr brauchst.


Wow mein erster Tipp in ASM hier grins

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@holg_i:
ja, ich hab die ganze ASCIIs ja schon rausgeworfen und sende nur noch hi 
und low byte (siehe letzte Mitteilung)

@spess53
ääähhm....ok, ich hab noch so meine Probleme mit Assembler, kannst du 
mir hier helfen? Es soll auf jedem Fall beim Empfang eines Strings über 
den UART was das high und low byte gesendet werden.

Gruß
Pfeiffy

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk P. schrieb:

> @spess53
> ääähhm....ok, ich hab noch so meine Probleme mit Assembler, kannst du
> mir hier helfen?

Ich denke, dass dir hier nicht wirklich klar ist, wie das mit rcall etc 
funktioniert. Was ein Interrupt ist dürftest auch noch nicht durchschaut 
haben.

Warum machst du den Empfang per Interrupt? Musst du doch nicht. Machs 
doch erst mal konventionell mittels Polling.


Du hast da einen ziemlichen Saustall auf dem Stack angerichtet. Im 
Grunde bist du gar nicht soweit von einer richtigen Lösung entfernt, 
wenn du die Ablaufpfade erst mal richtig stellst. Sieh erst mal zu, dass 
du das in den Griff kriegst.

Wenn du sowieso schon Java kannst, dann versteh ich nicht, warum du dir 
dann hier mit Assembler eine Baustelle aufmachst, die mit C (dank deiner 
Java Vorkentnisse) nur 1/4 so groß wäre.

Autor: Spess53 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ääähhm....ok, ich hab noch so meine Probleme mit Assembler, kannst du
>mir hier helfen? Es soll auf jedem Fall beim Empfang eines Strings über
>den UART was das high und low byte gesendet werden.

Das sollte dich aber nicht hindern, das Programm im Simulator zu testen.

Ein paar Kleinigkeiten habe ich schon korrigiert.

MfG Spess

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
klar Einarbeiten in Assemble, weiss ich ja (aber mir fehlt die Zeit!)- 
alles was ich in Assembler machen will ist diese Schnttstelle zum PC 
über die UART und damit die ADCs abfragen und noch einen Multiplexer 
davor. Mehr möchte ich garnicht. Es klappt ja so wie ichs progranmmiert 
habe, jetzt wollte ich es nur noch verbessern.

Gruß
Pfeiffy

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noch eine Frage: wie kann ich im Simulator den Interrupt simulieren?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>noch eine Frage: wie kann ich im Simulator den Interrupt simulieren?

Während der Simulation im I/O View das passende Interrupt Flag Bit 
setzen.

MfG Spess

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk P. schrieb:
> Hallo,
> klar Einarbeiten in Assemble, weiss ich ja

C und nicht Assembler ist für Deinen Anwendungsfall die richtige Wahl, 
wie Karl heinz Buchegger schon bemerkt hat.

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich lass das jetzt mal mit c, der code, den mir spess gegeben hat läuft 
einwandfrei und macht genau das, was er soll, nochmals danke!!!!
Ich wende mich nun der Verarbeitung und der Auswertung, wie auch dem 
Versuchsaufbau zu. Mit Java ist das eine tolle Sache, läuft schon 
wunderbar!!


Gruß
Pfeiffy

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.