PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ASM LCD-Seriel ATMega8



avr_racer
30.01.2015, 17:55
Seit gegrüßt Bastler,

heute mal eine Ansteuerung eines Standard-LCD (HD44780) mit einem 74HC164 in 8Bit-Form.
Ist nix neues wurde auch hier schon mit einem 74hc595 durchgeführt.

Änderung in der HEX_DEZ_Wandlung.asm wurden die Abholpunkte hinzugefügt das diese nicht ständig geändert werden müssen und somit nur in der Zahlenausgabe von 10 bis 2stellig leider noch ohne Führungsnullunterdrückung.... vielleicht kommts noch.....

Änderung LCD_Routine Zahlenausgabe entweder komplett oder aber mit dem Befehl SET so das hier nur entsprechende Stellen ausgegeben werden SIEHE start Makierung ROT

Alle andere Funktionen bleiben wie gehabt und werden nicht beeinflusst

Aber genug der Labberei hier die Infos:

origin.asm



;###########################################
;# Projekt: LCD 8bit seriel #
;# #
;# #
;# Taktfrequenz des AVR: 4 MHz #
;# #
;# CS-SOFT #
;###########################################

.include "m8def.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

;**********LCD Port mit 74HC164
.equ port_lcd_x = portc
.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 ;;;

;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
;**********SRAM
.equ erg_k = $0060 ;erg_k wird bis zu 5 weiteren bytes genutzt sprich erg_k+5
.equ ocr2s = $0065 ;für T2
.equ ocra1h = $0066 ;;;;;
.equ ocra1l = $0067 ;;;;;;;; für T1 A channel
.equ ocrb1h = $0068 ;;;;;
.equ ocrb1l = $0069 ;;;;;;;; für T1 B channel
.equ icr1xh = $006a ;;;;;
.equ icr1xl = $006b ;;;;;;;; für T1 ICR
.equ hadc = $006c ;adc
.equ ladc = $006d ;adc
.equ eep_adrh = $006e ;eeprom
.equ eep_adrl = $006f ;eeprom
.equ LTC_wertH = $0070
.equ LTC_wertL = $0071
.equ Poti0 = $0072 ;Potentiometer 0
.equ ploudr = $0073 ;poti für lautstärke rechts
.equ ploudl = $0074 ;poti für lautstärke links
.equ phigh = $0075 ;poti für höhen
.equ pbass = $0076 ;poti für bass
.equ halbeh = $0077 ;
.equ halbel = $0078

;***************************Einsprungadressen***** ******************
.cseg
.org $0000
rjmp stack
.org $0001 ;1
reti;rjmp INT_0
.org $0002 ;2
reti;rjmp INT_1
.org $0003 ;3
reti;rjmp INT_OC2
.org $0004 ;4
reti;rjmp INT_OVF2
.org $0005 ;5
reti;rjmp INT_ICP1
.org $0006 ;6
reti;rjmp INT_OC1A
.org $0007 ;7
reti;rjmp INT_OC1B
.org $0008 ;8
reti;rjmp INT_OVF1
.org $0009 ;9
reti; rjmp INT_OVF0
reti ;a keine SPI Routinen
.org $000b ;b
reti;rjmp INT_URXC
.org $000c ;c
reti;rjmp INT_UDRE
.org $000d ;d
reti;rjmp INT_UTXC
.org $000e ;e
reti;rjmp adc_rdy
.org $000f ;f
reti;rjmp eeprom_rdy
.org $0010 ;10
reti;rjmp ac_int
reti ;11 keine 2wireRoutinen
reti ;12 keine SPMRoutinen
.org $001c
reti;rjmp OC0A_int

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

rcall lcd_init
rcall lcd_clear
rcall werbe1
rcall werbe2

start: lds mathergll,ladc
inc mathergll
sts ladc,mathergll

rcall wert_out
rcall wait1s
rcall wert_out_all ;Augabe aller Dezimalstellen ohne Punkt ab tr xy zw de
rcall wait1s
rcall wert_out_4 ;Ausgabe Vorkommastellen und aller Nachkommastellen mit Punkt tr.xy zw de
rcall wait1s
rcall wert_out_4_2 ;Ausgabe Vorkommastellen und einiger Nachkommastellen mit Punkt tr.xy zw
rcall wait1s
rcall wert_out_2 ;Ausgabe der letzten 4 Dezimalstellen mit Punkt dazwischen zw.de

