PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ASM HC-SR04 mit AtMega328



avr_racer
19.08.2018, 19:04
In diesem Artikel gehts mal um das Ultraschallmodul HC-SR04.
Daten siehe Anlagenblatt
33578

Informatives zum Schall:

https://de.wikipedia.org/wiki/Schallgeschwindigkeit

331,5m/s bei 0°C, bei zunehmender Temperatur wird der Schall um 0,6m/s pro °C schneller.
Gleichung 1: 331,5m/s + 0,6 * 19°C = 342,9m/s bei 20°C


Informatives zum Programm:

Die Zeitbasis wird mit Timer 0 generiert im CTC-Modus 2 und mit OCR0B auf Pin D5 getoggelt. Hier ist ganz wichtig das OCR0A und OCR0B
den gleichen Wert haben da OCR0A die Auflösung in diesem Mode bestimmt. OCR0B ist hier schon in der Hardware mit PD5 im AVR selbst gekoppelt so das hier
der Timer 1 als einfacher Counter mit externer Taktung genutzt werden kann.
Auflösung 1bit enstpricht 1µs.

Der Triggerpin muss für mind. 10µs als Highpegel anliegen und wieder auf low gesetzt. Solange der Echopin low ist, wird in der Schleife gewartet bis der Burst vom Modul gesendet worden ist. Danach setzt das Modul sein Echopin auf HIGH und löst den ext. Interrupt 1, steigend Flanke, aus. Dadurch wird der Timer 0 freigegeben und beginnt den OCR0B=PD5=T1 zu toggeln so das mit jeder µs T1 incrementiert wird.
Wird das Echo vom Modul empfangen geht der Echopin von High auf Low und die Schleife im Programm wird unterbrochen, beide Timer gestoppt.

Hinweis: Timer1 ist begrenzt durch das OCR1A auf 30000µs als maximal Zeit (Hin/Rückweg). Wird dieser Wert erreicht werden beide Timer gestoppt und der Wert nimmt den selben Programmablauf als wenn ein Echo empfangen wurde.

Da das Echo Hin und Rückweg zurücklegt, kann hier schon eine Teilung durch 2 (30000µs/2 = 15000µs) erfolgen um die Zeit in µs des einfachen Weges zu ermitteln.
Danach erfolgt die erste Ausgabe, als Zeitwert, an den PC des einfachen Weges.

Im nächsten Schritt kann mit der einfachen Gleichung, der Weg(s) = Geschwindigkeit(v) * Zeit(t) berechnet werden. Hab hier einen festen Wert genommen von 343m/s was ca. einer Temperatur um die 19°C entspricht.
Hinweis: es wird ganzzahlig gerechnet indem Fall in dm/s und maximaler Zeitwert:
Beispiel: 3430dm/s * 15001µs = 51453430µm = 5145,3430mm = 5,1453430m

Nun wird der eigentliche Wert in mm als Ausgabe an den PC gesendet.
33579

Die Schallgeschwindigkeit kann zusätzlich mit einem Temperatursensor ergänzt und mit der obigen Gleichung 1 berechnet werden was dann den Festwert, T1_max , ersetzen könnte und so eine Kompensation ermöglicht.
Kompensation noch nicht enthalten.

Foglende Routinen
.include "h:\etronik\Software3\sonstiges\origin\mathe.asm"
.include "h:\etronik\Software3\sonstiges\origin\hex_dez_wand lung.asm"

sind hier bereitgestellt
https://www.roboternetz.de/community/threads/70938-ATMega48-88-168-328-Bibliothek
https://www.roboternetz.de/community/threads/67805-ATmega16-Bibliothek
https://www.roboternetz.de/community/threads/67800-Tiny-2313-Bibliothek

avr_racer
20.08.2018, 08:58
Ultraschall.asm

;###########################################
;# Projekt: #
;# #
;# #
;# Taktfrequenz des AVR: 16 MHz #
;# #
;# CS-SOFT #
;###########################################

.include "m328Pdef.inc" ;Atmega8

.def math1h = r8
.def math1l = r9
.def math2h = R10
.def math2l = r11
.def matherghh = r12
.def mathergh = r13
.def mathergl = r14
.def mathergll = r15

.def temp0 = r16 ;
.def temp1 = r17 ;
.def temp2 = r18
.def temp3 = r19 ;
.def temp4 = r20
.def cnt = r21

.equ cpu = 16000000
.equ Baud0 = 9600
.equ UBRR0 = cpu/(16*Baud0)-1

;**********LCD Port mit 74HC164
.equ LCD_signs = 20
.equ Zeile1 = $00+$80
.equ Zeile2 = $40+$80
.equ Zeile3 = Zeile1+LCD_signs
.equ Zeile4 = Zeile2+LCD_signs

.equ port_lcd_x = portc ;gilt für 4/8bit modus
.equ ddrx_lcd_x = ddrc
; Pinbelegungen
; STD
.equ SClock = 0 ;LCD ;;;
.equ SRS = 0
.equ SData = 1 ;74164 ;;;;;so Kann die HW angeschlossen sein
.equ SRW = 1
.equ Light = 2 ;LCD ;;;;;
.equ SEnable = 3 ;74164 ;;;


;********* parallel für LCD/Simulationssoftware*************
;.equ st_port_lcd_x = portb
;.equ st_ddrx_lcd_x = ddrb
; STD
.equ PRS = 4 ;
.equ PEnable = 5 ;

;Entry Set
.equ SH = 0 ;1 = Display shift 0 = not shifted
.equ ID = 1 ;1 = increase 0 = decrease
.equ HES = 2 ;immer 1 setzen Symbolisiert das Ende
;des Commandos
;DISPLAY on/off
.equ B = 0 ;1 = Blink 0 = no Blink
.equ C = 1 ;1 = Cursor on 0 = Cursor off
.equ D = 2 ;1 = Disp on 0 = Disp off
.equ HD = 3 ;immer 1 setzen Symbolisiert das Ende
;des Commandos
;Shift
.equ RL = 2 ;1 = right shift 0 = left shift
.equ SC = 3 ;1 = Disp shift 0 = Cursor move
.equ HS = 4 ;immer 1 setzen Symbolisiert das Ende
;des Commandos
;SET Function
.equ F = 2 ;1 = 5x10 0 = 5x7
.equ N = 3 ;1 = 2line(4line) 0 = 1line
.equ DL = 4 ;1 = 8bit int 0 = 4bit interface
.equ HSF = 5 ;immer 1 setzen Symbolisiert das Ende
;des Commandos

;**********interner ADC
.equ ADC_ddr = ddrc
.equ ADC_Port = Portc
.equ ADC_Pin = PinC
.equ Chan0 = 0
.equ Chan1 = 1
.equ Chan2 = 2
.equ Chan3 = 3
.equ Chan4 = 4
.equ Chan5 = 5
.equ ref5 = $1312
.equ ref52 = $0
.equ ref256 = $09d0
.equ ref2562 = $0
;**********SRAM
.equ erg_k = $0100 ;erg_k wird bis zu 5 weiteren bytes genutzt sprich erg_k+5
.equ ocra0 = $0105 ;für T2
.equ ocrb0 = $0106
.equ ocra1h = $0107 ;;;;;
.equ ocra1l = $0108 ;;;;;;;; für T1 A channel
.equ ocrb1h = $0109 ;;;;;
.equ ocrb1l = $010a ;;;;;;;; für T1 B channel
.equ icr1xh = $010b ;;;;;
.equ icr1xl = $010c ;;;;;;;; für T1 ICR
.equ ocra2 = $010d
.equ ocrb2 = $010e

