$modxx51 ;pracuje minimalne do 12MHz ;jednotlive funkce jsou popsany nize ;vyzaduje promennou v RAM o velikosti 2B pojmenovanou LCDstack ;vyzaduje definovani vyvodu SDA a SCL pro I2C sbernici ;EEPROM SDA equ P3.0 SCL equ P3.1 ;LCD E equ P3.2 RS equ P3.3 CS1 equ P3.4 CS2 equ P3.5 RW equ P3.7 ;data equ P1 dseg At 30h LCDstack: ds 2 ;promenna pro informace o radku a sloupci cseg ;ukazka pouziti acall LCDinit ;vypis vsech znaku sady mov R7,#30 ;od ASCII znaku 30 mov R6,#168 ;8*21=168 znaku PisDalsi: mov a,R7 acall LCDwriteChar inc R7 djnz R6,PisDalsi mov R2,#15 ;4s pauza acall Delay1 acall LCDclearAll ;smaz LCD mov dptr,#Line1 ;1. text acall LCDwrString mov dptr,#Line2 ;2. text acall LCDwrString mov dptr,#Line3 ;3. text acall LCDwrString mov a,#4 acall LCDsetLine ;na 5.radek mov dptr,#Line4 ;4, text acall LCDwrString mov dptr,#Line5 ;5. text acall LCDwrString mov dptr,#Line6 ;6. text acall LCDwrString jmp $ ;tex pro LCD (cisla v textu jsou ceske znaky) Line1: db 21,'Znakov',134,' sada pro LCD ' Line2: db 21,' ATM12864 s ',131,'adi',130,'em ' Line3: db 18,' KS0108 (S6B0108)' Line4: db 21,'(c) Stanislav Ma',129,'l',134,139,' ' Line5: db 21,' S.maslan@seznam.cz ' Line6: db 15,' 27.12.2004' ;zpozdeni R2*(asi 132000) SC (neni soucasti knihovny - jen pro ukazku pouziti) Delay1: mov R1,#0 mov R0,#0 djnz R0,$ djnz R1,$-4 djnz R2,Delay1 ret ;inicializace LCD; pozice na 0,0 (meni a,b,R0) ;musi se volat poprve pred praci s ostatnimi LCDinit: clr E setb RW clr RS CekejNaReset: nop setb E nop mov a,P1 clr E jb acc.4,CekejNaReset jb acc.7,CekejNaReset clr RW mov a,#00111111b ;zapnout LCD acall PosliInstr mov a,#11000000b ;posuv na 0 acall PosliInstr acall LCDclearAll ;smazat LCD ret ;smaze aktualni radek (meni a,b) a nastavi pozici na zacatek radku LCDclearLine: setb CS1 setb CS2 mov a,#01000000b acall PosliInstr mov b,#64 clr a LCDclrLn: acall PosliData djnz b,LCDclrLn mov LCDstack+1,#0 ret ;smaze cely displej, meni pozici na 0,0 (meni R0,b,a) LCDclearAll: setb CS1 setb CS2 mov R0,#7 LCDnLine: mov a,#10111000b orl a,R0 acall PosliInstr acall LCDclearLine dec R0 cjne R0,#255,LCDnLine mov LCDstack,#0 ret ;nastavi radek podle A v rozmezi 0-7 a vrati se na zacatek radku (meni a,b) LCDsetLine: setb CS1 setb CS2 mov LCDstack,a mov LCDstack+1,#0 orl a,#10111000b acall PosliInstr mov a,#01000000b acall PosliInstr ret ;nastavi pozici kurzoru podle A v rozsahu 0-20 (meni a,b) LCDsetPos: mov b,#6 mul ab mov LCDstack+1,a clr CS2 setb CS1 jnb acc.6,LCDsPok setb CS2 clr CS1 LCDsPok: anl a,#00111111b orl a,#01000000b acall PosliInstr cpl CS1 cpl CS2 mov a,#01000000b acall PosliInstr ret ;vypise retezec z tabulky na kterou ukazuje dptr, ;ktery musi zacinat poctem znaku retezce (napr.: db 4,'Text') ;(meni a,b,f0,R0,R1,R2,dptr) LCDwrString: clr a movc a,@a+dptr mov R2,a LCDwrStr: clr a inc dptr movc a,@a+dptr acall LCDwriteChar djnz R2,LCDwrStr ret ;napise znak obsazeny v A na LCD, inkrementuje pozici (meni a,b,f0,R0,R1) LCDwriteChar: mov b,#5 mul ab push acc clr f0 ; mov R1,#0 acall I2Cstart mov a,b rl a anl a,#00001110b orl a,#10100000b acall I2Cposilej pop acc acall I2Cposilej acall I2Cstart mov a,#10100001b acall I2Cposilej ReadEEch: mov a,LCDstack+1 setb CS1 clr CS2 jnb acc.6,CSxOk setb CS2 clr CS1 CSxOk: acall I2Ccti acall PosliData ;data byte do LCD inc LCDstack+1 inc R1 cjne R1,#4,ReadEEchN setb f0 ReadEEchN: cjne R1,#5,ReadEEch acall I2Cstop mov a,#0 acall PosliData ;mezera mezi znaky inc LCDstack+1 ; setb CS1 setb CS2 mov a,LCDstack+1 cjne a,#126,LCDchIncOk mov LCDstack+1,#0 mov a,#01000000b acall PosliInstr inc LCDstack mov a,LCDstack cjne a,#8,LCDlnIncOk mov a,#0 LCDlnIncOk: orl a,#10111000b acall PosliInstr LCDchIncOk: ret ;posle instrukci na LCD PosliInstr: clr RS mov P1,a nop setb E nop clr E ;cekat na busy=0 mov P1,#255 setb RW PosliInstrB: nop setb E nop mov a,P1 clr E jb acc.7,PosliInstrB clr RW ret ;posle data byte na LCD PosliData: setb RS mov P1,a nop setb E nop clr E ret ;tu je vse se sbernici I2C ;!!! oproti verzi, kterou pouzivam v ostatnich konstrukcich se ;pri cteni nahrava do ACK bit f0 - vyzaduje to EEPROM pri sekvencnim ;cteni, pro cteni 1 bytu musi byt f0 nastaven na 1 !!! ;zpozdeni pro I2C DelS: nop nop ret ;I2C start I2CStart: setb SDA setb SCL call DelS clr SDA call DelS clr SCL call DelS ret ;I2C stop I2CStop: setb SCL call DelS setb SDA call DelS ret ;cteni bytu z I2C do a I2CCti: mov R0,#8 setb SDA call DelS Cti1: setb SCL call DelS mov c,SDA clr SCL call DelS rlc a djnz R0,Cti1 ;ACK mov c,f0 mov SDA,c call DelS setb SCL call DelS clr SCL call DelS clr SDA call DelS ret ;posilani bytu z a na sbernici I2C I2CPosilej: mov R0,#8 Posilej1: rlc a mov SDA,c call DelS setb SCL call DelS clr SCL call DelS djnz R0,Posilej1 ;do c nacti ACK setb SDA call DelS setb SCL call DelS mov c,SDA clr SCL call DelS clr SDA ret end