rjmp start

;**********************Masterclr****************** *********************
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,$a0 ;bis zur zelle x=$a0 löschen
brne sram2
ret

;*************************weitere*includedata***** ******************
.include "hex_dez_wandlung.asm"
.include "lcd_KS0066_KS0070_8bit.asm"
.include "zeitschleifen.asm"
.include "DbTxt_LCD.asm"
;*************************ENDE******************** ******************


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Änderung load_hex_dez kann jetzt mit nur hex_dez aufgerufen werden.
Schnittstelle bleibt matherghh:hl:l:ll in die die zu wandelnde Werte, zu laden sind.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
hex_dez_wandlung.asm


;*************************AUSGBAE zahlen******************************** neu
;*******************Welche/Wieviele Stellen ausgegeben werden sollen
load_Y_ergk: ;Ausgabe 1Mrd / 100Mio
ldi yh,high(erg_k)
ldi yl,low(erg_k) ;speicherpunkt laden
ret

load_Y_ergk1: ;Ausgabe 10Mio / 1Mio
ldi yh,high(erg_k+1)
ldi yl,low(erg_k+1) ;speicherpunkt laden
ret

load_Y_ergk2: ;Ausgabe 100 000 / 10 000
ldi yh,high(erg_k+2)
ldi yl,low(erg_k+2) ;speicherpunkt laden
ret

load_Y_ergk3: ;Ausgabe 1000 / 100
ldi yh,high(erg_k+3)
ldi yl,low(erg_k+3) ;speicherpunkt laden
ret

load_Y_ergk4: ;Ausgabe 10 / 1
ldi yh,high(erg_k+4)
ldi yl,low(erg_k+4) ;speicherpunkt laden
ret

;**********Wandlungsvorbereitung von HEX in DEZ******
hex_dez:push xl
push xh
push zl
push zh
mov zh,matherghh ;highhigh ;wenn ZH=ff>>LCD=4294967295
mov zl,mathergh ;highlow ;wenn ZL=ff>>LCD=16777215 bei ZH=0
mov xh,mathergl ;high ;wenn XH=ff>>LCD=65535 bei ZH:ZL=0
mov xl,mathergll ;low ;wenn xl=ff>>LCD=255 bei XH=0
push yl
push yh
rcall load_Y_ergk ;Speicherbereich laden
ldi cnt,$ff ;
num_1000000000: ;Milliarden
inc cnt
subi xh, byte2(1000000000)
sbci zl, byte3(1000000000)
sbci zh, byte4(1000000000)
brcc num_1000000000
swap cnt
st y,cnt
ldi cnt,$0a
num_100000000: ;100Millionen
dec cnt ;+1
subi xh, byte2(-100000000)
sbci zl, byte3(-100000000)
sbci zh, byte4(-100000000)
brcs num_100000000 ;ja
ld temp0,y
or cnt,temp0
st y+,cnt ;fertig speichern
ldi cnt,$ff ;
num_10000000: ;10Millionen
inc cnt
subi xl, byte1(10000000)
sbci xh, byte2(10000000)
sbci zl, byte3(10000000)
sbci zh, 0
brcc num_10000000
swap cnt
st y,cnt
ldi cnt,$0a
num_1000000: ;1Million
dec cnt ;+1
subi xl, byte1(-1000000) ;
sbci xh, byte2(-1000000) ;vergleich auf >1000000
sbci zl, byte3(-1000000)
brcs num_1000000 ;ja
ld temp0,y
or cnt,temp0
st y+,cnt ;fertig speichernn
ldi cnt,$ff ;
num_100000: ;100Tausend
inc cnt
subi xl, byte1(100000)
sbci xh, byte2(100000)
sbci zl, byte3(100000)
brcc num_100000
swap cnt
st y,cnt
ldi cnt,$0a
num_10000: ;10Tausend
dec cnt ;+1
subi xl, byte1(-10000) ;
sbci xh, byte2(-10000) ;vergleich auf >10000
sbci zl, byte3(-10000)
brcs num_10000 ;ja
ld temp0,y
or cnt,temp0
st y+,cnt ;fertig speichern
ldi cnt,$ff
num_1000: ;Tausender
inc cnt
subi xl, low(1000)
sbci xh, high(1000)
brcc num_1000
swap cnt
st y,cnt
ldi cnt,$0a
num_100:dec cnt ;100
subi xl, low(-100)
sbci xh, high(-100)
brcs num_100
ld temp0,y
or cnt,temp0
st y+,cnt
ldi cnt,$ff
num_10: inc cnt ;Zehner + Einer
subi xl, 10
brcc num_10
subi xl, -10
swap cnt
or cnt,xl
st y+,cnt
pop yh
pop yl
pop zh
pop zl
pop xh
pop xl
ret