.equ hadc = $0110 ;adc
.equ ladc = $0111 ;adc
.equ eep_adrh = $0112 ;eeprom
.equ eep_adrl = $0113 ;eeprom
.equ LTC_wertH = $0114
.equ LTC_wertL = $0115
.equ sonar1h = $0116
.equ sonar1l = $0117
.equ RSdebug = $0140 ;debug serielle Schnittstelle
;***************************Einsprungadressen***** ******************
.cseg
.org $0000
rjmp stack
.org $0002 ;2
reti;rjmp INT_EX0
.org $0004 ;4
rjmp INT_EX1
.org $0006 ;6
reti;rjmp INT_PC0
.org $0008 ;8
reti;rjmp INT_PC1
.org $000a ;a
reti;rjmp INT_PC2
.org $000c ;c
reti;rjmp INT_WDT
.org $000e ;e
reti;rjmp INT_OC2A
.org $0010 ;10
reti;rjmp INT_OC2B
.org $0012 ;12
reti;rjmp INT_OVF2
.org $0014 ;14
reti;rjmp INT_CPT1
.org $0016 ;16
rjmp INT_OC1A ;reti
.org $0018 ;18
reti;rjmp INT_OC1B
.org $001a ;1a
reti;rjmp INT_OVF1
.org $001c ;1c
reti;rjmp INT_OC0A
.org $001e ;1e
reti;rjmp INT_OC0B
.org $0020 ;20
reti;rjmp INT_OVF0
.org $0022 ;22
reti;rjmp INT_SPI
.org $0024 ;24
reti;rjmp INT_USART_RX
.org $0026 ;26
reti;rjmp INT_USART_UDRE
.org $0028 ;28
reti;rjmp INT_USART_TX
.org $002a ;2a
reti;rjmp INT_ADC
.org $002c ;2c
reti;rjmp INT_EE_Ready
.org $002e ;2e
reti;rjmp INT_ANALOG_COMP
reti ;11 keine 2wireRoutinen
reti ;a keine SPI Routinen

;***************************Init mit allem drumdran*****************
stack: ldi temp1,high(ramend) ;Stackpointer festlegen
out sph, temp1
ldi temp1,low(ramend) ;Stackpointer festlegen
out spl, temp1
rcall sram

rcall init_HCSR04
sbi pind,6

; rcall lcd_init
; rcall lcd_clear
; rcall werbe1
; rcall werbe2
; rcall wait1s
; rcall leer_z

; rcall INIT_ext_Int01
; rcall deak_int01

; rcall INIT_PC_INTx

; rcall mode7_t0_init
; rcall prescaler_T0_on

; rcall mode4_t1_init
; rcall prescaler_T1_on

; rcall mode2_t2_init
; rcall prescaler_T2_on

; rcall adc_header

; rcall eeprom_init ;wenn ints bevorzugt werden
; rcall adr_cnt
; rcall eeprom_write

; rcall AC_init
; rcall ac_change

rcall usart_init ;wenn INT bevorzugt dann hier aktivieren und prog erweitern
rcall werbe_rs


start: rcall HCSR04_Start
rcall HCSR04_micros_out_uart
rcall Zeit_zu_Entfernung
rcall HCSR04_mm_out_uart
nop
nop
nop
nop
nop
nop
nop
start2: ldi temp0,$32
rcall waitxms

sbis pind,6
rjmp start
rjmp start2

;*********Sram clearen******************************************* ****
sram: clr temp0
ldi yl,low(SRAM_START)
ldi yh,high(SRAM_START) ;Masterclr des Sram's über
sram2: st y+,temp0 ;die indirekte Adressierung
cpi yl,$50 ;bis zur zelle x=$a0 löschen
brne sram2
ret
;*************************weitere*includedata***** ******************
.include "AtMega328_ext_ints.asm"
.include "AtMega328_timercounter.asm"
.include "AtMega328_uart_std.asm"
.include "AtMega328_RS_Txt_out.asm"
.include "HC_SR04_2.asm"

.include "h:\etronik\Software3\sonstiges\origin\mathe.asm"
.include "h:\etronik\Software3\sonstiges\origin\zeitschleife n.asm"
.include "h:\etronik\Software3\sonstiges\origin\hex_dez_wand lung.asm" ;gebraucht für LCD oder nur umwandlung
;*************************ENDE******************** ******************



AtMega328_ext_ints.asm

;PD2/3 sind INT0/1
INIT_EXT_INT01:
lds temp0,EICRA
ori temp0,(1<<ISC11|1<<ISC10|0<<ISC01|0<<ISC00) ;hier INT0/1 auf steigende flanke siehe PDF KAP.13
sts EICRA,temp0

in temp0,EIMSK
ori temp0,(1<<INT1|0<<INT0) ;beide INTs aktiv
out EIMSK,temp0

sei ;global int
ret

deak_INT01:
lds temp0,EIMSK
andi temp0,(0<<INT1|0<<INT0) ;beide INTs aktiv
sts EIMSK,temp0
ret

INT_EX0: ;hier steht das Programm welches ausgeführt werden soll
reti

INT_EX1: ;hier steht das Programm welches ausgeführt werden soll
rcall prescaler_T0_on
rcall prescaler_T1_on
reti

;*******************Pin Change Interrupt***************************************** ****
INIT_PC_INTx:
lds temp0,PCICR
ori temp0,(1<<PCIE2|1<<PCIE1|1<<PCIE0) ;Hier Portbereich wählen
sts PCICR,temp0 ;2=(23:16),1=(14:),0=(7:0)

rcall PCIE0_active
rcall PCIE1_active
rcall PCIE2_active

sei

ret

INIT_PC_INTx_deakt:
lds temp0,PCICR
andi temp0,(0<<PCIE2|0<<PCIE1|0<<PCIE0) ;Hier Portbereich wählen
sts PCICR,temp0 ;2=(23:16),1=(14:),0=(7:0)
ret

PCIE0_active:
lds temp0,PCMSK0
ori temp0,(0<<PCINT7 | 0<<PCINT6 | 0<<PCINT5| 0<<PCINT4 | 0<<PCINT3 | 0<<PCINT2 | 0<<PCINT1 | 0<<PCINT0)
sts PCMSK0,temp0
ret

PCIE1_active:
lds temp0,PCMSK1
ori temp0,(0<<PCINT14 | 0<<PCINT13 | 0<<PCINT12 | 0<<PCINT11 | 0<<PCINT10 | 0<<PCINT9 | 0<<PCINT8)
sts PCMSK1,temp0
ret

PCIE2_active:
lds temp0,PCMSK2
ori temp0,(0<<PCINT23 | 0<<PCINT22 | 0<<PCINT21 | 0<<PCINT20 | 0<<PCINT19 | 0<<PCINT18 | 0<<PCINT17 | 0<<PCINT16)
sts PCMSK2,temp0
ret


