⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.asm

📁 实现对ADE7759电能芯片的读写和校准,AVR单片机源码与电路图,单相电能表读写程序和初始化程序
💻 ASM
字号:
;==============================================================================
;  Procedury inicjalizacyjne
;  Projekt:	Miernik energii i mocy na ADE7759
;==============================================================================

.cseg
;------------------------------------------------------------------------------
USTAW_MEGA16:
.def	ee_adr	=r18
.def	ee_dane	=r19

	; konfig portow (tylko niektorych - reszta gdzie indziej)
	clr	temp
	out	DDRA, temp		; na wszelki wypadek (porty jako wejscie)
	out	DDRB, temp
	out	DDRC, temp
	out	DDRD, temp
	; portA -> ustawiany w lcd8.asm
	; portB -> pb7-pb4 : SPI
	ldi	temp, (1<<PB3) | (1<<PB2)	; pull-up
	out	PORTB, temp
	; portC -> pc1, pc0 : TWI; reszta to klawisze
	; portD -> pd7, pd5, pd4 : lcd8.asm; pd3 : klawisze; pd1, pd0 : UART
	clr	temp
	out	PORTD, temp

	; ustawienie niektorych rejestrow
	; wylaczenie JTAG:
	ldi	temp, 1<<JTD
	out	MCUCSR, temp
	out	MCUCSR, temp
	; wylaczenie komparatora:
	ldi	temp, 1<<ACD
	out	ACSR, temp
	; inne:
	clr	temp
	out	SFIOR, temp
	out	ADCSRA, temp
	; przerwanie INT0
	in	temp, MCUCR
	sbr	temp, (1<<ISC01) | (1<<ISC00)	; narastajace zbocze
	out	MCUCR, temp

	; przepisuje konfiguracje z EEPROM:(EEPROM) do RAM:(RAM)
	; wykorzystuje rejestr Y
	clr	yh
	out	EEARH, yh
	ldi	yl, RAM		; zmiennych nie moze byc wiecej niz 0xFF-0x68 (0xFF-RAM)
	ldi	ee_adr, EEPROM
ee_nastb:	out	EEARL, ee_adr	; wpisz adres do odczytu bajtu
 	sbi	EECR, EERE		; ustaw znacznik odczytu (procesor czeka 4 cykle na bajt z EE)
	in	ee_dane, EEDR
	st	y+, ee_dane		; przepisz bajt z EE do RAM, oraz zwieksz adres (offset) do RAM
	inc	ee_adr		; zwieksz adres odczytu
	cpi	yl, low(Ds_adr)	; czy koniec danych? (zmienna Ds_adr wskazuje adres zmiennych ulotnych)
	brne	ee_nastb		; nastepny bajt

	; inicjalizacja zmiennych ulotnych
	ldi	zl,  low(Energia1_ses)
	ldi	zh, high(Energia1_ses)
	rcall	CZYSC_ENERG		; czysci od razu energie taryfy2
	clr	temp
	sts	Hist_zera, temp
	sts	Hist_przepel_I, temp
	sts	Hist_przepel_U, temp
	sts	Klaw_dlugo, temp
	sts	Klaw_pusz, temp

	ldi	temp, 1<<ST_M
	sts	Status, temp	; Status wskazuje na moc
	ldi	temp, 1
	sts	Status_M, temp	; moc P
	sts	Status_U, temp	; ...RMS
	sts	Status_I, temp
	sts	Status_E2, temp	; ...energie sesji
	sts	Status_E1, temp	; ...energie sesji

	clr	flagi
	sts	Flagi3, flagi
	sts	Flagi4, flagi
	lds	temp, Flagi2
	lsr	temp		; bit TARYFY do C
	brcc	UM_T0
	sbr	flagi, 1<<fTARYFY	; ustaw licznik dwutaryfowy

UM_T0:	lds	temp, Flagi3
	sbr	temp, 1<<f3EN_RST	; pierwsza probka energii po resecie
	sts	Flagi3, temp

;------------------
	; obliczenie ilosci probek (maks. probek do zebrania -potrzebne dla sygnalow nieokresowych)
	; rejestry: n0, n1, mn0, mn1, kwd3::kwd0