lcd_KS0066_KS0070_8bit.asm


;******************************Header
/*;das ist die Testbelegung für sriell über 74hc164 zu 8bit
.equ erg_k = $0060 ;zahlenspeicher für ausgabe
; 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 ;;;

;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
*/
;*************************LCDinit***************** *********************
lcd_init:
; rcall reset_chip ;wenn reset-pin getriggert wird
sbi Port_lcd_x,SRS
ldi temp0,(1<<SData|1<<Light|1<<SEnable)
out ddrx_lcd_x,temp0

ldi temp0,$14 ;32ms warten
rcall waitxms

; rcall lcd_function_set_ext ;LCD mit Kontrastumschaltung und anderen Features
rcall lcd_function_set_std ;Standard LCD
rcall lcd_on ;LCD an
rcall entry_mode_std ;Haupteinstellungen
ret

lcd_clear:
ldi temp1,0b00000001
rcall lcd_command
ldi temp0,$14
rcall waitxms
ret

lcd_DDR_AdrX:
;ldi temp1,0b1xxxxxxx ;1 Signalisiert das es DisplayDaten sind und in den
rcall lcd_command ;DisplayDatenRam DDRam geschrieben werden für die Anzeige
rcall wait50us ;auf dem Display xxx= ist die Adresse
ret

;********Funktion Set für Displays MIT RE-Bit *****************************
lcd_function_set_ext:
ldi temp1,0b00100100 ;funktionset nur für LCD mit RE-Bit
rcall lcd_command ;DatenLine1=8bit, RE=1 (für Unterfunktionen an)
rcall wait50us

ldi temp1,0b00001001 ;funktionset nur für ReversDisplay
rcall lcd_command ;DatenLine1=8bit, N=1 4zeilig,
rcall wait50us

ldi temp1,0b00100000 ;funktionset nur für ReversDisplay
rcall lcd_command ;DatenLine1=8bit, RE=0 (Unterfuntionen aus) ,
rcall wait50us

ret

lcd_reverse:
ldi temp1,0b00101011 ;funktionset nur für ReversDisplay
rcall lcd_command ;DatenLine1=8bit, N=1 2zeilig á 40 Zeichen d.h. 4zeilig á 20Zeichen
rcall wait50us
ret

;********Funktion Set für Displays OHNE RE-Bit Std-Display*****************
entry_mode_std:
ldi temp1,(1<<HES|1<<ID|0<<SH)
rcall lcd_command
ret

lcd_on: ldi temp1,(1<<HD|1<<D|0<<C|0<<B)
rcall lcd_command
ret

lcd_shift:
ldi temp1,(1<<HS|0<<SC|1<<RL)
rcall lcd_command
ret

lcd_function_set_std:
ldi temp1,(1<<HSF|1<<DL|1<<N|0<<F) ;funktionset
rcall lcd_command ;DatenLine1=8bit, N=1 2zeilig á 40 Zeichen d.h. 4zeilig á 20Zeichen
ret

;**********************command******************** *********************
lcd_command:;SRS-PIN ist immer über int. pullup aktiv muss aber für lcd_cmd gelöscht
mov xl,temp1
rcall data_chip ;RS = 0 weil Commands gesendet werden
cbi port_lcd_x,SRW ;SRW-Pin löschen falls gesetzt
sbi ddrx_lcd_x,SRS ;SRS ddr setzen
cbi port_lcd_x,SRS ;SRS pullup deakt.
rcall lcd_enable
cbi ddrx_lcd_x,SRS ;SRS ddr löschen
sbi port_lcd_x,SRS ;SRS pullup akt.
ret