AtMega328_timercounter.asm

;*****************************INIT-Mode 1 Timer0******************************************** ************************
mode0_t0_init:
lds temp1,TIMSK0
ori temp1,(0<<OCIE0B | 0<<OCIE0A | 1<<TOIE0)
sts TIMSK0,temp1
clr temp1
sts TCNT0,temp1
ret

;MODE 1 PWM-PhaseCorrect beide Channels nutzbar da Counter bis FF zählt
mode1_t0_init:
rcall A0_ch_en ;out aktivieren
rcall B0_ch_en ;out aktivieren
rcall A0_ch_load ;Zeitwert laden
rcall B0_ch_load ;Zeitwert laden

in temp0,TCCR0A
ori temp0,(0<<COM0A1|1<<COM0A0|0<<COM0B1|1<<COM0B0) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
out TCCR0A,temp0

in temp0,TCCR0B
ori temp0,(0<<WGM02)
out TCCR0B,temp0

in temp0,TCCR0A
ori temp0,(0<<WGM01|1<<WGM00)
out TCCR0A,temp0

lds temp1,TIMSK0
ori temp1,(1<<OCIE0B | 1<<OCIE0A | 0<<TOIE0)
sts TIMSK0,temp1

ret

;MODE 2 CTC ACHTUNG OCRA als Auflösung nutzbar, OCRB muss <= OCRA sein falls man togglen will
mode2_t0_init:
; rcall A0_ch_en ;out aktivieren
rcall B0_ch_en ;out aktivieren
rcall A0_ch_load ;Zeitwert laden
rcall B0_ch_load ;Zeitwert laden

in temp0,TCCR0A
ori temp0,(0<<COM0A1|0<<COM0A0|0<<COM0B1|1<<COM0B0) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
out TCCR0A,temp0

in temp0,TCCR0B
ori temp0,(0<<WGM02)
out TCCR0B,temp0

in temp0,TCCR0A
ori temp0,(1<<WGM01|0<<WGM00)
out TCCR0A,temp0

lds temp1,TIMSK0
ori temp1,(0<<OCIE0B | 0<<OCIE0A | 0<<TOIE0)
sts TIMSK0,temp1

ret

;MODE 3 FAST PWM A / B unabahängig nutzbar
mode3_t0_init:
rcall A0_ch_en ;out aktivieren
rcall B0_ch_en ;out aktivieren
rcall A0_ch_load ;Zeitwert laden
rcall B0_ch_load ;Zeitwert laden

in temp0,TCCR0A
ori temp0,(1<<COM0A1|1<<COM0A0|1<<COM0B1|1<<COM0B0) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
out TCCR0A,temp0

in temp0,TCCR0B
ori temp0,(0<<WGM02)
out TCCR0B,temp0

in temp0,TCCR0A
ori temp0,(1<<WGM01|1<<WGM00)
out TCCR0A,temp0

lds temp1,TIMSK0
ori temp1,(1<<OCIE0B | 1<<OCIE0A | 0<<TOIE0)
sts TIMSK0,temp1

ret

;MODE 4 RESERVED


;MODE 5 PWM-PhaseCorrect nur OCRA mit CHAN A und INT A, wenn OCRB < OCRA dann ist noch INT B ohne CHAN B nutzbar
mode5_t0_init:
rcall A0_ch_en ;out aktivieren
rcall B0_ch_en ;out aktivieren
rcall A0_ch_load ;Zeitwert laden
rcall B0_ch_load ;Zeitwert laden

in temp0,TCCR0A
ori temp0,(0<<COM0A1|1<<COM0A0|0<<COM0B1|1<<COM0B0) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
out TCCR0A,temp0

in temp0,TCCR0B
ori temp0,(1<<WGM02)
out TCCR0B,temp0

in temp0,TCCR0A
ori temp0,(0<<WGM01|1<<WGM00)
out TCCR0A,temp0

lds temp1,TIMSK0
ori temp1,(1<<OCIE0B | 1<<OCIE0A | 0<<TOIE0)
sts TIMSK0,temp1

ret

;MODE 6 RESERVED

;MODE 7 FAST-PWM nur OCRA mit CHAN A und INT A, wenn OCRB < OCRA dann ist noch INT B ohne CHAN B nutzbar
mode7_t0_init:
rcall A0_ch_en ;out aktivieren
rcall B0_ch_en ;out aktivieren
rcall A0_ch_load ;Zeitwert laden
rcall B0_ch_load ;Zeitwert laden

in temp0,TCCR0A
ori temp0,(0<<COM0A1|1<<COM0A0|0<<COM0B1|1<<COM0B0) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
out TCCR0A,temp0

in temp0,TCCR0B
ori temp0,(1<<WGM02)
out TCCR0B,temp0

in temp0,TCCR0A
ori temp0,(1<<WGM01|1<<WGM00)
out TCCR0A,temp0

lds temp1,TIMSK0
ori temp1,(1<<OCIE0B | 1<<OCIE0A | 0<<TOIE0)
sts TIMSK0,temp1

ret

;Zähler de/aktivieren
prescaler_T0_on:
in temp0,TCCR0B
ori temp0,(0<<CS12|0<<CS11|1<<CS10) ;schmeißt den counter an
out TCCR0B,temp0
sei
ret

prescaler_T0_off:
in temp0,TCCR0B
andi temp0,(0<<CS12|0<<CS11|0<<CS10) ;stoppt den counter an
out TCCR0B,temp0
ret

T0_clr: clr temp0
sts TCNT0,temp0
ret

;*****************ChannelLoad********************* *********************************
A0_ch_load:
ldi temp0,CTC_T0 ;Toggeln oder Clr/Set aktiv muss OCR1Ah-Register beachtet werden um
sts ocra0,temp0 ;____--- oder _------ zu erreichen
out OCR0A,temp0 ;Toggeln oder Clr/Set aktiv muss OCR1Al-Register beachtet werden um

ret

A0_ch_en:
sbi ddrd,6 ;output aktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

A0_ch_dis:
cbi ddrd,6 ;output deaktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

B0_ch_load:
ldi temp0,CTC_T0 ;Toggeln oder Clr/Set aktiv muss OCR1Ah-Register beachtet werden um
sts ocrb0,temp0 ;____--- oder _------ zu erreichen
out OCR0B,temp0 ;Toggeln oder Clr/Set aktiv muss OCR1Al-Register beachtet werden um

ret

B0_ch_en:
sbi ddrd,5 ;output aktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

B0_ch_dis:
cbi ddrd,5 ;output deaktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

;******ISR
INT_OC0A: ;$000E
reti

INT_OC0B: ;$0010
reti

INT_OVF0: ;$0012
reti