OIP:	push	n0
	push	n1
	push	mn0
	push	mn1
	push	kwd0
	push	kwd1
	push	kwd2
	push	kwd3

	lds	n1, Ade_mode+1
	com	n1		; odwrocenie bitow
	ldi	mn0, 0b00011000	; maska na bity DTRT
	and	n1, mn0
	lsr	n1
	lsr	n1
	lsr	n1		; przesuniecie bitow do LSB
	ldi	mn0, 70		; 3,5kSps /50Hz = 70
	clr	mn1

	tst	n1
	breq	OIP_Z		; n1=0
OIP_J:	lsl	mn0
	rol	mn1		; *2
	dec	n1
	brne	OIP_J

OIP_Z:	lds	n0, Okresy_ile
	inc	n0		; "o dwa okresy wiecej" dla sygnalow nieokresowych
	inc	n0
	clr	n1
	rcall	MUL_16_16		; n1:n0 * mn1:mn0
	sts	Probek_ile, kwd0
	sts	Probek_ile+1, kwd1	; zapis wyniku do RAM
	lsl	mn0
	rol	mn1
	sts	Prb_na_okr_x2, mn0
	sts	Prb_na_okr_x2+1, mn1

	pop	kwd3
	pop	kwd2
	pop	kwd1
	pop	kwd0
	pop	mn1
	pop	mn0
	pop	n1
	pop	n0
	ret

;--------------------------------------
CZYSC_ENERG:	; czysci energie taryfu 1 i 2 --> adres w Z
	push	r18
	clr	temp
	ldi	r18, 14
CE_ZEN:	st	z+, temp
	dec	r18
	brne	CE_ZEN
	pop	r18
	ret


;------------------------------------------------------------------------------
USTAW_KLAWISZE:	; ustawienie klawiszy na dzialanie normalne (pooling T0)
	in	temp, KLAW_PORT-1
	cbr	temp, KLAW_MASKA	; rejestr DDRx wyzerowany - port jako wejscie
	out	KLAW_PORT-1, temp
	in	temp, KLAW_PORT
	sbr	temp, KLAW_MASKA	; rejestr PORTx ustawiony - pull-up na klawiszach
	out	KLAW_PORT, temp
	ret
	

;------------------------------------------------------------------------------
USTAW_ADE7759:	; przesylanie danych do rejestrow ADE7759
	; korzysta z Y, temp, r0, r1
	clr	yh
	ldi	yl, RAM		; wskaznik do zmiennych Ade_

	ldi	temp, ADE_CH1OS_ADR	; zaladuj adres rejestru w ADE
	ld	r0, y+		; Ade_ch1os
	rcall	SPI_ADE_WRITE_1B

	ldi	temp, ADE_CH2OS_ADR
	ld	r0, y+		; Ade_ch2os
	rcall	SPI_ADE_WRITE_1B

	ldi	temp, ADE_GAIN_ADR
	ld	r0, y+		; Ade_gain
	rcall	SPI_ADE_WRITE_1B

	ldi	temp, ADE_APGAIN_ADR
	ld	r0, y+		; Ade_apgain
	ld	r1, y+
	rcall	SPI_ADE_WRITE_2B

	ldi	temp, ADE_PHCAL_ADR
	ld	r0, y+		; Ade_phcal
	rcall	SPI_ADE_WRITE_1B

	ldi	temp, ADE_APOS_ADR
	ld	r0, y+		; Ade_apos
	ld	r1, y+
	rcall	SPI_ADE_WRITE_2B

	ldi	temp, ADE_ZXTOUT_ADR
	ld	r0, y+		; Ade_zxtout
	ld	r1, y+
	rcall	SPI_ADE_WRITE_2B

	ldi	temp, ADE_SAGCYC_ADR
	ld	r0, y+		; Ade_sagcyc
	rcall	SPI_ADE_WRITE_1B

	ldi	temp, ADE_SAGLVL_ADR
	ld	r0, y+		; Ade_saglvl
	rcall	SPI_ADE_WRITE_1B

	ldi	temp, ADE_IRQEN_ADR
	ld	r0, y+		; Ade_irqen
	rcall	SPI_ADE_WRITE_1B

	ldi	temp, ADE_MODE_ADR
	ld	r0, y+		; Ade_mode
	ld	r1, y+
	rcall	SPI_ADE_WRITE_2B

	call	DELAY_44us
	ret