;**************************data******************* *********************
lcd_data:;SRS-PIN ist immer über int. pullup aktiv, weil wenn hier es erst aktiv wird shiftreg +1 weitershiftet
mov xl,temp1
rcall data_chip ;RS = 1 weil Daten gesendet werden z.B.: 'A'
cbi port_lcd_x,SRW
rcall lcd_enable
ret

;***********************Enable******************** *********************
lcd_enable: ;LCD soll Byte lesen
sbi port_lcd_x,SEnable
rcall wait50us
cbi port_lcd_x,SEnable
ret

;**********************daten seriel übertragen 74164*******************
data_chip:
ldi temp3,$08 ;1Byte = 8Bit
data_chip_2:
sbrc xl,7 ;wenn Bit 7 = 1 dann
sbi port_lcd_x,SData ;den Pin auf 1 setzen
sbrs xl,7 ;wenn Bit 7 = 0 dann
cbi port_lcd_x,SData ;den Pin auf 0 setzen
rcall clock_chip ;74164 Clocken zum shiften
lsl xl ;links shiften Vorbereitung neues Bit
dec temp3
cpi temp3,$00 ;Abbruchbedingung
brne data_chip_2
ret

clock_chip: ;Takt
cbi port_lcd_x,SClock
sbi ddrx_lcd_x,SClock
rcall wait1us
cbi ddrx_lcd_x,SClock
sbi port_lcd_x,SClock
rcall wait50us
ret

/* Falls in HW nicht genutzt wird dann in SW deaktivieren
reset_chip: ;MUSS AUF 1 gesetzt werden damit der Chip
cbi port_lcd_x,Rst ;daten shiftet
rcall wait50us ;Kann auch extern mit einen PullUp am ResetPin
sbi port_lcd_x,Rst ;beschaltet werden
rcall wait50us
ret
*/
;*************************Ausgabe TXT**********************************
txt_out:lpm temp1,z+ ;!!! muss der .db *2 genommen werden
cpi temp1,$ff
breq txt_out_end
rcall lcd_data ;z.b.: ldi ZH,high(out0*2)
rjmp txt_out
txt_out_end:
ret
/*;Nur ein Zeichen Ausgeben falls erforderlich Zeichen in Sram definieren
zeichen_out:
;adr
rcall lcd_clearAX
lds temp1,zeichen ;Zeichen
rcall lcd_data
ret
*/

;**********Ausgabe Zahl Byte als ASCII zu LCD schicken
lcd_zahlout_5:
rcall load_Y_ergk ;Stellenangabe
rjmp lcd_zahlout_X
lcd_zahlout_4:
rcall load_Y_ergk1 ;Stellenangabe
rjmp lcd_zahlout_X
lcd_zahlout_3:
rcall load_Y_ergk2 ;Stellenangabe
rjmp lcd_zahlout_X
lcd_zahlout_2:
rcall load_Y_ergk3 ;Stellenangabe
rjmp lcd_zahlout_X
lcd_zahlout_1:
rcall load_Y_ergk4 ;Stellenangabe
lcd_zahlout_X:
ldi temp3,high(erg_k+5)
ldi temp4,low(erg_k+5)
lcd_zahlout_X_2:
ld temp1,y+ ;DezZahl von RAM holen
mov temp2,temp1 ;copieren

swap temp1 ;Nibbletausch
andi temp1,$0f ;unden
ori temp1,$30 ;Wandlung in ASCII-Zahl
rcall lcd_data ;ab in den Chip

mov temp1,temp2 ;Nibbletausch
andi temp1,$0f ;unden
ori temp1,$30 ;Wandlung in ASCII-Zahl
rcall lcd_data ;ab in den Chip

brts lcd_zahlout_end
cp yl,temp4 ;Abbruchbedingung
brne lcd_zahlout_x_2 ;Sprung zu Label

lcd_zahlout_end:
clt
ret

lcd_licht_an:
sbi Port_lcd_x,light
ret

lcd_licht_aus:
cbi Port_lcd_x,light
ret


DbTxt_LCD.asm


