avr_racer
12.08.2017, 13:55
Moin moin,
Die Bibliothek zielt auf den oben genannten AVR ATMega x8 ab. Dieser unterscheidet sich nur in der Flash/EEPROM/SRAMgröße. Der 48er z.B. ist ein Atmega8 mit nur 4kB Flash, 256byte EEPROM und 512byte SRAM. Der 328 hat das 8fache an Flash/Sram und das 4fache des EEPROMs eines 48er.
Auch hier können wieder die Bibliotheken vom LCD/Mathe/HexWandlung kompatibel benutzt werden.
ATMEGA328_origin.asm
;###########################################
;# Projekt: #
;# #
;# #
;# Taktfrequenz des AVR: 4 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 = 4000000
.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 RSdebug = $0140 ;debug serielle Schnittstelle
;***************************Einsprungadressen***** ******************
.cseg
.org $0000
rjmp stack
.org $0002 ;2
reti;rjmp INT_EX0
.org $0004 ;4
reti;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
rjmp INT_OC2A;reti
.org $0010 ;10
reti;rjmp INT_OC2B
.org $0012 ;12
reti;rjmp INT_OVF2
.org $0014 ;14
reti;rjmp INT_CPT1
.org $0016 ;16
reti;rjmp INT_OC1A
.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 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 ADC_Wandlung_Ausgabe_lcd
rjmp start
ADC_Wandlung_Ausgabe_lcd:
rcall adc_chan_0
rcall start_convers
ldi temp1,high(ref5)
ldi temp0,low(ref5)
mov math1h,temp1
mov math1l,temp0
lds math2h,hadc
lds math2l,ladc
rcall hmul_2_16bit ;Ergebenisse in Ergebnissregister
rcall zahl_out_lcd ;Zahlenausgabe über LCD
ret
;*********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_adc_lst.asm"
.include "AtMega328_analogcomparator.asm"
.include "AtMega328_ext_ints.asm"
.include "AtMega328_eeprom.asm"
.include "AtMega328_timercounter.asm"
.include "AtMega328_uart_std.asm"
.include "AtMega328_LCD_Txt_out.asm"
.include "AtMega328_RS_Txt_out.asm"
.include "i:\etronik\Software3\sonstiges\origin\mathe.asm"
.include "i:\etronik\Software3\sonstiges\origin\lcd_KS0066_K S0070_8bit.asm"
;.include "i:\etronik\Software3\sonstiges\origin\lcd_KS0066_K S0070_4bit_HapSim.asm" ;Nur zur Simulation mit HapSim aktivieren
.include "i:\etronik\Software3\sonstiges\origin\zeitschleife n.asm"
.include "i:\etronik\Software3\sonstiges\origin\hex_dez_wand lung.asm" ;gebraucht für LCD oder nur umwandlung
;*************************ENDE******************** ******************
.include "AtMega328_adc_lst.asm"
/*
.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 ref256 = $09d0
*/
;***********************adc_header**************** **********
adc_header:
rcall adc_init
;rcall start_convers_int ;mit Interrupt
rcall start_convers ;ohne Interrupt
ret
;***********************adc_init****************** ***********
adc_init:
ldi temp0,(0<<Chan5|0<<Chan4|0<<Chan3|0<<Chan2|0<<Chan1|0<<Chan0)
out ADC_ddr,temp0
ldi temp0,(0<<Chan5|0<<Chan4|0<<Chan3|0<<Chan2|0<<Chan1|0<<Chan0)
out ADC_Pin,temp0
ldi temp0,(1<<ADEN|0<<ADSC|0<<ADATE/*|ADIF*/|0<<ADIE|1<<ADPS2|0<<ADPS1|1<<ADPS0) ;ADC aktivieren Sample 50khz-250Khz
sts ADCSRA,temp0
ldi temp0,(0<<ACME | 0<<ADTS2 | 0<<ADTS1 | 0<<ADTS0 ) ;TRIGGER SOURCE
sts ADCSRB,temp0
rcall adc_ref_5V ;Interne 5V-Referenz
rcall adc_chan_gnd
ret
;*********************AREF
adc_ref_extern: ;extern on
ldi temp0,(0<<REFS1|0<<REFS0) ;AREF, Internal Vref turned off
sts admux,temp0
ret
adc_ref_5V: ;AREF 5V
ldi temp0,(0<<REFS1|1<<REFS0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
/*
adc_ref_reserve: ;reserve
in temp0,admux
ori temp0,(1<<REFS1|0<<REFS0) ;RESERVED
out admux,temp0
ret
*/
adc_ref_11V: ;1,1V on
ldi temp0,(1<<REFS1|1<<REFS0) ;internal 1,1V AREF pin
sts admux,temp0
ret
;mit Interrupt
start_convers_int:
lds temp0,adcsra ;wenn ADFR aktiv dann nur adc_read nötig für jeweiligen kanal
ori temp0,(0<<ADEN|1<<ADSC|0<<ADATE/*|ADIF*/|1<<ADIE|1<<ADPS2|0<<ADPS1|0<<ADPS0) ;freigabe ADC Abtastrate zwischen 50Khz-200Khz Teiler=32 single mode
sts adcsra,temp0 ;
sei
ret
;ohne Interrupt dann abfrage auf des bits ADSC=1?????
start_convers:
cli
lds temp0,ADCSRA
ori temp0,(0<<ADEN|1<<ADSC|0<<ADATE/*|ADIF*/|0<<ADIE|1<<ADPS2|0<<ADPS1|1<<ADPS0);freigabe der Messung
sts adcsra,temp0
start_convers2:
lds temp0,ADCSRA ;;;
sbrc temp0,ADSC ;;;;;; diese kleine routine braucht man nicht wenn man mit ints arbeitet
rjmp start_convers2 ;;;
rcall adc_chan_gnd
lds temp0,adcl ;wichtig erst low
lds temp1,adch ;dann high lesen sonst erg müll
sts hadc,temp1
sts ladc,temp0
sei
ret
;*******************Channels********************** ************************************************** **************
adc_chan_0:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|0<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_1:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|0<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_2:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|1<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_3:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|1<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_4:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|0<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_5:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|0<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_6:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|1<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_7:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|1<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_8:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|1<<MUX3|0<<MUX2|0<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_BG:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|1<<MUX3|1<<MUX2|1<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_gnd:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|1<<MUX3|1<<MUX2|1<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
;**************U-Ref laden***********************************
ref_5v: ldi temp1,high(ref5)
ldi temp0,low(ref5)
ret
ref_52v:ldi temp1,high(ref52)
ldi temp0,low(ref52)
ret
ref_256v:
ldi temp1,high(ref256)
ldi temp0,low(ref256)
ret
ref_2562v:
ldi temp1,high(ref2562)
ldi temp0,low(ref2562)
ret
;******************************adc_interrupt****** ****************
INT_ADC:
lds temp0,adcl ;wichtig erst low
sts ladc,temp0
lds temp1,adch ;dann high lesen sonst erg müll
sts hadc,temp1
reti
.include "AtMega328_analogcomparator.asm"
;ACHTUNG man kann im simulator nicht mit PD6/7 simulieren geht nur
;wenn ACO händisch gesetzt wird ACO=1 wird auch ACI=1 um den int zu nutzen
;wenn man den int nicht nutzt ist die abfrage auf ACO
AC_init:lds temp0,ADCSRB
ori temp0,(0<<ACME)
sts ADCSRB,temp0
ldi temp0,(0<<ACD|0<<ACBG|1<<ACIE|0<<ACIC|0<<ACIS1|0<<ACIS0)
out ACSR,temp0
sei ;
ret
;AUSWAHL neagtiver Input vom ADC
AC_negative_AC0:
rcall AC_negative_IN_init
rcall adc_chan_0
ret
AC_negative_AC1:
rcall AC_negative_IN_init
rcall adc_chan_1
ret
AC_negative_AC2:
rcall AC_negative_IN_init
rcall adc_chan_2
ret
AC_negative_AC3:
rcall AC_negative_IN_init
rcall adc_chan_3
ret
AC_negative_AC4:
rcall AC_negative_IN_init
rcall adc_chan_4
ret
AC_negative_AC5:
rcall AC_negative_IN_init
rcall adc_chan_5
ret
AC_negative_AC6:
rcall AC_negative_IN_init
rcall adc_chan_6
ret
AC_negative_AC7:
rcall AC_negative_IN_init
rcall adc_chan_7
ret
AC_negative_IN_init:
ldi temp0,(1<<ACME)
sts ADCSRB,temp0
ldi temp0,(0<<ADEN)
sts ADCSRA,temp0
ret
ac_change:
in temp0,ACSR
sbrs temp0,ACO
rjmp ac_change
ret
INT_ANALOG_COMP:
;wird aufgerufen wenn pd6+/pd7- pegelunterschiede feststellen
reti
.include "AtMega328_ext_ints.asm"
;PD2/3 sind INT0/1
INIT_EXT_INT01:
lds temp0,EICRA
ori temp0,(1<<ISC11|1<<ISC10|1<<ISC01|1<<ISC00) ;hier INT0/1 auf steigende flanke siehe PDF KAP.13
sts EICRA,temp0
in temp0,EIMSK
ori temp0,(1<<INT1|1<<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
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
.include "AtMega328_eeprom.asm"
;*************************************
eeprom_init:
ldi temp0,(1<<EERIE)
out EECR,temp0
sei
ret
eeprom_rdy:
;siehe eeprom_write ;** man kann in der wartezeit andere sachen erledigen
;bis der int kommt, um dann weitere daten an den eeprom zum schreiben zu senden
;nur bei eeprom schreiben möglich
reti
;Adreessierung im eeprom
adr_cnt:ldi r25,high(EEPROMEND+1)
ldi r24,low(EEPROMEND+1)
lds yh,eep_adrh
lds yl,eep_adrl
adiw yh:yl,$01
cp yl,r24
cpc yh,r25
breq adr_cnt_eeprom_end
sts eep_adrl,yl
sts eep_adrh,yh
ret
adr_cnt_eeprom_end:
ret
EEPROM_write:
sbic EECR,EEPE ;** falls eewe im eecr noch gesetzt
rjmp EEPROM_write ;** spring zu zurück
lds r18,eep_adrh
lds r17,eep_adrl
out EEARH, r18 ;highbyte der adr
out EEARL,r17 ;lowbyte der adr
out EEDR,r16 ;zu speichernder wert
sbi EECR,EEMPE ;sperrt eeprom master write enable
sbi EECR,EEPE ;setze EEWE um eeprom zu schreiben
ret
EEPROM_read:
sbic EECR,EEPE ;falls eewe im eecr noch gesetzt
rjmp EEPROM_read ;springe zurück
lds r18,eep_adrh
lds r17,eep_adrl
out EEARH, r18 ;highbyte der adr
out EEARL, r17 ;lowbyte der adr
sbi EECR,EERE ;sperrt lesen des eeproms
in r16,EEDR ;zu lesender wert
ret
- - - Aktualisiert - - -
.include "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 NUR ein OCR nutzbar A oder B ausser
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,(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|0<<WGM00)
out TCCR0A,temp0
lds temp1,TIMSK0
ori temp1,(1<<OCIE0B | 1<<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,$50 ;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,$25 ;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
Fortsetzung folgt
Die Bibliothek zielt auf den oben genannten AVR ATMega x8 ab. Dieser unterscheidet sich nur in der Flash/EEPROM/SRAMgröße. Der 48er z.B. ist ein Atmega8 mit nur 4kB Flash, 256byte EEPROM und 512byte SRAM. Der 328 hat das 8fache an Flash/Sram und das 4fache des EEPROMs eines 48er.
Auch hier können wieder die Bibliotheken vom LCD/Mathe/HexWandlung kompatibel benutzt werden.
ATMEGA328_origin.asm
;###########################################
;# Projekt: #
;# #
;# #
;# Taktfrequenz des AVR: 4 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 = 4000000
.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 RSdebug = $0140 ;debug serielle Schnittstelle
;***************************Einsprungadressen***** ******************
.cseg
.org $0000
rjmp stack
.org $0002 ;2
reti;rjmp INT_EX0
.org $0004 ;4
reti;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
rjmp INT_OC2A;reti
.org $0010 ;10
reti;rjmp INT_OC2B
.org $0012 ;12
reti;rjmp INT_OVF2
.org $0014 ;14
reti;rjmp INT_CPT1
.org $0016 ;16
reti;rjmp INT_OC1A
.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 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 ADC_Wandlung_Ausgabe_lcd
rjmp start
ADC_Wandlung_Ausgabe_lcd:
rcall adc_chan_0
rcall start_convers
ldi temp1,high(ref5)
ldi temp0,low(ref5)
mov math1h,temp1
mov math1l,temp0
lds math2h,hadc
lds math2l,ladc
rcall hmul_2_16bit ;Ergebenisse in Ergebnissregister
rcall zahl_out_lcd ;Zahlenausgabe über LCD
ret
;*********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_adc_lst.asm"
.include "AtMega328_analogcomparator.asm"
.include "AtMega328_ext_ints.asm"
.include "AtMega328_eeprom.asm"
.include "AtMega328_timercounter.asm"
.include "AtMega328_uart_std.asm"
.include "AtMega328_LCD_Txt_out.asm"
.include "AtMega328_RS_Txt_out.asm"
.include "i:\etronik\Software3\sonstiges\origin\mathe.asm"
.include "i:\etronik\Software3\sonstiges\origin\lcd_KS0066_K S0070_8bit.asm"
;.include "i:\etronik\Software3\sonstiges\origin\lcd_KS0066_K S0070_4bit_HapSim.asm" ;Nur zur Simulation mit HapSim aktivieren
.include "i:\etronik\Software3\sonstiges\origin\zeitschleife n.asm"
.include "i:\etronik\Software3\sonstiges\origin\hex_dez_wand lung.asm" ;gebraucht für LCD oder nur umwandlung
;*************************ENDE******************** ******************
.include "AtMega328_adc_lst.asm"
/*
.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 ref256 = $09d0
*/
;***********************adc_header**************** **********
adc_header:
rcall adc_init
;rcall start_convers_int ;mit Interrupt
rcall start_convers ;ohne Interrupt
ret
;***********************adc_init****************** ***********
adc_init:
ldi temp0,(0<<Chan5|0<<Chan4|0<<Chan3|0<<Chan2|0<<Chan1|0<<Chan0)
out ADC_ddr,temp0
ldi temp0,(0<<Chan5|0<<Chan4|0<<Chan3|0<<Chan2|0<<Chan1|0<<Chan0)
out ADC_Pin,temp0
ldi temp0,(1<<ADEN|0<<ADSC|0<<ADATE/*|ADIF*/|0<<ADIE|1<<ADPS2|0<<ADPS1|1<<ADPS0) ;ADC aktivieren Sample 50khz-250Khz
sts ADCSRA,temp0
ldi temp0,(0<<ACME | 0<<ADTS2 | 0<<ADTS1 | 0<<ADTS0 ) ;TRIGGER SOURCE
sts ADCSRB,temp0
rcall adc_ref_5V ;Interne 5V-Referenz
rcall adc_chan_gnd
ret
;*********************AREF
adc_ref_extern: ;extern on
ldi temp0,(0<<REFS1|0<<REFS0) ;AREF, Internal Vref turned off
sts admux,temp0
ret
adc_ref_5V: ;AREF 5V
ldi temp0,(0<<REFS1|1<<REFS0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
/*
adc_ref_reserve: ;reserve
in temp0,admux
ori temp0,(1<<REFS1|0<<REFS0) ;RESERVED
out admux,temp0
ret
*/
adc_ref_11V: ;1,1V on
ldi temp0,(1<<REFS1|1<<REFS0) ;internal 1,1V AREF pin
sts admux,temp0
ret
;mit Interrupt
start_convers_int:
lds temp0,adcsra ;wenn ADFR aktiv dann nur adc_read nötig für jeweiligen kanal
ori temp0,(0<<ADEN|1<<ADSC|0<<ADATE/*|ADIF*/|1<<ADIE|1<<ADPS2|0<<ADPS1|0<<ADPS0) ;freigabe ADC Abtastrate zwischen 50Khz-200Khz Teiler=32 single mode
sts adcsra,temp0 ;
sei
ret
;ohne Interrupt dann abfrage auf des bits ADSC=1?????
start_convers:
cli
lds temp0,ADCSRA
ori temp0,(0<<ADEN|1<<ADSC|0<<ADATE/*|ADIF*/|0<<ADIE|1<<ADPS2|0<<ADPS1|1<<ADPS0);freigabe der Messung
sts adcsra,temp0
start_convers2:
lds temp0,ADCSRA ;;;
sbrc temp0,ADSC ;;;;;; diese kleine routine braucht man nicht wenn man mit ints arbeitet
rjmp start_convers2 ;;;
rcall adc_chan_gnd
lds temp0,adcl ;wichtig erst low
lds temp1,adch ;dann high lesen sonst erg müll
sts hadc,temp1
sts ladc,temp0
sei
ret
;*******************Channels********************** ************************************************** **************
adc_chan_0:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|0<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_1:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|0<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_2:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|1<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_3:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|0<<MUX2|1<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_4:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|0<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_5:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|0<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_6:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|1<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_7:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|0<<MUX3|1<<MUX2|1<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_8:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|1<<MUX3|0<<MUX2|0<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_BG:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|1<<MUX3|1<<MUX2|1<<MUX1|0<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
adc_chan_gnd:
lds temp0,ADMUX
andi temp0,$F0
ori temp0,(0<<ADLAR|1<<MUX3|1<<MUX2|1<<MUX1|1<<MUX0) ;AVCC with external capacitor at AREF pin
sts admux,temp0
ret
;**************U-Ref laden***********************************
ref_5v: ldi temp1,high(ref5)
ldi temp0,low(ref5)
ret
ref_52v:ldi temp1,high(ref52)
ldi temp0,low(ref52)
ret
ref_256v:
ldi temp1,high(ref256)
ldi temp0,low(ref256)
ret
ref_2562v:
ldi temp1,high(ref2562)
ldi temp0,low(ref2562)
ret
;******************************adc_interrupt****** ****************
INT_ADC:
lds temp0,adcl ;wichtig erst low
sts ladc,temp0
lds temp1,adch ;dann high lesen sonst erg müll
sts hadc,temp1
reti
.include "AtMega328_analogcomparator.asm"
;ACHTUNG man kann im simulator nicht mit PD6/7 simulieren geht nur
;wenn ACO händisch gesetzt wird ACO=1 wird auch ACI=1 um den int zu nutzen
;wenn man den int nicht nutzt ist die abfrage auf ACO
AC_init:lds temp0,ADCSRB
ori temp0,(0<<ACME)
sts ADCSRB,temp0
ldi temp0,(0<<ACD|0<<ACBG|1<<ACIE|0<<ACIC|0<<ACIS1|0<<ACIS0)
out ACSR,temp0
sei ;
ret
;AUSWAHL neagtiver Input vom ADC
AC_negative_AC0:
rcall AC_negative_IN_init
rcall adc_chan_0
ret
AC_negative_AC1:
rcall AC_negative_IN_init
rcall adc_chan_1
ret
AC_negative_AC2:
rcall AC_negative_IN_init
rcall adc_chan_2
ret
AC_negative_AC3:
rcall AC_negative_IN_init
rcall adc_chan_3
ret
AC_negative_AC4:
rcall AC_negative_IN_init
rcall adc_chan_4
ret
AC_negative_AC5:
rcall AC_negative_IN_init
rcall adc_chan_5
ret
AC_negative_AC6:
rcall AC_negative_IN_init
rcall adc_chan_6
ret
AC_negative_AC7:
rcall AC_negative_IN_init
rcall adc_chan_7
ret
AC_negative_IN_init:
ldi temp0,(1<<ACME)
sts ADCSRB,temp0
ldi temp0,(0<<ADEN)
sts ADCSRA,temp0
ret
ac_change:
in temp0,ACSR
sbrs temp0,ACO
rjmp ac_change
ret
INT_ANALOG_COMP:
;wird aufgerufen wenn pd6+/pd7- pegelunterschiede feststellen
reti
.include "AtMega328_ext_ints.asm"
;PD2/3 sind INT0/1
INIT_EXT_INT01:
lds temp0,EICRA
ori temp0,(1<<ISC11|1<<ISC10|1<<ISC01|1<<ISC00) ;hier INT0/1 auf steigende flanke siehe PDF KAP.13
sts EICRA,temp0
in temp0,EIMSK
ori temp0,(1<<INT1|1<<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
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
.include "AtMega328_eeprom.asm"
;*************************************
eeprom_init:
ldi temp0,(1<<EERIE)
out EECR,temp0
sei
ret
eeprom_rdy:
;siehe eeprom_write ;** man kann in der wartezeit andere sachen erledigen
;bis der int kommt, um dann weitere daten an den eeprom zum schreiben zu senden
;nur bei eeprom schreiben möglich
reti
;Adreessierung im eeprom
adr_cnt:ldi r25,high(EEPROMEND+1)
ldi r24,low(EEPROMEND+1)
lds yh,eep_adrh
lds yl,eep_adrl
adiw yh:yl,$01
cp yl,r24
cpc yh,r25
breq adr_cnt_eeprom_end
sts eep_adrl,yl
sts eep_adrh,yh
ret
adr_cnt_eeprom_end:
ret
EEPROM_write:
sbic EECR,EEPE ;** falls eewe im eecr noch gesetzt
rjmp EEPROM_write ;** spring zu zurück
lds r18,eep_adrh
lds r17,eep_adrl
out EEARH, r18 ;highbyte der adr
out EEARL,r17 ;lowbyte der adr
out EEDR,r16 ;zu speichernder wert
sbi EECR,EEMPE ;sperrt eeprom master write enable
sbi EECR,EEPE ;setze EEWE um eeprom zu schreiben
ret
EEPROM_read:
sbic EECR,EEPE ;falls eewe im eecr noch gesetzt
rjmp EEPROM_read ;springe zurück
lds r18,eep_adrh
lds r17,eep_adrl
out EEARH, r18 ;highbyte der adr
out EEARL, r17 ;lowbyte der adr
sbi EECR,EERE ;sperrt lesen des eeproms
in r16,EEDR ;zu lesender wert
ret
- - - Aktualisiert - - -
.include "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 NUR ein OCR nutzbar A oder B ausser
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,(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|0<<WGM00)
out TCCR0A,temp0
lds temp1,TIMSK0
ori temp1,(1<<OCIE0B | 1<<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,$50 ;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,$25 ;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
Fortsetzung folgt