;==============================================================================
USTAW_DS1307_ALL:	; ustawia wszystko - dane ze zmiennych *_bcd
		; wykorzystuje: Z, Y, temp, r0
	ldi	yl,  low(Bufor)
	ldi	yh, high(Bufor)	; adres bufora w Y
	ldi	temp, DS1307_ADRES | TWI_WRITE
	st	Y+, temp		; zapisz adres DS1307 w buforze
	ldi	temp, 1		; adres rejestru w DS1307
	st	y+, temp
	; zawartosc rejestrow...
	ldi	zl,  low(Minuty_bcd)
	ldi	zh, high(Minuty_bcd)
	ld	temp, z+		; minuty
	st	y+, temp
	ld	temp, z+		; godziny
	st	y+, temp
	ld	temp, z+		; dzien tyg.
	st	y+, temp
	ld	temp, z+		; dni
	st	y+, temp
	ld	temp, z+		; miesiace
	st	y+, temp
	ld	temp, z+		; lata
	st	y+, temp
	ldi	temp, 0b10010000	; zawartosc rejestru 7
	st	y+, temp

	ldi	temp, 8
	mov	r0, temp		; licznik ilosci danych do wyslania
	ldi	yl,  low(Bufor)
	ldi	yh, high(Bufor)	; adres bufora w Y
	rcall	TWI_MASTER_WRITE
	call	DELAY_44us		; MUSI byc opoznienie, bo TWI pracuje duzo
				; ...wolniej niz CPU
	; wyslanie sekund i uaktywnienie zegara
	ldi	yl,  low(Bufor)
	ldi	yh, high(Bufor)	; adres bufora w Y
	ldi	temp, DS1307_ADRES | TWI_WRITE
	st	Y, temp		; zapisz adres DS1307 w buforze
	ldi	temp, 0		; adres rejestru w DS1307
	std	y+1, temp
	ldi	temp, 0		; sekundy
	std	y+2, temp
	ldi	temp, 2
	mov	r0, temp		; licznik ilosci danych do wyslania
	rcall	TWI_MASTER_WRITE

	rcall	SPRAWDZ_TARYFE
	ret

;--------------------------------------
;USTAW_DS1307_R7:	; ustawia tylko rejestr 7 (przy starcie, tak na wszelki wypadek)
;		; inne rejestry ustawia sie z menu
;	ldi	yl,  low(Bufor)
;	ldi	yh, high(Bufor)	; adres bufora w Y
;	ldi	temp, DS1307_ADRES | TWI_WRITE
;	st	Y, temp		; zapisz adres DS1307 w buforze
;	ldi	temp, 7		; adres rejestru w DS1307
;	std	y+1, temp
;	ldi	temp, 0b10010000	; zawartosc rejestru
;	std	y+2, temp
;	ldi	temp, 2
;	mov	r0, temp		; licznik ilosci danych do wyslania
;	rcall	TWI_MASTER_WRITE
;	ret


;------------------------------------------------------------------------------
CZYTAJ_DS1307:	; czyta rejestry czasowe z DS1307
		; najpierw ustawienie rejestru 0 w DS1307
	ldi	yl,  low(Bufor)
	ldi	yh, high(Bufor)	; adres bufora w Y
	ldi	temp, DS1307_ADRES | TWI_WRITE
	st	Y, temp		; zapisz adres DS1307 w buforze
	ldi	temp, 0		; adres rejestru w DS1307
	std	y+1, temp
	ldi	temp, 1
	mov	r0, temp		; licznik ilosci danych do wyslania
	rcall	TWI_MASTER_WRITE
	call	DELAY_44us		; na wszelki wypadek troche opoznienia
		; r0 -ilosc bajtow do odczytu
		; Y -wskaznik do zmiennych w RAM i [Y] -> adres DS1307
	ldi	yl,  low(Ds_adr)
	ldi	yh, high(Ds_adr)	; adres poczatku zmiennych w Y
	ldi	temp, DS1307_ADRES | TWI_READ
	st	Y, temp		; zapisz adres DS1307 w buforze
	ldi	temp, 7
	mov	r0, temp		; licznik ilosci danych do odczytu
	rcall	TWI_MASTER_READ

	; konwersja sekund_bcd na sekundy_bin
	push	bcd0		; ochrona rejestrow
	push	bin0
	lds	bcd0, Sekundy_bcd
	rcall	BCD_8_BIN
	sts	Sekundy_bin, bin0
	pop	bin0
	pop	bcd0
	ret