;********************TextAusgabeLCD*************** ******************
werbe1: ldi temp1,0b10000000
rcall lcd_DDR_AdrX
ldi ZH,high(out0*2)
ldi ZL,low(out0*2)
rcall txt_out
ret

werbe2: ldi temp1,0b11000000
rcall lcd_DDR_AdrX
ldi ZH,high(out1*2)
ldi ZL,low(out1*2)
rcall txt_out
ret

wert_out:
ldi temp1,0b11001000
rcall lcd_DDR_AdrX
clr matherghh
clr mathergh
clr mathergl
lds mathergll,ladc
rcall hex_dez ;Wandlung von HEX in DEZ steht dierekt im RAM
rcall lcd_zahlout_1
ret

;TESTANZEIGEN zum auslesen verschiedener Werte
;alles mit * sind Testwerte nur zu Demozwecken
wert_out_all:
ldi temp2,$ff ;*
ldi temp1,$ff ;*
ldi temp0,$ff ;*
clr matherghh ;Schnittstelle
mov mathergh,temp2
mov mathergl,temp1
mov mathergll,temp0 ;Wert laden

rcall hex_dez

ldi temp1,0b11001000
rcall lcd_DDR_AdrX ;ADRx -> LCD

rcall lcd_zahlout_5 ;um hier Abbruch zu schaffen

ldi temp1,'?' ;Masseinheit = ?
rcall lcd_data ;Punkt setzen

ret

wert_out_4:
rcall werbe2 ;2te Zeile überschreiben
ldi temp2,$ff ;*
ldi temp1,$ff ;*
ldi temp0,$ff ;*
clr matherghh
mov mathergh,temp2 ;Schnittstelle
mov mathergl,temp1
mov mathergll,temp0 ;Wert laden

rcall hex_dez

ldi temp1,0b11001000
rcall lcd_DDR_AdrX ;ADRx -> LCD

set ;T-Flag setzen
rcall lcd_zahlout_4 ;um hier Abbruch zu schaffen

ldi temp1,'.' ;
rcall lcd_data ;Punkt setzen

rcall lcd_zahlout_3 ;Nachkommastellausgabe komplett

ldi temp1,'?' ;Masseinheit = ?
rcall lcd_data ;Punkt setzen

ret

wert_out_4_2:
rcall werbe2 ;2te Zeile überschreiben
ldi temp2,$ff ;*
ldi temp1,$ff ;*
ldi temp0,$ff ;*
clr matherghh
mov mathergh,temp2 ;Schnittstelle
mov mathergl,temp1
mov mathergll,temp0 ;Wert laden

rcall hex_dez

ldi temp1,0b11001000
rcall lcd_DDR_AdrX ;ADRx -> LCD

set ;T-Flag setzen
rcall lcd_zahlout_4 ;um hier Abbruch zu schaffen

ldi temp1,'.' ;
rcall lcd_data ;Punkt setzen

set
rcall lcd_zahlout_3 ;nur bestimmte Nachkommastellausgabe

set
rcall lcd_zahlout_2 ;nur bestimmte Nachkommastellausgabe

ldi temp1,'?' ;Masseinheit = ?
rcall lcd_data ;Punkt setzen

ret

wert_out_2:
rcall werbe2
ldi temp1,$03
ldi temp0,$ff
clr matherghh
clr mathergh ;Schnittstelle
mov mathergl,temp1
mov mathergll,temp0 ;Wert laden

rcall hex_dez

ldi temp1,0b11001000
rcall lcd_DDR_AdrX ;ADRx -> LCD

set ;T-Flag setzen
rcall lcd_zahlout_2 ;um hier Abbruch zu schaffen

ldi temp1,'.' ;
rcall lcd_data ;Punkt setzen

rcall lcd_zahlout_1

ldi temp1,'?' ;Masseinheit = ?
rcall lcd_data ;Punkt setzen

ret
;************************direktwandlung*wort*in*AS CII***************
; * + *=16Stellen/+=20stellen
; "0123456789ABCDEF01234"
out0: .db " LCD-Test AVR ",$ff
out1: .db "Zahlen: ",$ff


Die Zeitschleifen ASM kann aus der Atmega8 Bibliothek kopiert werden das sich hier nix geändert hat

hier der Schaltplan

2972029721