;******************************Init-Modes des Timers1******************************************* ********************
mode0_T1_init:;NORMAL_MODE OCR1A h:l,OCR1B h:l update ocrxH:L sofort oder im INT
; rcall A1_ch_en ;out aktivieren
; rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
; rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<ICNC1|0<<ICES1|0<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(0<<COM1A1|0<<COM1A0|0<<COM1B1|0<<COM1B0|0<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|0<<OCIE1B|1<<OCIE1A|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode1_T1_init:;8bit phase correct mode OCR1A h:l,OCR1B h:l update ocrxH:L on top oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|0<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode2_T1_init:;9bit phase correct mode OCR1A h:l,OCR1B h:l update ocrxH:L on top oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|1<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode3_T1_init:;10bit phase correct mode OCR1A h:l,OCR1B h:l update ocrxH:L on top oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|1<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode4_T1_init:;CTC mode OCR1A h:l,OCR1B h:l update ocrAH:L oder im INT
;rcall A1_ch_en ;out aktivieren
;rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
;rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(0<<COM1A1|0<<COM1A0|0<<COM1B1|1<<COM1B0|0<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|0<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode5_T1_init:;FAST PWM 8bit OCR1A h:l,OCR1B h:l update ocrxH:L on bottom oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(0<<COM1A1|1<<COM1A0|0<<COM1B1|1<<COM1B0|0<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|0<<OCIE1A|0<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode6_T1_init:;FAST PWM 9bit OCR1A h:l,OCR1B h:l update ocrxH:L on bottom oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|1<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode7_T1_init:;FAST PWM 10bit OCR1A h:l,OCR1B h:l update ocrxH:L on bottom oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(0<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|1<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode8_T1_init:;PWM,PahseFrequenzyCorrect OCR1A h:l,ICRh:l update ocrxH:L on bottom oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(1<<ICES1|1<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|0<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(1<<ICIE1|0<<OCIE1A|0<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode9_T1_init:;PWM,PahseFrequenzyCorrect OCR1A h:l,OCR1A h:l update ocrxH:L on bottom oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(1<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|0<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode10_T1_init:;PWM,PahseCorrect OCR1A h:l,ICRh:l update ocrxH:L on top oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(1<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|1<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(1<<ICIE1|0<<OCIE1A|0<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode11_T1_init:;PWM,PahseCorrect OCR1A h:l,OCRah:l update ocrxH:L on top oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(1<<WGM13|0<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|1<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode12_T1_init:;CTC OCR1A h:l,ICRh:l update sofort oder im INT
; rcall A1_ch_en ;out aktivieren
; rcall B1_ch_en ;out aktivieren
; rcall A1_ch_load ;Zeitwert laden
; rcall B1_ch_load ;Zeitwert laden
rcall ICR1_ch_load
ldi temp0,(1<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(0<<COM1A1|0<<COM1A0|0<<COM1B1|0<<COM1B0|0<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(1<<ICIE1|0<<OCIE1A|0<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode13_T1_init:;RESERVED not activated
/* ;rcall A1_ch_en ;out aktivieren
;rcall B1_ch_en ;out aktivieren
;rcall A1_ch_load ;Zeitwert laden
;rcall B1_ch_load ;Zeitwert laden
ldi temp0,(1<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
out TCCR1B,temp0
in temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|0<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
out TCCR1A,temp0
in temp0,TIMSK
ori temp0,(0<<TICIE1|1<<OCIE1A|1<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
out TIMSK,temp0
*/ ret

mode14_T1_init:;FAST PWM OCR1A h:l,ICRh:l update ocrxH:L on bottom oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(1<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(1<<COM1A1|0<<COM1A0|1<<COM1B1|0<<COM1B0|1<<WGM11|0<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(1<<ICIE1|0<<OCIE1A|0<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

mode15_T1_init:;FAST PWM OCR1A h:l,OCRah:l update ocrxH:L on bottom oder im INT
rcall A1_ch_en ;out aktivieren
rcall B1_ch_en ;out aktivieren
rcall A1_ch_load ;Zeitwert laden
rcall B1_ch_load ;Zeitwert laden
ldi temp0,(1<<WGM13|1<<WGM12) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1B,temp0
lds temp0,TCCR1A
ori temp0,(0<<COM1A1|1<<COM1A0|0<<COM1B1|0<<COM1B0|1<<WGM11|1<<WGM10) ;zum Toggeln COM1xA/B Einstellungen beachten!!!!!!!!!
sts TCCR1A,temp0
lds temp0,TIMSK1
ori temp0,(0<<ICIE1|0<<OCIE1A|0<<OCIE1B|0<<TOIE1) ;INT für ICP=off, OCIE1A=off, OCIE1B=off, OVFL=1
sts TIMSK1,temp0
ret

prescaler_T1_on:
lds temp0,TCCR1B
ori temp0,(1<<CS12|1<<CS11|1<<CS10) ;schmeißt den counter an
sts TCCR1B,temp0
sei
ret

prescaler_T1_off:
lds temp0,TCCR1B
andi temp0,(0<<CS12|0<<CS11|0<<CS10) ;stoppt den counter an
sts TCCR1B,temp0
ret

T1_clr: clr temp0
sts TCNT1h,temp0
sts TCNT1l,temp0
ret

;**********Channel load
A1_ch_load:
ldi temp0,T1_max_h ;Toggeln oder Clr/Set aktiv muss OCR1Ah-Register beachtet werden um
sts OCRa1h,temp0 ;____--- oder _------ zu erreichen
sts OCR1ah,temp0
ldi temp0,T1_max_l ;Toggeln oder Clr/Set aktiv muss OCR1Al-Register beachtet werden um
sts OCRa1l,temp0 ;____--- oder _------ zu erreichen
sts OCR1al,temp0
ret

A1_ch_en:
sbi ddrb,1 ;output aktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

A1_ch_dis:
cbi ddrb,1 ;output deaktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

B1_ch_load:
ldi temp0,$00 ;Toggeln oder Clr/Set aktiv muss OCR1Bh-Register beachtet werden um
sts OCRb1h,temp0 ;____--- oder _------ zu erreichen
sts OCR1bh,temp0
ldi temp0,$80 ;Toggeln oder Clr/Set aktiv muss OCR1Bl-Register beachtet werden um
sts OCRb1l,temp0 ;____--- oder _------ zu erreichen
sts OCR1bl,temp0
ret

B1_ch_en:
sbi ddrb,2 ;output aktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

B1_ch_dis:
cbi ddrb,2 ;output deaktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

ICR1_ch_load:
ldi temp0,$00 ;Toggeln oder Clr/Set aktiv muss OCR1Bh-Register beachtet werden um
sts ICR1xh,temp0 ;____--- oder _------ zu erreichen
sts ICR1h,temp0
ldi temp0,$09 ;Toggeln oder Clr/Set aktiv muss OCR1Bl-Register beachtet werden um
sts ICR1xl,temp0 ;____--- oder _------ zu erreichen
sts ICR1l,temp0
ret

;**********ISR
INT_CPT1: ;$0014 Timer/Counter1 Capture Event
;ICRH:L wird vom Counter TVCNT1H:L bei Steigender/Fallender Flanke beschrieben
reti

INT_OC1A: ;$0016 Timer/Counter1 Compare Match A
push temp0
rcall prescaler_T0_off
rcall prescaler_T1_off
pop temp0
reti

INT_OC1B: ;$0018 Timer/Counter1 Compare Match B
push temp0
lds temp0,OCRb1h ;Toggeln oder Clr/Set aktiv muss OCR1Bh-Register beachtet werden um
sts OCR1Bh,temp0 ;____--- oder _------ zu erreichen
lds temp0,OCRb1l ;Toggeln oder Clr/Set aktiv muss OCR1Bl-Register beachtet werden um
sts OCR1Bl,temp0 ;____--- oder _------ zu erreichen
pop temp0
reti

INT_OVF1: ;$001A Timer/Counter1 Overflow
reti

;************************************************* ************************************************** ****************
;******************************Init-Modes des Timers2******************************************* ********************
mode0_T2_init:;NORMAL_MODE OCR2 update sofort oder im INT
rcall A2_ch_en ;output aktivieren wenn Toggeln am PINB3=OCR2 erwünscht
rcall B2_ch_en ;Toggeln oder Clr/Set aktiv muss OCR2-Register beachtet werden um
rcall A2_ch_load ;____--- oder _------ zu erreichen
rcall B2_ch_load

lds temp0,TCCR2B
ori temp0,(0<<WGM22)
sts TCCR2B,temp0

lds temp0,TCCR2A
ori temp0,( 0<<WGM21 | 0<<WGM20 )
sts TCCR2A,temp0

lds temp0,TCCR2A
ori temp0,( 0<<COM2A1 | 0<<COM2A0 | 0<<COM2B1 | 0<<COM2B0 ) ;zum Toggeln COM2x Einstellungen beachten!!!!!!!!!
sts TCCR2A,temp0

lds temp0,TIMSK2
ori temp0,( 0<<OCIE2B | 0<<OCIE2A | 1<<TOIE2 );OutputCompareInterrupt deaktiviert
sts TIMSK2,temp0

ret

mode1_T2_init:;PWM-PhaseCorrect
rcall A2_ch_en ;output aktivieren wenn Toggeln am PINB3=OCR2 erwünscht
rcall B2_ch_en ;Toggeln oder Clr/Set aktiv muss OCR2-Register beachtet werden um
rcall A2_ch_load ;____--- oder _------ zu erreichen
rcall B2_ch_load

lds temp0,TCCR2B
ori temp0,(0<<WGM22)
sts TCCR2B,temp0

lds temp0,TCCR2A
ori temp0,( 0<<WGM21 | 1<<WGM20 )
sts TCCR2A,temp0

lds temp0,TCCR2A
ori temp0,( 1<<COM2A1 | 1<<COM2A0 | 0<<COM2B1 | 0<<COM2B0 ) ;zum Toggeln COM2x Einstellungen beachten!!!!!!!!!
sts TCCR2A,temp0

lds temp0,TIMSK2
ori temp0,( 0<<OCIE2B | 1<<OCIE2A | 0<<TOIE2 );OutputCompareInterrupt deaktiviert
sts TIMSK2,temp0

ret

mode2_T2_init:;CTC
;rcall A2_ch_en ;output aktivieren wenn Toggeln am PINB3=OCR2 erwünscht
;rcall B2_ch_en ;Toggeln oder Clr/Set aktiv muss OCR2-Register beachtet werden um
rcall A2_ch_load ;____--- oder _------ zu erreichen
;rcall B2_ch_load

lds temp0,TCCR2B
ori temp0,(0<<WGM22)
sts TCCR2B,temp0

lds temp0,TCCR2A
ori temp0,( 1<<WGM21 | 0<<WGM20 )
sts TCCR2A,temp0

lds temp0,TCCR2A
ori temp0,( 0<<COM2A1 | 1<<COM2A0 | 0<<COM2B1 | 1<<COM2B0 ) ;zum Toggeln COM2x Einstellungen beachten!!!!!!!!!
sts TCCR2A,temp0

lds temp0,TIMSK2
ori temp0,( 0<<OCIE2B | 1<<OCIE2A | 0<<TOIE2 );OutputCompareInterrupt deaktiviert
sts TIMSK2,temp0

ret

mode3_T2_init:;FastPWM
rcall A2_ch_en ;output aktivieren wenn Toggeln am PINB3=OCR2 erwünscht
rcall B2_ch_en ;Toggeln oder Clr/Set aktiv muss OCR2-Register beachtet werden um
rcall A2_ch_load ;____--- oder _------ zu erreichen
rcall B2_ch_load

lds temp0,TCCR2B
ori temp0,(0<<WGM22)
sts TCCR2B,temp0

lds temp0,TCCR2A
ori temp0,( 1<<WGM21 | 1<<WGM20 )
sts TCCR2A,temp0

lds temp0,TCCR2A
ori temp0,( 0<<COM2A1 | 1<<COM2A0 | 0<<COM2B1 | 1<<COM2B0 ) ;zum Toggeln COM2x Einstellungen beachten!!!!!!!!!
sts TCCR2A,temp0

lds temp0,TIMSK2
ori temp0,( 1<<OCIE2B | 1<<OCIE2A | 0<<TOIE2 );OutputCompareInterrupt deaktiviert
sts TIMSK2,temp0

ret

mode5_T2_init:;PWM PHASE CORRECT
rcall A2_ch_en ;output aktivieren wenn Toggeln am PINB3=OCR2 erwünscht
rcall B2_ch_en ;Toggeln oder Clr/Set aktiv muss OCR2-Register beachtet werden um
rcall A2_ch_load ;____--- oder _------ zu erreichen
rcall B2_ch_load

lds temp0,TCCR2B
ori temp0,(1<<WGM22)
sts TCCR2B,temp0

lds temp0,TCCR2A
ori temp0,( 0<<WGM21 | 1<<WGM20 )
sts TCCR2A,temp0

lds temp0,TCCR2A
ori temp0,( 0<<COM2A1 | 1<<COM2A0 | 1<<COM2B1 | 0<<COM2B0 ) ;zum Toggeln COM2x Einstellungen beachten!!!!!!!!!
sts TCCR2A,temp0

lds temp0,TIMSK2
ori temp0,( 1<<OCIE2B | 1<<OCIE2A | 0<<TOIE2 );OutputCompareInterrupt deaktiviert
sts TIMSK2,temp0

ret

mode7_T2_init:;FAST PWM
rcall A2_ch_en ;output aktivieren wenn Toggeln am PINB3=OCR2 erwünscht
rcall B2_ch_en ;Toggeln oder Clr/Set aktiv muss OCR2-Register beachtet werden um
rcall A2_ch_load ;____--- oder _------ zu erreichen
rcall B2_ch_load

lds temp0,TCCR2B
ori temp0,(1<<WGM22)
sts TCCR2B,temp0

lds temp0,TCCR2A
ori temp0,( 1<<WGM21 | 1<<WGM20 )
sts TCCR2A,temp0

lds temp0,TCCR2A
ori temp0,( 1<<COM2A1 | 1<<COM2A0 | 1<<COM2B1 | 1<<COM2B0 ) ;zum Toggeln COM2x Einstellungen beachten!!!!!!!!!
sts TCCR2A,temp0

lds temp0,TIMSK2
ori temp0,( 1<<OCIE2B | 1<<OCIE2A | 0<<TOIE2 );OutputCompareInterrupt deaktiviert
sts TIMSK2,temp0

ret

prescaler_T2_on:
lds temp0,TCCR2B
ori temp0,(1<<CS22|1<<CS21|1<<CS20) ;schmeißt den counter an
sts TCCR2B,temp0
sei
ret

prescaler_T2_off:
lds temp0,TCCR2B
andi temp0,(0<<CS22|0<<CS21|0<<CS20) ;stoppt den counter an
sts TCCR2B,temp0
ret

T2_clr: clr temp0
sts TCNT2,temp0
ret

;**********Channel load
A2_ch_load:
ldi temp0,$4d ;Toggeln oder Clr/Set aktiv muss OCR1Ah-Register beachtet werden um
sts OCR2A,temp0
clr temp0
sts ocra2,temp0
ret

A2_ch_en:
sbi ddrb,3 ;output aktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

A2_ch_dis:
cbi ddrb,3 ;output deaktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

B2_ch_load:
ldi temp0,$40 ;Toggeln oder Clr/Set aktiv muss OCR1Ah-Register beachtet werden um
sts OCR2B,temp0
sts ocrb2,temp0
ret

B2_ch_en:
sbi ddrd,3 ;output aktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret

B2_ch_dis:
cbi ddrd,3 ;output deaktivieren wenn Toggeln am PINB1=OCR1A erwünscht
ret


;*******ISR
INT_OC2A: ;$000E
lds temp0,ocra2
inc temp0
sts ocra2,temp0
cpi temp0,$64
breq INT_OC2A2
sts ocra2,temp0
reti
INT_OC2A2:
clr temp0
sts ocra2,temp0
sbic pinb,5
cbi portb,5
sbis pinb,5
sbi portb,5
reti

INT_OC2B: ;$0010
push temp1
lds temp1,ocrb2
sts OCR2B,temp1
pop temp1
reti

INT_OVF2: ;$0012
reti

oberallgeier
20.08.2018, 10:09
In diesem Artikel gehts mal um das Ultraschallmodul HC-SR04 ..Bravo. Schön, cool, endlich wieder was Schickes per ASM. Ich schreibe seit Jahren zwar nix mehr so elementar, aber meine AVR-Anfänge waren nur ASM. Sogar nen Servotester gibts bei mir - sehr einfach, programmiert in ASM (https://www.roboternetz.de/community/threads/44919-Servo-tester-mit-ATiny13?p=430092&viewfull=1#post430092) !


.. Informatives zum Schall: .. 331,5m/s bei 0°C, bei zunehmender Temperatur wird der Schall um 0,6m/s pro °C schneller ..Gut, Deine Daten sind aber NUR auf MSL bezogen! Denk daran, dass die Gasgleichung

https://wikimedia.org/api/rest_v1/media/math/render/svg/d9c91015cbefe70ac353df47e6c9dbe421f9d338

den Druck enthält *gg* - und der ändert sich halt und das nicht nur mit der so genannten Meereshöhe, besser Höhe über NormalNull (heißt heute anders). Meine Schreibtischoberkante steht auf 812 m über AMSL - da gelten Deine Daten eben nicht mehr :-/ . Selbst die Schwerkraft ist bei mir geringer. Andererseits führt der Temperatureinfluss dazu, dass für uns Flieger die Berge im Winter höher sind . . .

avr_racer
20.08.2018, 10:53
AtMega328_uart_std.asm

;************************Unterprogramme*********** *******************
rx: rcall data_received ;warte auf daten von PC
cpi temp1,' ' ;vergleich auf leerzeichen
brne rx ;sonst wenn falsch warte weiter
ldi temp1,'*' ;
rcall data_transmit ;sende * als ack
ret

tx: rcall wait150ms
ldi temp1,'T'
rcall data_transmit ;sende T
ldi temp1,'S'
rcall data_transmit ;sende S
ldi temp1,'T'
rcall data_transmit ;sende T
ret
;*********************Textausgabe aus DB***********************************
txt_out_rs_debug:
rcall debug_pnt ;Pointer für Debug laden wird alles in SRAM ab Adresse $0060 geschrieben
txt_out_rs:
lpm temp1,z+ ;!!! muss in der .db *2 genommen werden
cpi temp1,$ff
breq txt_out_rs_end
; st x+,temp1 ;nur einschalten wenn debug angesprungen wird
rcall data_transmit ;z.b.: ldi ZH,high(out0*2)
rjmp txt_out_rs
txt_out_rs_end:
ret

debug_pnt:
ldi xh,high(RSdebug)
ldi xl,low(RSdebug)
ret

;***********This is an ENTER omg*******************************************
enter_rs232:
ldi temp1,$0d
rcall data_transmit
ldi temp1,$0a
rcall data_transmit
ret

leer_zeichen_rs232:
ldi temp1,' '
rcall data_transmit
ret

;***************************ZahlenAusgabe********* ****************
zahl_rs_load_out_xy:
rcall hex_dez ;Zahlenwandlung
push yh ;on stack anderer AdressBereich
push yl ;on stack
rcall load_Y_ergk1 ;Startbyte ; load_Y_ergk(n) (5Byte), n=1(4byte), n=2(3byte), n=3(2byte), n=4(1byte)
ldi temp3,high(erg_k+3)
ldi temp4,low(erg_k+3); Ende
rjmp zahl_rs_load_out2

zahl_rs_load_out:
; ld mathergll,y+ ;alles in die Mathregs laden
; clr mathergl
; clr mathergh
; clr matherghh
rcall hex_dez ;Zahlenwandlung
push yh ;on stack anderer AdressBereich
push yl ;on stack
rcall load_Y_ergk2 ;maximale Ausgabe an Zahlen also 5Byte; load_Y_ergk1(4byte),2(3byte),3(2byte),4(1byte)
ldi temp3,high(erg_k+5)
ldi temp4,low(erg_k+5)
zahl_rs_load_out2:
rcall zahl_out_rsx ;Dez in ASCII + Ausgabe
cp yl,temp4 ;
brne zahl_rs_load_out2
pop yl ;from stack
pop yh ;from stack
ret

zahl_out_rsx: ;RSX Ausgabe mit Variabler BYTEZAHL durch load_Y_ergk festgelegt
ld temp1,y+
rjmp zahl_out_rs
zahl_out_rs1: ;rs Ausgabe 2er Zahlen = 1Byte
ld temp1,y ; nur um 1byte auszugeben
zahl_out_rs: ;wird nur rs1 angesprungen müssen die Daten vorher geladen werden
mov temp2,temp1
swap temp1
andi temp1,$0f
ori temp1,$30
rcall data_transmit ;Zehnerausgabe
;Ausgbabe 1er Zahl
mov temp1,temp2
andi temp1,$0f
ori temp1,$30
rcall data_transmit ;Einerausgabe
ret

;*****************Wandlung von 1A-hex in 1A-ASCII = 31 , 41 Anzeige ist 1 A
adr_hex_ASCII_rs: ;Daten vorher in Temp1 laden
pc_ser2:mov temp2,temp1 ;byte sichern

swap temp1 ;swapen
andi temp1,$0f ;ausanden
cpi temp1,$0a ;vergleich ob >= 10
brsh pc_ser21 ;wenn ja mach ein HexBuchstabe zu ASCII-Buschstabe
subi temp1,-$30 ;wenn nein mach HexZahl zu ASCII-Zahl
rjmp pc_ser22
pc_ser21:
subi temp1,-$37 ;HexBuchstabe zu ASCII-Buschstabe
pc_ser22:
rcall data_transmit ;und ab damit zum PC
mov temp1,temp2 ;gesichertes byte laden
andi temp1,$0f ;ausanden
cpi temp1,$0a ;vergleich ob >= 10
brsh pc_ser31 ;wenn ja mach ein HexBuchstabe zu ASCII-Buschstabe
subi temp1,-$30 ;wenn nein mach HexZahl zu ASCII-Zahl
rjmp pc_ser32
pc_ser31:
subi temp1,-$37 ;HexBuchstabe zu ASCII-Buschstabe
pc_ser32:
rcall data_transmit ;und ab damit zum PC
rcall leer_zeichen_rs232 ;leerzeichen
rcall enter_rs232 ;wenn ja mach noch ein ENTER
ret

;************************uart_init mit RX interrupt**********************
usart_init:
ldi temp0,high (UBRR0)
ldi temp1,low (UBRR0)
sts UBRR0H,temp0 ;9600 Baud einstellen PDF S.133 table52
sts UBRR0L,temp1

rcall char_size8 ;8 zeichen, 1 stoppbit

lds temp0,UCSR0A
ori temp0,(0<<U2X0|0<<MPCM0) ;no DoubleSpeed, no MultiProzComMode
sts UCSR0A,temp0

ret

char_size5:
ldi temp0,(0<<UMSEL01|0<<UMSEL00|0<<UPM01|0<<UPM00|0<<USBS0|0<<UCSZ01|0<<UCSZ00|0<<UCPOL0) ; UCSRC1 or UBRRH0,USBS=0 stoppbits1,
sts UCSR0C,temp0
ldi temp0,(0<<RXCIE0|0<<TXCIE0|0<<UDRIE0|1<<RXEN0|1<<TXEN0|0<<UCSZ02) ;enable RX u TX <=5bit(UCSZ2=0)
sts UCSR0B,temp0 ;
ret

char_size6:
ldi temp0,(0<<UMSEL01|0<<UMSEL00|0<<UPM01|0<<UPM00|0<<USBS0|0<<UCSZ01|1<<UCSZ00|0<<UCPOL0) ;UCSRC1 or UBRRH0,USBS=0 stoppbits1,
sts UCSR0C,temp0
ldi temp0,(0<<RXCIE0|0<<TXCIE0|0<<UDRIE0|1<<RXEN0|1<<TXEN0|0<<UCSZ02) ;enable RX u TX <=6bit(UCSZ2=0)
sts UCSR0B,temp0
ret

char_size7:
ldi temp0,(0<<UMSEL01|0<<UMSEL00|0<<UPM01|0<<UPM00|0<<USBS0|1<<UCSZ01|0<<UCSZ00|0<<UCPOL0) ;UCSRC1 or UBRRH0,USBS=0 stoppbits1,
sts UCSR0C,temp0
ldi temp0,(0<<RXCIE0|0<<TXCIE0|0<<UDRIE0|1<<RXEN0|1<<TXEN0|0<<UCSZ02) ;enable RX u TX <=7bit(UCSZ2=0)
sts UCSR0B,temp0 ;
ret

char_size8:
ldi temp0,(0<<UMSEL01|0<<UMSEL00|0<<UPM01|0<<UPM00|0<<USBS0|1<<UCSZ01|1<<UCSZ00|0<<UCPOL0) ;UCSRC1 or UBRRH0,USBS=0 stoppbits1,
sts UCSR0C,temp0
ldi temp0,(0<<RXCIE0|0<<TXCIE0|0<<UDRIE0|1<<RXEN0|1<<TXEN0|0<<UCSZ02) ;enable RX u TX <=7bit(UCSZ2=0)
sts UCSR0B,temp0
ret

char_size9:
ldi temp0,(0<<UMSEL01|0<<UMSEL00|0<<UPM01|0<<UPM00|0<<USBS0|1<<UCSZ01|1<<UCSZ00|0<<UCPOL0) ;UCSRC1 or UBRRH0,USBS=0 stoppbits1,
sts UCSR0C,temp0
ldi temp0,(0<<RXCIE0|0<<TXCIE0|0<<UDRIE0|1<<RXEN0|1<<TXEN0|1<<UCSZ02) ;enable RX u TX <=9bit(UCSZ2=1)
sts UCSR0B,temp0
ret

;************************uart_deinit************** ******************
usart_all_aus:
clr temp0
sts UCSR0B,temp0
sts UCSR0C,temp0
sts UBRR0L,temp0
sts UBRR0H,temp0
ret

usart_ofln: ;wenn unterprogramme nicht
clr temp0 ;gestört werden dürfen
sts UCSR0B,temp0 ;nur usart offline
ret

;**********************daten_senden*************** ******************
INT_USART_RX:
;siehe data_transmit;** man kann in der wartezeit andere sachen erledigen
;bis der int kommt im INT selbst könnte man ne art daten-lese-schleife implementieren
;um weitere daten zu senden die dann an temp1>>>UDR weitergegeben werden
sts UDR0,temp1 ; Put LSB data (r17) into buffer, tranceived data
reti
;(polling)
data_transmit:
lds temp0,UCSR0A
sbrs temp0,UDRE0 ;**
rjmp data_transmit ;**
sts UDR0,temp1 ; Put LSB data (r17) into buffer, tranceived data
ret

;**********************daten_empfangen **********************
INT_USART_TX:
lds temp1,UDR0 ; Put data from buffer into r17, received Data
;siehe data_received;** man kann in der wartezeit andere sachen erledigen
;bis der int kommt im INT selbst könnte man ne art daten-schreib-schleife implementieren
;um weitere daten zu empfangen die dann an UDR>>>temp1 weitergegeben werden
reti
;(polling)
data_received:
lds temp0,UCSR0A
sbrs temp0,RXC0 ;**
rjmp data_received ;**
lds temp1,UDR0 ; Put data from buffer into r17, received Data
ret

;********************DatenRegisterLeereInterrupt** *********************
INT_UDRE:
;SOLANGE dieses register leer ist wird diese routine aufgerufen
;also eigentlich immer wenn UDR=0
reti


AtMega328_RS_Txt_out.asm

;**************Zeichen AUSGABE PC**************************************
werbe_rs:
ldi ZH,high(rs_out0*2)
ldi ZL,low(rs_out0*2)
rcall txt_out_rs
;rcall txt_out_rs_debug
rcall enter_rs232
ret

Sonar1_rs:
ldi ZH,high(rs_out1*2)
ldi ZL,low(rs_out1*2)
rcall txt_out_rs
;rcall txt_out_rs_debug
;rcall enter_rs232
ret

millimeter_rs:
ldi ZH,high(rs_out2*2)
ldi ZL,low(rs_out2*2)
rcall txt_out_rs
;rcall txt_out_rs_debug
rcall enter_rs232
rcall enter_rs232
ret

microsekunden_rs:
ldi ZH,high(rs_out3*2)
ldi ZL,low(rs_out3*2)
rcall txt_out_rs
;rcall txt_out_rs_debug
rcall enter_rs232
ret

;************************Zahleausgabe************* ******************
HCSR04_micros_out_uart:
rcall Sonar1_rs
lds mathergll,Sonar1l ;alles in die Mathregs laden
lds mathergl,Sonar1h
clr mathergh
clr matherghh
rcall zahl_rs_load_out
rcall microsekunden_rs
ret

HCSR04_mm_out_uart:
rcall Sonar1_rs
rcall zahl_rs_load_out_xy ;variable Ausgabe
rcall millimeter_rs
ret

;************************direktwandlung*wort*in*AS CII***************
rs_out0: .db "Ultraschall HC-SR04 V0.1",$ff
rs_out1: .db "Distanz: ",$ff
rs_out2: .db "mm",$ff
rs_out3: .db "us",$ff


HC_SR04_2.asm

;********************HC-SR04 Ultraschallsensor*******************
.equ HCSR04_ddr = DDRD
.equ HCSR04_pin = PIND
.equ HCSR04_port= PORTD

.equ Echo = 3
.equ Trigger = 4

.equ CTC_T0 = 7 ; benötigt um 1µs zu erzeugen

.equ T1_max_h = $75 ;high der 30000µs
.equ T1_max_l = $30 ;low der 30000 µs

.equ V_US_20 = 3430 ;dm/s 343 bezogen auf 20°C! Mit Temperatursensor kann hier eingegriffen werden
;************************Init********************* ***************
init_HCSR04:
sbi HCSR04_ddr,Trigger ;Triggerpin als Ausgang setzen
cbi HCSR04_ddr,ECHO
cbi HCSR04_port,ECHO ;Echopin = INT1 als Eingang

rcall INIT_EXT_INT01 ;Int1 = Echo und Aktivierung von T0 auf st. Flanke
rcall mode2_T0_init ;Auflösung 1µs im CTC ohne INT von OCR0A/B, Toggle OCR0B=PD5, Teiler 1 mit CTC_T0
rcall mode0_T1_init ;Teiler auf ext. Eingang PD5, OCR1A = T1_max

ret

;**********************Messung starten***************************
HCSR04_Start:
clr temp1
out TCNT0,temp1
sts TCNT1h,temp1
sts TCNT1l,temp1
rcall HCSR04_Trigger ;Trigger starten
;HCSR04 beginnt nach 450µs mit dem setzen des Echos auf High
;deshalb INT1 auf steigende Flanke
HCSR04_wait:
nop
nop
nop
nop
sbis HCSR04_pin,Echo ;warten bis EchoPin H ist
rjmp HCSR04_wait ;sonst Sprung
HCSR04_wait2:
nop
nop
nop
nop
sbic HCSR04_pin,Echo
rjmp HCSR04_wait2 ;warten bis Echo zurück kommt H-L
rcall prescaler_T0_off ;
rcall prescaler_T1_off ;beide Timer stoppen
lds temp1,TCNT1L
lds temp0,TCNT1H ;Zeit in µs auslesen = doppelter Weg
lsr temp0
ror temp1 ;einmal halbieren
sts sonar1h,temp0
sts sonar1l,temp1 ;Rohzeit in µs speichern = einfacher Weg
ret

HCSR04_Trigger:
sbi HCSR04_port,Trigger
rcall wait10us
rcall wait10us
cbi HCSR04_port,Trigger
ret

;***********************Berechnung der Entfernung anhand ************************
;***********************der Geschwindigkeit und der gem. Zeit ************************
Zeit_zu_Entfernung: ;Geschwindigkeit Schall * Zeit = Entfernung Bsp.: 343m/s * 15001µs = 5145343µm
ldi temp3,high (V_US_20)
ldi temp2,low (V_US_20) ;feste oder errechnete Schgallgeschwindigkeit laden
lds temp1,sonar1h
lds temp0,sonar1l ; Zeit in µs laden

mov math1h,temp3
mov math1l,temp2
mov math2h,temp1
mov math2l,temp0

rcall hmul_2_16bit ; Berechnung durchführen Erg in Mathergll:hh
ret



- - - Aktualisiert - - -

zum angesprochenen Punkt der Luftdruck kann vernachlässigt werden solange man es nicht im Vakuum nutzen möchte...
http://automatisierungstechnik.fh-pforzheim.de/fileadmin/offenes_labor/sensorik/windgeschwindigkeit/doc/DieSchallgeschwindigkeitLuftdruck.pdf

HaWe
20.08.2018, 12:55
zum angesprochenen Punkt der Luftdruck kann vernachlässigt werden solange man es nicht im Vakuum nutzen möchte...
http://automatisierungstechnik.fh-pforzheim.de/fileadmin/offenes_labor/sensorik/windgeschwindigkeit/doc/DieSchallgeschwindigkeitLuftdruck.pdf

stimmt, eher ist die absolute Feuchte interessant, aber auch das wird in der Messgenauigkeit eher untergehen 8)

avr_racer
22.08.2018, 12:04
Nachtrag Zeitschleifen für 16Mhz

zeitschleifen_16Mhz.asm


;************************zeitschleifen************ ******************************

wait1us:nop
ret

wait6us:push xh
push xl
ldi xh,$00
ldi xl,$0f
rjmp z_loop2

wait9us:push xh
push xl
ldi xh,$00
ldi xl,$19
rjmp z_loop2

wait10us:
push xh
push xl
ldi xh,$00
ldi xl,$1c
rjmp z_loop2

wait25us:
push xh
push xl
ldi xh,$00
ldi xl,$4c
rjmp z_loop2

wait50us:
push xh
push xl
ldi xh,$00
ldi xl,$9c
rjmp z_loop2

wait55us:
push xh
push xl
ldi xh,$00
ldi xl,$ac
rjmp z_loop2

wait58us:
push xh
push xl
ldi xh,$00
ldi xl,$b6
rjmp z_loop2

wait60us:
push xh
push xl
ldi xh,$00
ldi xl,$bc
rjmp z_loop2

wait64us:
push xh
push xl
ldi xh,$00
ldi xl,$c9
rjmp z_loop2

wait70us:
push xh
push xl
ldi xh,$00
ldi xl,$dc
rjmp z_loop2

wait100us:
push xh
push xl
ldi xh,$01
ldi xl,$3c
rjmp z_loop2

wait500us:
push xh
push xl
ldi xh,$06
ldi xl,$3a
rjmp z_loop2

wait1ms:push xh
push xl
ldi xh,$0c
ldi xl,$78
rjmp z_loop2


wait10ms:push xh
push xl
ldi xh,$7c
ldi xl,$cc
rjmp z_loop2

wait150ms:
ldi temp0,$0f
rjmp waitx10ms

wait750ms:
ldi temp0,$4b
rjmp waitx10ms

wait1s: ldi temp0,$64
rjmp waitx10ms



z_loop2:sbiw xh:xl,$01
cpi xl,$00
brne z_loop2
cpi xh,$00
brne z_loop2
pop xl
pop xh
ret

waitxms:rcall wait1ms
dec temp0
brne waitxms
ret

waitx10ms:
rcall wait10ms
dec temp0
brne waitx10ms
ret

avr_racer
30.08.2018, 12:05
So Update wie angekündigt

mit / ohne Temperatursensor
Berechnung der Geschwindigkeit bei ändernder Temperatur

33592