;------------------------------------------------------------------------------
CZYT_EN_DS1307:	; czyta rejestry energii z DS1307
		; najpierw ustawienie rejestru 0 w DS1307
	ldi	yl,  low(Bufor)
	ldi	yh, high(Bufor)	; adres bufora w Y
	ldi	temp, DS1307_ADRES | TWI_WRITE
	st	Y, temp		; zapisz adres DS1307 w buforze
	ldi	temp, 8		; adres rejestru w DS1307
	std	y+1, temp
	ldi	temp, 1
	mov	r0, temp		; licznik ilosci danych do wyslania
	rcall	TWI_MASTER_WRITE
	call	DELAY_44us		; na wszelki wypadek troche opoznienia
		; r0 -ilosc bajtow do odczytu
		; Y -wskaznik do zmiennych w RAM i [Y] -> adres DS1307
	ldi	yl,  low(Energia1-1)
	ldi	yh, high(Energia1-1)
	ld	temp, y
	push	temp		; ochrona zmiennej w RAM przed Energia1

	ldi	temp, DS1307_ADRES | TWI_READ
	st	Y, temp		; zapisz adres DS1307 w buforze
	ldi	temp, ILE_BAJT_EN
	mov	r0, temp		; licznik ilosci danych do odczytu
	rcall	TWI_MASTER_READ

	ldi	yl,  low(Energia1-1)
	ldi	yh, high(Energia1-1)
	pop	r0
	st	y, r0
CEDS_OK:	ret



;==============================================================================
INICJUJ_EEPROM:	; sprawdza czy EEPROM nie jest pusty (po programowaniu)
		; a jesli jest, to programuje go wartosciami domyslnymi
		; wykorzystuje rejestr Y (EE) i Z (Flash), ee_dane, ee_adr, temp, r0, r1
	cbr	flagi, 1<<fINT2
	
	clr	yh
	out	EEARH, yh
	ldi	yl, 4		; testowana komorka pamieci
	out	EEARL, yl
 	sbi	EECR, EERE		; ustaw znacznik odczytu
	in	ee_dane, EEDR
	cpi	ee_dane, 74		; testowana wartosc: <>74 -brak EE
	breq	IEE_RET		; =74 --> EEPROM poprawny

IEE_IEE:	ldi	zl,  low(2*EE_ADE_ini)
	ldi	zh, high(2*EE_ADE_ini)	; adres danych do zapisania
	ldi	temp,  low(2*EE_KON)
	mov	r0, temp
	ldi	temp, high(2*EE_KON)
	mov	r1, temp		; adres koncowy danych
	clr	yh
	out	EEARH, yh
	ldi	ee_adr, EEPROM	; adres poczatkowy w EEPROM

IEE_1:	lpm	ee_dane, z+		; pobierz bajt z Flash
	rcall	EE_ZAPIS		; i zapisz w EE
	inc	ee_adr
	cp	zl, r0
	cpc	zh, r1		; porownanie czy koniec danych
	brlo	IEE_1		; jesli < to nastepny bajt

IEE_GOT:	ldi	ee_adr, 4		; testowana komorka pamieci
	ldi	ee_dane, 74		; testowana wartosc (EEPROM poprawny)
	rcall	EE_ZAPIS

IEE_RET:	ret



;--------------------------------------
EE_ZAPIS:	; tylko pierwsze 256 bajtow! (nie obsluguje EEADRH)
	sbic	EECR, EEWE		; czekaj na ewentualny koniec zapisu lub odczytu EE
	rjmp	EE_ZAPIS
	out	EEARL, ee_adr	; wpisz adres komorki EE
	out	EEDR, ee_dane	; wpisz dane do zapisu
	sbi	EECR, EEMWE		; ustaw pierwszy znacznik zapisu
	sbi	EECR, EEWE		; ustaw drugi znacznik zapisu
	ret	; po dwoch cyklach oczekiwania praca procesora jest kontynuowana
		; a "w tle" jest wykonywany zapis bajtu w EEPROM


.exit
;------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -